Merging from default branch and resolving conflicts. mvn install -DskipTests passes OK. closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 30 Apr 2014 15:04:10 +0200
branchclosure
changeset 1513ba912ef24b27
parent 1508 e995e8d39240
parent 1512 5171ac3b4232
child 1514 d2401e2648af
Merging from default branch and resolving conflicts. mvn install -DskipTests passes OK.
dew/nbactions.xml
dew/pom.xml
dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java
dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java
dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/app.css
dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/bootstrap-combined.min.css
dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/error.png
dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings-white.png
dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings.png
dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/html5.png
dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/java.png
dew/src/main/resources/org/apidesign/bck2brwsr/dew/index.html
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/angular/angular.min.js
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js
dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/theme/elegant.css
dew/src/test/java/org/apidesign/bck2brwsr/dew/CompileTest.java
ide/editor/pom.xml
ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JNIHelper.java
ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSEmbeddingProvider.java
ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBody.java
ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizer.java
ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/ManglingSink.java
ide/editor/src/main/nbm/manifest.mf
ide/editor/src/main/resources/org/netbeans/modules/jackpot30/test/hints/Bundle.properties
ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/DejsniReaderTest.java
ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBodyTest.java
ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizerTest.java
ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/ManglingSinkTest.java
ide/pom.xml
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
javaquery/demo-twitter/bck2brwsr-assembly.xml
javaquery/demo-twitter/nb-configuration.xml
javaquery/demo-twitter/nbactions.xml
javaquery/demo-twitter/pom.xml
javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java
javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html
javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css
javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java
launcher/fx/pom.xml
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXInspect.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java
launcher/http/pom.xml
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java
launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java
pom.xml
rt/archetype/pom.xml
rt/archetype/src/main/java/org/apidesign/bck2brwsr/archetype/package-info.java
rt/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
rt/archetype/src/main/resources/archetype-resources/bck2brwsr-assembly.xml
rt/archetype/src/main/resources/archetype-resources/nbactions.xml
rt/archetype/src/main/resources/archetype-resources/pom.xml
rt/archetype/src/main/resources/archetype-resources/src/main/java/App.java
rt/archetype/src/main/resources/archetype-resources/src/main/resources/index.html
rt/archetype/src/main/resources/archetype-resources/src/test/java/AppTest.java
rt/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java
rt/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java
rt/archetype/src/test/java/org/apidesign/bck2brwsr/archetype/ArchetypeVersionTest.java
rt/emul/brwsrtest/src/test/java/org/apidesign/bck2brwsr/brwsrtest/ResourcesInBrwsrTest.java
rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/NotifyWaitTest.java
rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java
rt/emul/mini/src/main/java/java/lang/Class.java
rt/emul/mini/src/main/java/java/lang/Object.java
rt/emul/mini/src/main/java/java/lang/String.java
rt/emul/mini/src/main/java/java/lang/reflect/Array.java
rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java
rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_String.js
rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java
rt/vm/pom.xml
rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesWithExtensionsTest.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java
     1.1 --- a/.hgtags	Tue Apr 29 15:25:58 2014 +0200
     1.2 +++ b/.hgtags	Wed Apr 30 15:04:10 2014 +0200
     1.3 @@ -10,3 +10,5 @@
     1.4  623816269b75e53fffb4b19960df7040a3c20056 release-0.7
     1.5  23572dc719bd630817d11eaabdee4565f63ef8e1 release-0.7.1
     1.6  56abd247f421febd8b2c5e59d666968692e11555 release-0.7.2
     1.7 +a83e16b8b825399bb21461e578c32d86982e4ed3 release-0.8
     1.8 +1b30bba2b38db83c7a232039cfd2eaf7e0e25f3f release-0.8.1
     2.1 --- a/benchmarks/matrix-multiplication/pom.xml	Tue Apr 29 15:25:58 2014 +0200
     2.2 +++ b/benchmarks/matrix-multiplication/pom.xml	Wed Apr 30 15:04:10 2014 +0200
     2.3 @@ -4,12 +4,12 @@
     2.4  
     2.5    <groupId>org.apidesign.bck2brwsr</groupId>
     2.6    <artifactId>matrix.multiplication</artifactId>
     2.7 -  <version>0.8-SNAPSHOT</version>
     2.8 +  <version>0.9-SNAPSHOT</version>
     2.9    <packaging>jar</packaging>
    2.10    <parent>
    2.11      <artifactId>benchmarks</artifactId>
    2.12      <groupId>org.apidesign.bck2brwsr</groupId>
    2.13 -    <version>0.8-SNAPSHOT</version>
    2.14 +    <version>0.9-SNAPSHOT</version>
    2.15    </parent>
    2.16  
    2.17    <name>Matrix multiplication</name>
    2.18 @@ -74,7 +74,7 @@
    2.19      <dependency>
    2.20        <groupId>org.apidesign.bck2brwsr</groupId>
    2.21        <artifactId>emul.mini</artifactId>
    2.22 -      <version>0.8-SNAPSHOT</version>
    2.23 +      <version>0.9-SNAPSHOT</version>
    2.24      </dependency>
    2.25      <dependency>
    2.26        <groupId>org.testng</groupId>
    2.27 @@ -91,13 +91,13 @@
    2.28      <dependency>
    2.29        <groupId>org.apidesign.bck2brwsr</groupId>
    2.30        <artifactId>vmtest</artifactId>
    2.31 -      <version>0.8-SNAPSHOT</version>
    2.32 +      <version>0.9-SNAPSHOT</version>
    2.33        <scope>test</scope>
    2.34      </dependency>
    2.35      <dependency>
    2.36        <groupId>org.apidesign.bck2brwsr</groupId>
    2.37        <artifactId>launcher.http</artifactId>
    2.38 -      <version>0.8-SNAPSHOT</version>
    2.39 +      <version>0.9-SNAPSHOT</version>
    2.40        <scope>test</scope>
    2.41      </dependency>
    2.42    </dependencies>
     3.1 --- a/benchmarks/pom.xml	Tue Apr 29 15:25:58 2014 +0200
     3.2 +++ b/benchmarks/pom.xml	Wed Apr 30 15:04:10 2014 +0200
     3.3 @@ -4,11 +4,11 @@
     3.4    <parent>
     3.5      <artifactId>bck2brwsr</artifactId>
     3.6      <groupId>org.apidesign</groupId>
     3.7 -    <version>0.8-SNAPSHOT</version>
     3.8 +    <version>0.9-SNAPSHOT</version>
     3.9    </parent>
    3.10    <groupId>org.apidesign.bck2brwsr</groupId>
    3.11    <artifactId>benchmarks</artifactId>
    3.12 -  <version>0.8-SNAPSHOT</version>
    3.13 +  <version>0.9-SNAPSHOT</version>
    3.14    <packaging>pom</packaging>
    3.15    <name>Performance benchmarks</name>
    3.16    <modules>
     4.1 --- a/dew/nbactions.xml	Tue Apr 29 15:25:58 2014 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,52 +0,0 @@
     4.4 -<?xml version="1.0" encoding="UTF-8"?>
     4.5 -<!--
     4.6 -
     4.7 -    Back 2 Browser Bytecode Translator
     4.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.9 -
    4.10 -    This program is free software: you can redistribute it and/or modify
    4.11 -    it under the terms of the GNU General Public License as published by
    4.12 -    the Free Software Foundation, version 2 of the License.
    4.13 -
    4.14 -    This program is distributed in the hope that it will be useful,
    4.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.17 -    GNU General Public License for more details.
    4.18 -
    4.19 -    You should have received a copy of the GNU General Public License
    4.20 -    along with this program. Look for COPYING file in the top folder.
    4.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
    4.22 -
    4.23 --->
    4.24 -<actions>
    4.25 -        <action>
    4.26 -            <actionName>run</actionName>
    4.27 -            <goals>
    4.28 -                <goal>process-classes</goal>
    4.29 -                <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
    4.30 -            </goals>
    4.31 -        </action>
    4.32 -        <action>
    4.33 -            <actionName>debug</actionName>
    4.34 -            <goals>
    4.35 -                <goal>process-classes</goal>
    4.36 -                <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
    4.37 -            </goals>
    4.38 -            <properties>
    4.39 -                <exec.args>-Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath org.apidesign.bck2brwsr.dew.Dew</exec.args>
    4.40 -                <exec.executable>java</exec.executable>
    4.41 -                <jpda.listen>true</jpda.listen>
    4.42 -            </properties>
    4.43 -        </action>
    4.44 -        <action>
    4.45 -            <actionName>profile</actionName>
    4.46 -            <goals>
    4.47 -                <goal>process-classes</goal>
    4.48 -                <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
    4.49 -            </goals>
    4.50 -            <properties>
    4.51 -                <exec.args>${profiler.args} -classpath %classpath org.apidesign.bck2brwsr.dew.Dew</exec.args>
    4.52 -                <exec.executable>${profiler.java}</exec.executable>
    4.53 -            </properties>
    4.54 -        </action>
    4.55 -    </actions>
     5.1 --- a/dew/pom.xml	Tue Apr 29 15:25:58 2014 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,91 +0,0 @@
     5.4 -<?xml version="1.0"?>
     5.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">
     5.6 -  <modelVersion>4.0.0</modelVersion>
     5.7 -  <parent>
     5.8 -    <groupId>org.apidesign</groupId>
     5.9 -    <artifactId>bck2brwsr</artifactId>
    5.10 -    <version>0.8-SNAPSHOT</version>
    5.11 -  </parent>
    5.12 -  <groupId>org.apidesign.bck2brwsr</groupId>
    5.13 -  <artifactId>dew</artifactId>
    5.14 -  <version>0.8-SNAPSHOT</version>
    5.15 -  <name>Development Environment for Web</name>
    5.16 -  <url>http://maven.apache.org</url>
    5.17 -    <build>
    5.18 -        <plugins>
    5.19 -            <plugin>
    5.20 -                <groupId>org.apache.maven.plugins</groupId>
    5.21 -                <artifactId>maven-compiler-plugin</artifactId>
    5.22 -                <version>2.3.2</version>
    5.23 -                <configuration>
    5.24 -                    <source>1.7</source>
    5.25 -                    <target>1.7</target>
    5.26 -                </configuration>
    5.27 -            </plugin>
    5.28 -            <plugin>
    5.29 -                <groupId>org.codehaus.mojo</groupId>
    5.30 -                <artifactId>exec-maven-plugin</artifactId>
    5.31 -                <version>1.2.1</version>
    5.32 -                <executions>
    5.33 -                    <execution>
    5.34 -                        <goals>
    5.35 -                            <goal>exec</goal>
    5.36 -                        </goals>
    5.37 -                    </execution>
    5.38 -                </executions>
    5.39 -                <configuration>
    5.40 -                    <executable>java</executable>
    5.41 -                     <arguments>
    5.42 -                        <argument>-classpath</argument>
    5.43 -                        <classpath />
    5.44 -                        <argument>org.apidesign.bck2brwsr.dew.Dew</argument>
    5.45 -                    </arguments>
    5.46 -                </configuration>
    5.47 -            </plugin>
    5.48 -            <plugin>
    5.49 -                <groupId>org.apache.maven.plugins</groupId>
    5.50 -                <artifactId>maven-deploy-plugin</artifactId>
    5.51 -                <version>2.7</version>
    5.52 -                <configuration>
    5.53 -                    <skip>true</skip>
    5.54 -                </configuration>
    5.55 -            </plugin>      
    5.56 -        </plugins>
    5.57 -    </build>
    5.58 -    <properties>
    5.59 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    5.60 -  </properties>
    5.61 -  <dependencies>
    5.62 -    <dependency>
    5.63 -      <groupId>org.glassfish.grizzly</groupId>
    5.64 -      <artifactId>grizzly-http-server</artifactId>
    5.65 -      <version>2.2.19</version>
    5.66 -    </dependency>
    5.67 -    <dependency>
    5.68 -      <groupId>${project.groupId}</groupId>
    5.69 -      <artifactId>vm4brwsr</artifactId>
    5.70 -      <version>${project.version}</version>
    5.71 -    </dependency>
    5.72 -    <dependency>
    5.73 -      <groupId>org.json</groupId>
    5.74 -      <artifactId>json</artifactId>
    5.75 -      <version>20090211</version>
    5.76 -    </dependency>
    5.77 -    <dependency>
    5.78 -      <groupId>org.testng</groupId>
    5.79 -      <artifactId>testng</artifactId>
    5.80 -      <scope>test</scope>
    5.81 -      <exclusions>
    5.82 -        <exclusion>
    5.83 -          <artifactId>junit</artifactId>
    5.84 -          <groupId>junit</groupId>
    5.85 -        </exclusion>
    5.86 -      </exclusions>
    5.87 -    </dependency>
    5.88 -    <dependency>
    5.89 -      <groupId>${project.groupId}</groupId>
    5.90 -      <artifactId>javaquery.api</artifactId>
    5.91 -      <version>${project.version}</version>
    5.92 -    </dependency>
    5.93 -  </dependencies>
    5.94 -</project>
     6.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java	Tue Apr 29 15:25:58 2014 +0200
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,203 +0,0 @@
     6.4 -/**
     6.5 - * Back 2 Browser Bytecode Translator
     6.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 - *
     6.8 - * This program is free software: you can redistribute it and/or modify
     6.9 - * it under the terms of the GNU General Public License as published by
    6.10 - * the Free Software Foundation, version 2 of the License.
    6.11 - *
    6.12 - * This program is distributed in the hope that it will be useful,
    6.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 - * GNU General Public License for more details.
    6.16 - *
    6.17 - * You should have received a copy of the GNU General Public License
    6.18 - * along with this program. Look for COPYING file in the top folder.
    6.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 - */
    6.21 -package org.apidesign.bck2brwsr.dew;
    6.22 -
    6.23 -import java.io.ByteArrayInputStream;
    6.24 -import java.io.ByteArrayOutputStream;
    6.25 -import java.io.IOException;
    6.26 -import java.io.InputStream;
    6.27 -import java.io.OutputStream;
    6.28 -import java.net.URI;
    6.29 -import java.net.URISyntaxException;
    6.30 -import java.util.ArrayList;
    6.31 -import java.util.Arrays;
    6.32 -import java.util.HashMap;
    6.33 -import java.util.List;
    6.34 -import java.util.Map;
    6.35 -import java.util.regex.Matcher;
    6.36 -import java.util.regex.Pattern;
    6.37 -import javax.tools.Diagnostic;
    6.38 -import javax.tools.DiagnosticListener;
    6.39 -import javax.tools.FileObject;
    6.40 -import javax.tools.ForwardingJavaFileManager;
    6.41 -import javax.tools.JavaFileManager;
    6.42 -import javax.tools.JavaFileObject;
    6.43 -import javax.tools.JavaFileObject.Kind;
    6.44 -import javax.tools.SimpleJavaFileObject;
    6.45 -import javax.tools.StandardJavaFileManager;
    6.46 -import javax.tools.StandardLocation;
    6.47 -import javax.tools.ToolProvider;
    6.48 -
    6.49 -/**
    6.50 - *
    6.51 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.52 - */
    6.53 -final class Compile implements DiagnosticListener<JavaFileObject> {
    6.54 -    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
    6.55 -    private final Map<String, byte[]> classes;
    6.56 -    private final String pkg;
    6.57 -    private final String cls;
    6.58 -    private final String html;
    6.59 -
    6.60 -    private Compile(String html, String code) throws IOException {
    6.61 -        this.pkg = findPkg(code);
    6.62 -        this.cls = findCls(code);
    6.63 -        this.html = html;
    6.64 -        classes = compile(html, code);
    6.65 -    }
    6.66 -
    6.67 -    /** Performs compilation of given HTML page and associated Java code
    6.68 -     */
    6.69 -    public static Compile create(String html, String code) throws IOException {
    6.70 -        return new Compile(html, code);
    6.71 -    }
    6.72 -    
    6.73 -    /** Checks for given class among compiled resources */
    6.74 -    public byte[] get(String res) {
    6.75 -        return classes.get(res);
    6.76 -    }
    6.77 -    
    6.78 -    /** Obtains errors created during compilation.
    6.79 -     */
    6.80 -    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
    6.81 -        List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
    6.82 -        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
    6.83 -            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
    6.84 -                err.add(diagnostic);
    6.85 -            }
    6.86 -        }
    6.87 -        return err;
    6.88 -    }
    6.89 -    
    6.90 -    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
    6.91 -        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
    6.92 -
    6.93 -        final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
    6.94 -
    6.95 -        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
    6.96 -            @Override
    6.97 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    6.98 -                return code;
    6.99 -            }
   6.100 -        };
   6.101 -        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
   6.102 -            @Override
   6.103 -            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   6.104 -                return html;
   6.105 -            }
   6.106 -
   6.107 -            @Override
   6.108 -            public InputStream openInputStream() throws IOException {
   6.109 -                return new ByteArrayInputStream(html.getBytes());
   6.110 -            }
   6.111 -        };
   6.112 -        
   6.113 -        final URI scratch;
   6.114 -        try {
   6.115 -            scratch = new URI("mem://mem3");
   6.116 -        } catch (URISyntaxException ex) {
   6.117 -            throw new IOException(ex);
   6.118 -        }
   6.119 -        
   6.120 -        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
   6.121 -            @Override
   6.122 -            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   6.123 -                if (kind  == Kind.CLASS) {
   6.124 -                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
   6.125 -
   6.126 -                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
   6.127 -                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
   6.128 -                        @Override
   6.129 -                        public OutputStream openOutputStream() throws IOException {
   6.130 -                            return buffer;
   6.131 -                        }
   6.132 -                    };
   6.133 -                }
   6.134 -                
   6.135 -                if (kind == Kind.SOURCE) {
   6.136 -                    return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
   6.137 -                        private final ByteArrayOutputStream data = new ByteArrayOutputStream();
   6.138 -                        @Override
   6.139 -                        public OutputStream openOutputStream() throws IOException {
   6.140 -                            return data;
   6.141 -                        }
   6.142 -
   6.143 -                        @Override
   6.144 -                        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   6.145 -                            data.close();
   6.146 -                            return new String(data.toByteArray());
   6.147 -                        }
   6.148 -                    };
   6.149 -                }
   6.150 -                
   6.151 -                throw new IllegalStateException();
   6.152 -            }
   6.153 -
   6.154 -            @Override
   6.155 -            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   6.156 -                if (location == StandardLocation.SOURCE_PATH) {
   6.157 -                    if (packageName.equals(pkg)) {
   6.158 -                        return htmlFile;
   6.159 -                    }
   6.160 -                }
   6.161 -                
   6.162 -                return null;
   6.163 -            }
   6.164 -            
   6.165 -        };
   6.166 -
   6.167 -        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
   6.168 -
   6.169 -        Map<String, byte[]> result = new HashMap<>();
   6.170 -
   6.171 -        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
   6.172 -            result.put(e.getKey(), e.getValue().toByteArray());
   6.173 -        }
   6.174 -
   6.175 -        return result;
   6.176 -    }
   6.177 -
   6.178 -
   6.179 -    @Override
   6.180 -    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   6.181 -        errors.add(diagnostic);
   6.182 -    }
   6.183 -    private static String findPkg(String java) throws IOException {
   6.184 -        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
   6.185 -        Matcher m = p.matcher(java);
   6.186 -        if (!m.find()) {
   6.187 -            throw new IOException("Can't find package declaration in the java file");
   6.188 -        }
   6.189 -        String pkg = m.group(1);
   6.190 -        return pkg;
   6.191 -    }
   6.192 -    private static String findCls(String java) throws IOException {
   6.193 -        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
   6.194 -        Matcher m = p.matcher(java);
   6.195 -        if (!m.find()) {
   6.196 -            throw new IOException("Can't find package declaration in the java file");
   6.197 -        }
   6.198 -        String cls = m.group(1);
   6.199 -        return cls;
   6.200 -    }
   6.201 -
   6.202 -    String getHtml() {
   6.203 -        String fqn = "'" + pkg + '.' + cls + "'";
   6.204 -        return html.replace("'${fqn}'", fqn);
   6.205 -    }
   6.206 -}
     7.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java	Tue Apr 29 15:25:58 2014 +0200
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,138 +0,0 @@
     7.4 -/**
     7.5 - * Back 2 Browser Bytecode Translator
     7.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 - *
     7.8 - * This program is free software: you can redistribute it and/or modify
     7.9 - * it under the terms of the GNU General Public License as published by
    7.10 - * the Free Software Foundation, version 2 of the License.
    7.11 - *
    7.12 - * This program is distributed in the hope that it will be useful,
    7.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 - * GNU General Public License for more details.
    7.16 - *
    7.17 - * You should have received a copy of the GNU General Public License
    7.18 - * along with this program. Look for COPYING file in the top folder.
    7.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 - */
    7.21 -package org.apidesign.bck2brwsr.dew;
    7.22 -
    7.23 -import java.io.ByteArrayInputStream;
    7.24 -import java.io.IOException;
    7.25 -import java.io.InputStream;
    7.26 -import java.io.InputStreamReader;
    7.27 -import java.io.OutputStream;
    7.28 -import java.util.List;
    7.29 -import java.util.Locale;
    7.30 -import javax.tools.Diagnostic;
    7.31 -import javax.tools.JavaFileObject;
    7.32 -import org.apidesign.vm4brwsr.Bck2Brwsr;
    7.33 -import org.glassfish.grizzly.http.Method;
    7.34 -import org.glassfish.grizzly.http.server.HttpHandler;
    7.35 -import org.glassfish.grizzly.http.server.HttpServer;
    7.36 -import org.glassfish.grizzly.http.server.Request;
    7.37 -import org.glassfish.grizzly.http.server.Response;
    7.38 -import org.glassfish.grizzly.http.util.HttpStatus;
    7.39 -import org.json.JSONArray;
    7.40 -import org.json.JSONObject;
    7.41 -import org.json.JSONTokener;
    7.42 -
    7.43 -/**
    7.44 - *
    7.45 - * @author phrebejk
    7.46 - */
    7.47 -final class Dew extends HttpHandler implements Bck2Brwsr.Resources {
    7.48 -    private Compile data;
    7.49 -
    7.50 -    public static void main(String... args) throws Exception {
    7.51 -        DewLauncher l = new DewLauncher(null);
    7.52 -        l.addClassLoader(DewLauncher.class.getClassLoader());
    7.53 -        final Dew dew = new Dew();
    7.54 -        HttpServer s = l.initServer(dew);
    7.55 -        s.getServerConfiguration().addHttpHandler(dew, "/dew/");
    7.56 -        l.launchServerAndBrwsr(s, "/dew/");
    7.57 -        System.in.read();
    7.58 -    }
    7.59 -    
    7.60 -    @Override
    7.61 -    public void service(Request request, Response response) throws Exception {
    7.62 -        
    7.63 -        if ( request.getMethod() == Method.POST ) {
    7.64 -            InputStream is = request.getInputStream();
    7.65 -            JSONTokener tok = new JSONTokener(new InputStreamReader(is));
    7.66 -            JSONObject obj = new JSONObject(tok);
    7.67 -            String tmpHtml = obj.getString("html");
    7.68 -            String tmpJava = obj.getString("java");
    7.69 -            
    7.70 -            Compile res = Compile.create(tmpHtml, tmpJava);
    7.71 -            List<Diagnostic<? extends JavaFileObject>> err = res.getErrors();
    7.72 -            if (err.isEmpty()) {
    7.73 -                data = res;
    7.74 -                response.getOutputStream().write("[]".getBytes());
    7.75 -                response.setStatus(HttpStatus.OK_200);
    7.76 -            } else {
    7.77 -                
    7.78 -                JSONArray errors = new JSONArray();
    7.79 -                
    7.80 -                for (Diagnostic<? extends JavaFileObject> d : err) {
    7.81 -                    JSONObject e = new JSONObject();
    7.82 -                    e.put("col", d.getColumnNumber());
    7.83 -                    e.put("line", d.getLineNumber());
    7.84 -                    e.put("kind", d.getKind().toString());
    7.85 -                    e.put("msg", d.getMessage(Locale.ENGLISH));
    7.86 -                    errors.put(e);
    7.87 -                }
    7.88 -                
    7.89 -                errors.write(response.getWriter());                
    7.90 -                response.setStatus(HttpStatus.PRECONDITION_FAILED_412);
    7.91 -            }
    7.92 -            
    7.93 -            return;
    7.94 -        }
    7.95 -        
    7.96 -        String r = request.getHttpHandlerPath();
    7.97 -        if (r == null || r.equals("/")) {
    7.98 -            r = "index.html";
    7.99 -        }
   7.100 -        if (r.equals("/result.html")) {
   7.101 -            response.setContentType("text/html");
   7.102 -            if (data != null) {
   7.103 -                response.getOutputBuffer().write(data.getHtml());
   7.104 -            }
   7.105 -            response.setStatus(HttpStatus.OK_200);
   7.106 -            return;
   7.107 -        }
   7.108 -        
   7.109 -        if (r.startsWith("/")) {
   7.110 -            r = r.substring(1);
   7.111 -        }
   7.112 -        
   7.113 -        if (r.endsWith(".html") || r.endsWith(".xhtml")) {
   7.114 -            response.setContentType("text/html");
   7.115 -        }
   7.116 -        OutputStream os = response.getOutputStream();
   7.117 -        try (InputStream is = Dew.class.getResourceAsStream(r) ) {
   7.118 -            copyStream(is, os, request.getRequestURL().toString() );
   7.119 -        } catch (IOException ex) {
   7.120 -            response.setDetailMessage(ex.getLocalizedMessage());
   7.121 -            response.setError();
   7.122 -            response.setStatus(404);
   7.123 -        }
   7.124 -    }
   7.125 -    
   7.126 -    static void copyStream(InputStream is, OutputStream os, String baseURL) throws IOException {
   7.127 -        for (;;) {
   7.128 -            int ch = is.read();
   7.129 -            if (ch == -1) {
   7.130 -                break;
   7.131 -            }
   7.132 -            os.write(ch);            
   7.133 -        }
   7.134 -    }
   7.135 -
   7.136 -    @Override
   7.137 -    public InputStream get(String r) throws IOException {
   7.138 -        byte[] arr = data == null ? null : data.get(r);
   7.139 -        return arr == null ? null : new ByteArrayInputStream(arr);
   7.140 -    }
   7.141 -}
     8.1 --- a/dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java	Tue Apr 29 15:25:58 2014 +0200
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,203 +0,0 @@
     8.4 -/**
     8.5 - * Back 2 Browser Bytecode Translator
     8.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 - *
     8.8 - * This program is free software: you can redistribute it and/or modify
     8.9 - * it under the terms of the GNU General Public License as published by
    8.10 - * the Free Software Foundation, version 2 of the License.
    8.11 - *
    8.12 - * This program is distributed in the hope that it will be useful,
    8.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 - * GNU General Public License for more details.
    8.16 - *
    8.17 - * You should have received a copy of the GNU General Public License
    8.18 - * along with this program. Look for COPYING file in the top folder.
    8.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    8.20 - */
    8.21 -package org.apidesign.bck2brwsr.dew;
    8.22 -
    8.23 -import java.io.IOException;
    8.24 -import java.io.InputStream;
    8.25 -import java.io.Writer;
    8.26 -import java.net.URI;
    8.27 -import java.net.URISyntaxException;
    8.28 -import java.net.URL;
    8.29 -import java.util.Arrays;
    8.30 -import java.util.Enumeration;
    8.31 -import java.util.LinkedHashSet;
    8.32 -import java.util.Set;
    8.33 -import java.util.logging.Level;
    8.34 -import java.util.logging.Logger;
    8.35 -import org.apidesign.vm4brwsr.Bck2Brwsr;
    8.36 -import org.glassfish.grizzly.PortRange;
    8.37 -import org.glassfish.grizzly.http.server.HttpHandler;
    8.38 -import org.glassfish.grizzly.http.server.HttpServer;
    8.39 -import org.glassfish.grizzly.http.server.NetworkListener;
    8.40 -import org.glassfish.grizzly.http.server.Request;
    8.41 -import org.glassfish.grizzly.http.server.Response;
    8.42 -import org.glassfish.grizzly.http.server.ServerConfiguration;
    8.43 -
    8.44 -/**
    8.45 - * Lightweight server to launch dew - the Development Environment for Web.
    8.46 - */
    8.47 -final class DewLauncher {
    8.48 -    private static final Logger LOG = Logger.getLogger(DewLauncher.class.getName());
    8.49 -    private Set<ClassLoader> loaders = new LinkedHashSet<>();
    8.50 -    private Set<Bck2Brwsr.Resources> xRes = new LinkedHashSet<>();
    8.51 -    private final Res resources = new Res();
    8.52 -    private final String cmd;
    8.53 -
    8.54 -    public DewLauncher(String cmd) {
    8.55 -        this.cmd = cmd;
    8.56 -    }
    8.57 -    
    8.58 -    public void addClassLoader(ClassLoader url) {
    8.59 -        this.loaders.add(url);
    8.60 -    }
    8.61 -
    8.62 -    final HttpServer initServer(Bck2Brwsr.Resources... extraResources) throws IOException {
    8.63 -        xRes.addAll(Arrays.asList(extraResources));
    8.64 -        
    8.65 -        HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
    8.66 -
    8.67 -        final ServerConfiguration conf = s.getServerConfiguration();
    8.68 -        conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
    8.69 -        conf.addHttpHandler(new VMInit(), "/vm.js");
    8.70 -        conf.addHttpHandler(new Classes(resources), "/classes/");
    8.71 -        return s;
    8.72 -    }
    8.73 -    
    8.74 -    final Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
    8.75 -        server.start();
    8.76 -        NetworkListener listener = server.getListeners().iterator().next();
    8.77 -        int port = listener.getPort();
    8.78 -        
    8.79 -        URI uri = new URI("http://localhost:" + port + page);
    8.80 -        LOG.log(Level.INFO, "Showing {0}", uri);
    8.81 -        if (cmd == null) {
    8.82 -            try {
    8.83 -                LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
    8.84 -                    System.getProperty("java.vm.name"),
    8.85 -                    System.getProperty("java.vm.vendor"),
    8.86 -                    System.getProperty("java.vm.version"),
    8.87 -                });
    8.88 -                java.awt.Desktop.getDesktop().browse(uri);
    8.89 -                LOG.log(Level.INFO, "Desktop.browse successfully finished");
    8.90 -                return null;
    8.91 -            } catch (UnsupportedOperationException ex) {
    8.92 -                LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
    8.93 -                LOG.log(Level.FINE, null, ex);
    8.94 -            }
    8.95 -        }
    8.96 -        {
    8.97 -            String cmdName = cmd == null ? "xdg-open" : cmd;
    8.98 -            String[] cmdArr = { 
    8.99 -                cmdName, uri.toString()
   8.100 -            };
   8.101 -            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
   8.102 -            final Process process = Runtime.getRuntime().exec(cmdArr);
   8.103 -            return new Object[] { process, null };
   8.104 -        }
   8.105 -    }
   8.106 -
   8.107 -    private class Res implements Bck2Brwsr.Resources {
   8.108 -        @Override
   8.109 -        public InputStream get(String resource) throws IOException {
   8.110 -            for (ClassLoader l : loaders) {
   8.111 -                URL u = null;
   8.112 -                Enumeration<URL> en = l.getResources(resource);
   8.113 -                while (en.hasMoreElements()) {
   8.114 -                    u = en.nextElement();
   8.115 -                }
   8.116 -                if (u != null) {
   8.117 -                    return u.openStream();
   8.118 -                }
   8.119 -            }
   8.120 -            for (Bck2Brwsr.Resources r : xRes) {
   8.121 -                InputStream is = r.get(resource);
   8.122 -                if (is != null) {
   8.123 -                    return is;
   8.124 -                }
   8.125 -            }
   8.126 -            throw new IOException("Can't find " + resource);
   8.127 -        }
   8.128 -    }
   8.129 -
   8.130 -    private static class VM extends HttpHandler {
   8.131 -        private final String bck2brwsr;
   8.132 -
   8.133 -        public VM(Res loader) throws IOException {
   8.134 -            StringBuilder sb = new StringBuilder();
   8.135 -            Bck2Brwsr.generate(sb, loader);
   8.136 -            this.bck2brwsr = sb.toString();
   8.137 -        }
   8.138 -
   8.139 -        @Override
   8.140 -        public void service(Request request, Response response) throws Exception {
   8.141 -            response.setCharacterEncoding("UTF-8");
   8.142 -            response.setContentType("text/javascript");
   8.143 -            response.getWriter().write(bck2brwsr);
   8.144 -        }
   8.145 -    }
   8.146 -    private static class VMInit extends HttpHandler {
   8.147 -        public VMInit() {
   8.148 -        }
   8.149 -
   8.150 -        @Override
   8.151 -        public void service(Request request, Response response) throws Exception {
   8.152 -            response.setCharacterEncoding("UTF-8");
   8.153 -            response.setContentType("text/javascript");
   8.154 -            response.getWriter().append(
   8.155 -                "function ldCls(res) {\n"
   8.156 -                + "  var request = new XMLHttpRequest();\n"
   8.157 -                + "  request.open('GET', '/classes/' + res, false);\n"
   8.158 -                + "  request.send();\n"
   8.159 -                + "  var arr = eval('(' + request.responseText + ')');\n"
   8.160 -                + "  return arr;\n"
   8.161 -                + "}\n"
   8.162 -                + "var vm = new bck2brwsr(ldCls);\n");
   8.163 -        }
   8.164 -    }
   8.165 -
   8.166 -    private static class Classes extends HttpHandler {
   8.167 -        private final Res loader;
   8.168 -
   8.169 -        public Classes(Res loader) {
   8.170 -            this.loader = loader;
   8.171 -        }
   8.172 -
   8.173 -        @Override
   8.174 -        public void service(Request request, Response response) throws Exception {
   8.175 -            String res = request.getHttpHandlerPath();
   8.176 -            if (res.startsWith("/")) {
   8.177 -                res = res.substring(1);
   8.178 -            }
   8.179 -            try (InputStream is = loader.get(res)) {
   8.180 -                response.setContentType("text/javascript");
   8.181 -                Writer w = response.getWriter();
   8.182 -                w.append("[");
   8.183 -                for (int i = 0;; i++) {
   8.184 -                    int b = is.read();
   8.185 -                    if (b == -1) {
   8.186 -                        break;
   8.187 -                    }
   8.188 -                    if (i > 0) {
   8.189 -                        w.append(", ");
   8.190 -                    }
   8.191 -                    if (i % 20 == 0) {
   8.192 -                        w.write("\n");
   8.193 -                    }
   8.194 -                    if (b > 127) {
   8.195 -                        b = b - 256;
   8.196 -                    }
   8.197 -                    w.append(Integer.toString(b));
   8.198 -                }
   8.199 -                w.append("\n]");
   8.200 -            } catch (IOException ex) {
   8.201 -                response.setError();
   8.202 -                response.setDetailMessage(ex.getMessage());
   8.203 -            }
   8.204 -        }
   8.205 -    }
   8.206 -}
     9.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/app.css	Tue Apr 29 15:25:58 2014 +0200
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,54 +0,0 @@
     9.4 -/* app css stylesheet */
     9.5 -.code-editor, .mono-font, .CodeMirror {
     9.6 -    font-family: "Inconsolata","Monaco","Consolas","Andale Mono","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
     9.7 -    font-size: 13px;
     9.8 -    line-height: 15px;
     9.9 -}
    9.10 -
    9.11 -.CodeMirror {                    
    9.12 -    border: 1px solid #d9edf7;      
    9.13 -    height: 300px;
    9.14 -}
    9.15 -      
    9.16 -.CodeMirror-scroll {
    9.17 -    overflow-y: auto;
    9.18 -    overflow-x: auto;
    9.19 -}
    9.20 -
    9.21 -.error-hover:hover {
    9.22 -    text-decoration: underline;
    9.23 -    cursor: pointer;
    9.24 -} 
    9.25 -
    9.26 -.ic-html5 {
    9.27 -  display: inline-block;  
    9.28 -  height: 20px;
    9.29 -  width: 20px;
    9.30 -  vertical-align: text-bottom;
    9.31 -  background-repeat: no-repeat;  
    9.32 -  background-image: url("../img/html5.png");  
    9.33 -}
    9.34 -
    9.35 -.ic-java {
    9.36 -  display: inline-block;  
    9.37 -  height: 20px;
    9.38 -  width: 20px;
    9.39 -  vertical-align: text-bottom;
    9.40 -  background-repeat: no-repeat;  
    9.41 -  background-image: url("../img/java.png"); 
    9.42 - 
    9.43 -}
    9.44 -
    9.45 -.issues {    
    9.46 -    width: 16px;
    9.47 -}
    9.48 -
    9.49 -.issue { 
    9.50 -    height: 16px;
    9.51 -    width: 16px;
    9.52 -    vertical-align: middle;
    9.53 -    background-repeat: no-repeat;  
    9.54 -    background-image: url("../img/error.png"); 
    9.55 -    /* color: #822; */
    9.56 -}
    9.57 -
    10.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/bootstrap-combined.min.css	Tue Apr 29 15:25:58 2014 +0200
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,18 +0,0 @@
    10.4 -/*!
    10.5 - * Bootstrap v2.2.2
    10.6 - *
    10.7 - * Copyright 2012 Twitter, Inc
    10.8 - * Licensed under the Apache License v2.0
    10.9 - * http://www.apache.org/licenses/LICENSE-2.0
   10.10 - *
   10.11 - * Designed and built with all the love in the world @twitter by @mdo and @fat.
   10.12 - */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media .pull-left{margin-right:10px}.media .pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}
   10.13 -/*!
   10.14 - * Bootstrap Responsive v2.2.2
   10.15 - *
   10.16 - * Copyright 2012 Twitter, Inc
   10.17 - * Licensed under the Apache License v2.0
   10.18 - * http://www.apache.org/licenses/LICENSE-2.0
   10.19 - *
   10.20 - * Designed and built with all the love in the world @twitter by @mdo and @fat.
   10.21 - */@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
    11.1 Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/error.png has changed
    12.1 Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings-white.png has changed
    13.1 Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings.png has changed
    14.1 Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/html5.png has changed
    15.1 Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/java.png has changed
    16.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/index.html	Tue Apr 29 15:25:58 2014 +0200
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,98 +0,0 @@
    16.4 -<!--
    16.5 -To change this template, choose Tools | Templates
    16.6 -and open the template in the editor.
    16.7 --->
    16.8 -<!DOCTYPE html>
    16.9 -<html lang="en" ng-app="bck2brwsr" ng-controller="DevCtrl">
   16.10 -    <head>
   16.11 -        <title>Back2Browser - DEW</title>
   16.12 -        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   16.13 -        <meta name="viewport" content="width=device-width, initial-scale=1.0">
   16.14 -        <link rel="stylesheet" href="css/bootstrap-combined.min.css"/>  
   16.15 -        <link rel="stylesheet" href="js/codemirror/codemirror.css">
   16.16 -        <link rel="stylesheet" href="js/codemirror/theme/elegant.css"/>
   16.17 -        <link rel="stylesheet" href="css/app.css"/>
   16.18 -    </head>
   16.19 -    <body>
   16.20 -                
   16.21 -        <div class="navbar navbar-fixed-top" style="width: 100%"> 
   16.22 -        <div class="navbar-inner" style="padding-left: 12px; padding-right: 12px;">
   16.23 -            <!-- a class="brand" style="font-size: 100%"><span class="text-info"><b>Java and HTML5</b></span><small>- Together at Last!</small></a-->
   16.24 -            <form class="navbar-form pull-right">
   16.25 -                <!-- select class="span2"></select -->
   16.26 -                <button ng-click="post()" class="btn btn-warning">Rebuild</button>
   16.27 -              </form>
   16.28 -            <!-- ul class="nav">                          
   16.29 -                <li><select class="btn-small" type="text"></select></li>
   16.30 -            </ul -->
   16.31 -            <!-- form class="form form-horizontal pull-right">
   16.32 -                <button class="btn btn-warning btn-small pull-right top" ng-click="post()">Rebuild</button>
   16.33 -            </form -->
   16.34 -            <!-- ul class="nav pull-right">
   16.35 -                
   16.36 -            </ul-->     
   16.37 -        </div>  
   16.38 -        </div>
   16.39 -
   16.40 -        <div class="container-fluid">        
   16.41 -        
   16.42 -        <div style="height: 4em;">&nbsp;</div>    
   16.43 -            
   16.44 -        <div class="row-fluid">
   16.45 -            <div class="span6" style="margin-bottom: 10px;"> 
   16.46 -                <table class="table table-condensed" style="margin-bottom: 2px">
   16.47 -                <tr><td><i class="ic-html5"></i> HTML5</td></tr>               
   16.48 -                </table>
   16.49 -                <div>
   16.50 -                    <textarea ui-codemirror='{ lineNumbers : true, mode : "xml", theme : "elegant", matchBrackets : true, lineWrapping : true }' ng-model="html"></textarea>
   16.51 -                    <div class="alert alert-error" ng-show="doc.modelError">
   16.52 -                        <small>{{doc.modelError.toString()}}</small>
   16.53 -                    </div>
   16.54 -                </div>    
   16.55 -            </div>
   16.56 -            
   16.57 -            <div class="span6">  
   16.58 -                <table class="table table-condensed" style="margin-bottom: 2px">
   16.59 -                <tr><td><i class="ic-java"></i> Java</td></tr>               
   16.60 -                </table>                
   16.61 -                <div>
   16.62 -                    <textarea id="editorJava" ui-codemirror='{ lineNumbers : true, mode : "text/x-java", theme : "elegant", matchBrackets : true, lineWrapping : true, gutters: ["CodeMirror-linenumbers", "issues"] }' ng-model="java"></textarea>
   16.63 -                    <div class="alert alert-error" ng-show="doc.modelError">
   16.64 -                        <small>{{doc.modelError.toString()}}</small>
   16.65 -                    </div>
   16.66 -                </div>
   16.67 -            </div>
   16.68 -        
   16.69 -        </div>    
   16.70 -            
   16.71 -        <table class="table table-condensed">
   16.72 -            <tr ng-click="gotoError(e.line, e.col)" ng-repeat="e in errors" ng-class="errorClass(e.kind)">
   16.73 -                <td style="text-align: right">{{e.line}}</td> 
   16.74 -                <td>:</td> 
   16.75 -                <td style="text-align: left">{{e.col}}</td> 
   16.76 -                <td width="100%" class="text-error error-hover">{{e.msg}} <i class="icon-play"/></td>
   16.77 -            </tr>            
   16.78 -        </table>    
   16.79 -            
   16.80 -        
   16.81 -        <div>&nbsp;</div>    
   16.82 -            
   16.83 -        <ul class="nav nav-tabs">
   16.84 -            <li ng-class="'active'"><a href="#">Result</a></li>
   16.85 -        </ul>    
   16.86 -        
   16.87 -        
   16.88 -        <!-- button class="btn" ng-click="reload()">Reload</button -->
   16.89 -        <iframe id="result" frameborder="0" scrolling="yes" width="100%" style="height: 1000px; overflow: auto; border: 1px solid #DFDFDF;" src="result.html">
   16.90 -            <p>Your browser does not support iframes.</p>
   16.91 -        </iframe>
   16.92 -            
   16.93 -        </div>
   16.94 -        
   16.95 -        <script src="js/angular/angular.min.js"></script>
   16.96 -        <script src="js/codemirror/codemirror.js"></script>
   16.97 -        <script src="js/codemirror/mode/xml.js"></script>
   16.98 -        <script src="js/codemirror/mode/clike.js"></script>
   16.99 -        <script src="js/app.js"></script>
  16.100 -    </body>
  16.101 -</html>
    17.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/angular/angular.min.js	Tue Apr 29 15:25:58 2014 +0200
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,159 +0,0 @@
    17.4 -/*
    17.5 - AngularJS v1.0.3
    17.6 - (c) 2010-2012 Google, Inc. http://angularjs.org
    17.7 - License: MIT
    17.8 -*/
    17.9 -(function(U,ca,p){'use strict';function m(b,a,c){var d;if(b)if(N(b))for(d in b)d!="prototype"&&d!="length"&&d!="name"&&b.hasOwnProperty(d)&&a.call(c,b[d],d);else if(b.forEach&&b.forEach!==m)b.forEach(a,c);else if(L(b)&&wa(b.length))for(d=0;d<b.length;d++)a.call(c,b[d],d);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d);return b}function lb(b){var a=[],c;for(c in b)b.hasOwnProperty(c)&&a.push(c);return a.sort()}function ec(b,a,c){for(var d=lb(b),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}
   17.10 -function mb(b){return function(a,c){b(c,a)}}function xa(){for(var b=Z.length,a;b;){b--;a=Z[b].charCodeAt(0);if(a==57)return Z[b]="A",Z.join("");if(a==90)Z[b]="0";else return Z[b]=String.fromCharCode(a+1),Z.join("")}Z.unshift("0");return Z.join("")}function x(b){m(arguments,function(a){a!==b&&m(a,function(a,d){b[d]=a})});return b}function G(b){return parseInt(b,10)}function ya(b,a){return x(new (x(function(){},{prototype:b})),a)}function D(){}function ma(b){return b}function I(b){return function(){return b}}
   17.11 -function t(b){return typeof b=="undefined"}function v(b){return typeof b!="undefined"}function L(b){return b!=null&&typeof b=="object"}function F(b){return typeof b=="string"}function wa(b){return typeof b=="number"}function na(b){return Sa.apply(b)=="[object Date]"}function J(b){return Sa.apply(b)=="[object Array]"}function N(b){return typeof b=="function"}function oa(b){return b&&b.document&&b.location&&b.alert&&b.setInterval}function R(b){return F(b)?b.replace(/^\s*/,"").replace(/\s*$/,""):b}function fc(b){return b&&
   17.12 -(b.nodeName||b.bind&&b.find)}function Ta(b,a,c){var d=[];m(b,function(b,g,i){d.push(a.call(c,b,g,i))});return d}function gc(b,a){var c=0,d;if(J(b)||F(b))return b.length;else if(L(b))for(d in b)(!a||b.hasOwnProperty(d))&&c++;return c}function za(b,a){if(b.indexOf)return b.indexOf(a);for(var c=0;c<b.length;c++)if(a===b[c])return c;return-1}function Ua(b,a){var c=za(b,a);c>=0&&b.splice(c,1);return a}function V(b,a){if(oa(b)||b&&b.$evalAsync&&b.$watch)throw B("Can't copy Window or Scope");if(a){if(b===
   17.13 -a)throw B("Can't copy equivalent objects or arrays");if(J(b)){for(;a.length;)a.pop();for(var c=0;c<b.length;c++)a.push(V(b[c]))}else for(c in m(a,function(b,c){delete a[c]}),b)a[c]=V(b[c])}else(a=b)&&(J(b)?a=V(b,[]):na(b)?a=new Date(b.getTime()):L(b)&&(a=V(b,{})));return a}function hc(b,a){var a=a||{},c;for(c in b)b.hasOwnProperty(c)&&c.substr(0,2)!=="$$"&&(a[c]=b[c]);return a}function ha(b,a){if(b===a)return!0;if(b===null||a===null)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&
   17.14 -c=="object")if(J(b)){if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ha(b[d],a[d]))return!1;return!0}}else if(na(b))return na(a)&&b.getTime()==a.getTime();else{if(b&&b.$evalAsync&&b.$watch||a&&a.$evalAsync&&a.$watch||oa(b)||oa(a))return!1;c={};for(d in b){if(d.charAt(0)!=="$"&&!N(b[d])&&!ha(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c[d]&&d.charAt(0)!=="$"&&!N(a[d]))return!1;return!0}return!1}function Va(b,a){var c=arguments.length>2?ia.call(arguments,2):[];return N(a)&&!(a instanceof RegExp)?c.length?
   17.15 -function(){return arguments.length?a.apply(b,c.concat(ia.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}:a}function ic(b,a){var c=a;/^\$+/.test(b)?c=p:oa(a)?c="$WINDOW":a&&ca===a?c="$DOCUMENT":a&&a.$evalAsync&&a.$watch&&(c="$SCOPE");return c}function da(b,a){return JSON.stringify(b,ic,a?"  ":null)}function nb(b){return F(b)?JSON.parse(b):b}function Wa(b){b&&b.length!==0?(b=E(""+b),b=!(b=="f"||b=="0"||b=="false"||b=="no"||b=="n"||b=="[]")):b=!1;
   17.16 -return b}function pa(b){b=u(b).clone();try{b.html("")}catch(a){}return u("<div>").append(b).html().match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+E(b)})}function Xa(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.split("="),d=decodeURIComponent(c[0]),a[d]=v(c[1])?decodeURIComponent(c[1]):!0)});return a}function ob(b){var a=[];m(b,function(b,d){a.push(Ya(d,!0)+(b===!0?"":"="+Ya(b,!0)))});return a.length?a.join("&"):""}function Za(b){return Ya(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,
   17.17 -"=").replace(/%2B/gi,"+")}function Ya(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(a?null:/%20/g,"+")}function jc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,i=["ng:app","ng-app","x-ng-app","data-ng-app"],f=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;m(i,function(a){i[a]=!0;c(ca.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(m(b.querySelectorAll("."+a),c),m(b.querySelectorAll("."+a+"\\:"),c),m(b.querySelectorAll("["+
   17.18 -a+"]"),c))});m(d,function(a){if(!e){var b=f.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):m(a.attributes,function(b){if(!e&&i[b.name])e=a,g=b.value})}});e&&a(e,g?[g]:[])}function pb(b,a){b=u(b);a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");var c=qb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,i){a.$apply(function(){b.data("$injector",i);c(b)(a)})}]);return c}function $a(b,a){a=a||"_";return b.replace(kc,
   17.19 -function(b,d){return(d?a:"")+b.toLowerCase()})}function qa(b,a,c){if(!b)throw new B("Argument '"+(a||"?")+"' is "+(c||"required"));return b}function ra(b,a,c){c&&J(b)&&(b=b[b.length-1]);qa(N(b),a,"not a function, got "+(b&&typeof b=="object"?b.constructor.name||"Object":typeof b));return b}function lc(b){function a(a,b,e){return a[b]||(a[b]=e())}return a(a(b,"angular",Object),"module",function(){var b={};return function(d,e,g){e&&b.hasOwnProperty(d)&&(b[d]=null);return a(b,d,function(){function a(c,
   17.20 -d,e){return function(){b[e||"push"]([c,d,arguments]);return j}}if(!e)throw B("No module: "+d);var b=[],c=[],k=a("$injector","invoke"),j={_invokeQueue:b,_runBlocks:c,requires:e,name:d,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:k,run:function(a){c.push(a);
   17.21 -return this}};g&&k(g);return j})}})}function rb(b){return b.replace(mc,function(a,b,d,e){return e?d.toUpperCase():d}).replace(nc,"Moz$1")}function ab(b,a){function c(){var e;for(var b=[this],c=a,i,f,h,k,j,l;b.length;){i=b.shift();f=0;for(h=i.length;f<h;f++){k=u(i[f]);c?k.triggerHandler("$destroy"):c=!c;j=0;for(e=(l=k.children()).length,k=e;j<k;j++)b.push(ja(l[j]))}}return d.apply(this,arguments)}var d=ja.fn[b],d=d.$original||d;c.$original=d;ja.fn[b]=c}function Q(b){if(b instanceof Q)return b;if(!(this instanceof
   17.22 -Q)){if(F(b)&&b.charAt(0)!="<")throw B("selectors not implemented");return new Q(b)}if(F(b)){var a=ca.createElement("div");a.innerHTML="<div>&#160;</div>"+b;a.removeChild(a.firstChild);bb(this,a.childNodes);this.remove()}else bb(this,b)}function cb(b){return b.cloneNode(!0)}function sa(b){sb(b);for(var a=0,b=b.childNodes||[];a<b.length;a++)sa(b[a])}function tb(b,a,c){var d=$(b,"events");$(b,"handle")&&(t(a)?m(d,function(a,c){db(b,c,a);delete d[c]}):t(c)?(db(b,a,d[a]),delete d[a]):Ua(d[a],c))}function sb(b){var a=
   17.23 -b[Aa],c=Ba[a];c&&(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),tb(b)),delete Ba[a],b[Aa]=p)}function $(b,a,c){var d=b[Aa],d=Ba[d||-1];if(v(c))d||(b[Aa]=d=++oc,d=Ba[d]={}),d[a]=c;else return d&&d[a]}function ub(b,a,c){var d=$(b,"data"),e=v(c),g=!e&&v(a),i=g&&!L(a);!d&&!i&&$(b,"data",d={});if(e)d[a]=c;else if(g)if(i)return d&&d[a];else x(d,a);else return d}function Ca(b,a){return(" "+b.className+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" ")>-1}function vb(b,a){a&&m(a.split(" "),function(a){b.className=
   17.24 -R((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," "))})}function wb(b,a){a&&m(a.split(" "),function(a){if(!Ca(b,a))b.className=R(b.className+" "+R(a))})}function bb(b,a){if(a)for(var a=!a.nodeName&&v(a.length)&&!oa(a)?a:[a],c=0;c<a.length;c++)b.push(a[c])}function xb(b,a){return Da(b,"$"+(a||"ngController")+"Controller")}function Da(b,a,c){b=u(b);for(b[0].nodeType==9&&(b=b.find("html"));b.length;){if(c=b.data(a))return c;b=b.parent()}}function yb(b,a){var c=Ea[a.toLowerCase()];
   17.25 -return c&&zb[b.nodeName]&&c}function pc(b,a){var c=function(c,e){if(!c.preventDefault)c.preventDefault=function(){c.returnValue=!1};if(!c.stopPropagation)c.stopPropagation=function(){c.cancelBubble=!0};if(!c.target)c.target=c.srcElement||ca;if(t(c.defaultPrevented)){var g=c.preventDefault;c.preventDefault=function(){c.defaultPrevented=!0;g.call(c)};c.defaultPrevented=!1}c.isDefaultPrevented=function(){return c.defaultPrevented};m(a[e||c.type],function(a){a.call(b,c)});aa<=8?(c.preventDefault=null,
   17.26 -c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function ga(b){var a=typeof b,c;if(a=="object"&&b!==null)if(typeof(c=b.$$hashKey)=="function")c=b.$$hashKey();else{if(c===p)c=b.$$hashKey=xa()}else c=b;return a+":"+c}function Fa(b){m(b,this.put,this)}function eb(){}function Ab(b){var a,c;if(typeof b=="function"){if(!(a=b.$inject))a=[],c=b.toString().replace(qc,""),c=c.match(rc),m(c[1].split(sc),function(b){b.replace(tc,
   17.27 -function(b,c,d){a.push(d)})}),b.$inject=a}else J(b)?(c=b.length-1,ra(b[c],"fn"),a=b.slice(0,c)):ra(b,"fn",!0);return a}function qb(b){function a(a){return function(b,c){if(L(b))m(b,mb(a));else return a(b,c)}}function c(a,b){N(b)&&(b=l.instantiate(b));if(!b.$get)throw B("Provider "+a+" must define $get factory method.");return j[a+f]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[];m(a,function(a){if(!k.get(a))if(k.put(a,!0),F(a)){var c=ta(a);b=b.concat(e(c.requires)).concat(c._runBlocks);
   17.28 -try{for(var d=c._invokeQueue,c=0,f=d.length;c<f;c++){var h=d[c],g=h[0]=="$injector"?l:l.get(h[0]);g[h[1]].apply(g,h[2])}}catch(n){throw n.message&&(n.message+=" from "+a),n;}}else if(N(a))try{b.push(l.invoke(a))}catch(i){throw i.message&&(i.message+=" from "+a),i;}else if(J(a))try{b.push(l.invoke(a))}catch(j){throw j.message&&(j.message+=" from "+String(a[a.length-1])),j;}else ra(a,"module")});return b}function g(a,b){function c(d){if(typeof d!=="string")throw B("Service name expected");if(a.hasOwnProperty(d)){if(a[d]===
   17.29 -i)throw B("Circular dependency: "+h.join(" <- "));return a[d]}else try{return h.unshift(d),a[d]=i,a[d]=b(d)}finally{h.shift()}}function d(a,b,e){var f=[],k=Ab(a),g,n,i;n=0;for(g=k.length;n<g;n++)i=k[n],f.push(e&&e.hasOwnProperty(i)?e[i]:c(i,h));a.$inject||(a=a[g]);switch(b?-1:f.length){case 0:return a();case 1:return a(f[0]);case 2:return a(f[0],f[1]);case 3:return a(f[0],f[1],f[2]);case 4:return a(f[0],f[1],f[2],f[3]);case 5:return a(f[0],f[1],f[2],f[3],f[4]);case 6:return a(f[0],f[1],f[2],f[3],
   17.30 -f[4],f[5]);case 7:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6]);case 8:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7]);case 9:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8]);case 10:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9]);default:return a.apply(b,f)}}return{invoke:d,instantiate:function(a,b){var c=function(){},e;c.prototype=(J(a)?a[a.length-1]:a).prototype;c=new c;e=d(a,c,b);return L(e)?e:c},get:c,annotate:Ab}}var i={},f="Provider",h=[],k=new Fa,j={$provide:{provider:a(c),
   17.31 -factory:a(d),service:a(function(a,b){return d(a,["$injector",function(a){return a.instantiate(b)}])}),value:a(function(a,b){return d(a,I(b))}),constant:a(function(a,b){j[a]=b;o[a]=b}),decorator:function(a,b){var c=l.get(a+f),d=c.$get;c.$get=function(){var a=r.invoke(d,c);return r.invoke(b,null,{$delegate:a})}}}},l=g(j,function(){throw B("Unknown provider: "+h.join(" <- "));}),o={},r=o.$injector=g(o,function(a){a=l.get(a+f);return r.invoke(a.$get,a)});m(e(b),function(a){r.invoke(a||D)});return r}function uc(){var b=
   17.32 -!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;m(a,function(a){!b&&E(a.nodeName)==="a"&&(b=a)});return b}function g(){var b=c.hash(),d;b?(d=i.getElementById(b))?d.scrollIntoView():(d=e(i.getElementsByName(b)))?d.scrollIntoView():b==="top"&&a.scrollTo(0,0):a.scrollTo(0,0)}var i=a.document;b&&d.$watch(function(){return c.hash()},function(){d.$evalAsync(g)});return g}]}function vc(b,a,c,d){function e(a){try{a.apply(null,
   17.33 -ia.call(arguments,1))}finally{if(n--,n===0)for(;w.length;)try{w.pop()()}catch(b){c.error(b)}}}function g(a,b){(function ea(){m(q,function(a){a()});s=b(ea,a)})()}function i(){O!=f.url()&&(O=f.url(),m(A,function(a){a(f.url())}))}var f=this,h=a[0],k=b.location,j=b.history,l=b.setTimeout,o=b.clearTimeout,r={};f.isMock=!1;var n=0,w=[];f.$$completeOutstandingRequest=e;f.$$incOutstandingRequestCount=function(){n++};f.notifyWhenNoOutstandingRequests=function(a){m(q,function(a){a()});n===0?a():w.push(a)};
   17.34 -var q=[],s;f.addPollFn=function(a){t(s)&&g(100,l);q.push(a);return a};var O=k.href,C=a.find("base");f.url=function(a,b){if(a){if(O!=a)return O=a,d.history?b?j.replaceState(null,"",a):(j.pushState(null,"",a),C.attr("href",C.attr("href"))):b?k.replace(a):k.href=a,f}else return k.href.replace(/%27/g,"'")};var A=[],K=!1;f.onUrlChange=function(a){K||(d.history&&u(b).bind("popstate",i),d.hashchange?u(b).bind("hashchange",i):f.addPollFn(i),K=!0);A.push(a);return a};f.baseHref=function(){var a=C.attr("href");
   17.35 -return a?a.replace(/^https?\:\/\/[^\/]*/,""):a};var W={},y="",M=f.baseHref();f.cookies=function(a,b){var d,e,f,k;if(a)if(b===p)h.cookie=escape(a)+"=;path="+M+";expires=Thu, 01 Jan 1970 00:00:00 GMT";else{if(F(b))d=(h.cookie=escape(a)+"="+escape(b)+";path="+M).length+1,d>4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"),W.length>20&&c.warn("Cookie '"+a+"' possibly not set or overflowed because too many cookies were already set ("+W.length+
   17.36 -" > 20 )")}else{if(h.cookie!==y){y=h.cookie;d=y.split("; ");W={};for(f=0;f<d.length;f++)e=d[f],k=e.indexOf("="),k>0&&(W[unescape(e.substring(0,k))]=unescape(e.substring(k+1)))}return W}};f.defer=function(a,b){var c;n++;c=l(function(){delete r[c];e(a)},b||0);r[c]=!0;return c};f.defer.cancel=function(a){return r[a]?(delete r[a],o(a),e(D),!0):!1}}function wc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new vc(b,d,a,c)}]}function xc(){this.$get=function(){function b(b,
   17.37 -d){function e(a){if(a!=l){if(o){if(o==a)o=a.n}else o=a;g(a.n,a.p);g(a,l);l=a;l.n=null}}function g(a,b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw B("cacheId "+b+" taken");var i=0,f=x({},d,{id:b}),h={},k=d&&d.capacity||Number.MAX_VALUE,j={},l=null,o=null;return a[b]={put:function(a,b){var c=j[a]||(j[a]={key:a});e(c);t(b)||(a in h||i++,h[a]=b,i>k&&this.remove(o.key))},get:function(a){var b=j[a];if(b)return e(b),h[a]},remove:function(a){var b=j[a];if(b){if(b==l)l=b.p;if(b==o)o=b.n;g(b.n,b.p);delete j[a];
   17.38 -delete h[a];i--}},removeAll:function(){h={};i=0;j={};l=o=null},destroy:function(){j=f=h=null;delete a[b]},info:function(){return x({},f,{size:i})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function yc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Bb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g="Template must have exactly one root element. was: ";
   17.39 -this.directive=function f(d,e){F(d)?(qa(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];m(a[d],function(a){try{var f=b.invoke(a);if(N(f))f={compile:I(f)};else if(!f.compile&&f.link)f.compile=I(f.link);f.priority=f.priority||0;f.name=f.name||d;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(k){c(k)}});return e}])),a[d].push(e)):m(d,mb(f));return this};this.$get=["$injector","$interpolate","$exceptionHandler",
   17.40 -"$http","$templateCache","$parse","$controller","$rootScope",function(b,h,k,j,l,o,r,n){function w(a,b,c){a instanceof u||(a=u(a));m(a,function(b,c){b.nodeType==3&&(a[c]=u(b).wrap("<span></span>").parent()[0])});var d=s(a,b,a,c);return function(b,c){qa(b,"scope");var e=c?ua.clone.call(a):a;e.data("$scope",b);q(e,"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}function q(a,b){try{a.addClass(b)}catch(c){}}function s(a,b,c,d){function e(a,c,d,k){for(var g,h,j,n,o,l=0,r=0,q=f.length;l<q;r++)j=c[r],g=f[l++],
   17.41 -h=f[l++],g?(g.scope?(n=a.$new(L(g.scope)),u(j).data("$scope",n)):n=a,(o=g.transclude)||!k&&b?g(h,n,j,d,function(b){return function(c){var d=a.$new();return b(d,c).bind("$destroy",Va(d,d.$destroy))}}(o||b)):g(h,n,j,p,k)):h&&h(a,j.childNodes,p,k)}for(var f=[],k,g,h,j=0;j<a.length;j++)g=new ea,k=O(a[j],[],g,d),g=(k=k.length?C(k,a[j],g,b,c):null)&&k.terminal||!a[j].childNodes.length?null:s(a[j].childNodes,k?k.transclude:b),f.push(k),f.push(g),h=h||k||g;return h?e:null}function O(a,b,c,f){var k=c.$attr,
   17.42 -g;switch(a.nodeType){case 1:A(b,fa(Cb(a).toLowerCase()),"E",f);var h,j,n;g=a.attributes;for(var o=0,l=g&&g.length;o<l;o++)if(h=g[o],h.specified)j=h.name,n=fa(j.toLowerCase()),k[n]=j,c[n]=h=R(aa&&j=="href"?decodeURIComponent(a.getAttribute(j,2)):h.value),yb(a,n)&&(c[n]=!0),X(a,b,h,n),A(b,n,"A",f);a=a.className;if(F(a)&&a!=="")for(;g=e.exec(a);)n=fa(g[2]),A(b,n,"C",f)&&(c[n]=R(g[3])),a=a.substr(g.index+g[0].length);break;case 3:H(b,a.nodeValue);break;case 8:try{if(g=d.exec(a.nodeValue))n=fa(g[1]),A(b,
   17.43 -n,"M",f)&&(c[n]=R(g[2]))}catch(r){}}b.sort(y);return b}function C(a,b,c,d,e){function f(a,b){if(a)a.require=z.require,l.push(a);if(b)b.require=z.require,ba.push(b)}function h(a,b){var c,d="data",e=!1;if(F(a)){for(;(c=a.charAt(0))=="^"||c=="?";)a=a.substr(1),c=="^"&&(d="inheritedData"),e=e||c=="?";c=b[d]("$"+a+"Controller");if(!c&&!e)throw B("No controller: "+a);}else J(a)&&(c=[],m(a,function(a){c.push(h(a,b))}));return c}function j(a,d,e,f,g){var n,q,w,K,s;n=b===e?c:hc(c,new ea(u(e),c.$attr));q=n.$$element;
   17.44 -if(C){var zc=/^\s*([@=&])\s*(\w*)\s*$/,O=d.$parent||d;m(C.scope,function(a,b){var c=a.match(zc)||[],e=c[2]||b,f,g,k;switch(c[1]){case "@":n.$observe(e,function(a){d[b]=a});n.$$observers[e].$$scope=O;break;case "=":g=o(n[e]);k=g.assign||function(){f=d[b]=g(O);throw B(Db+n[e]+" (directive: "+C.name+")");};f=d[b]=g(O);d.$watch(function(){var a=g(O);a!==d[b]&&(a!==f?f=d[b]=a:k(O,a=f=d[b]));return a});break;case "&":g=o(n[e]);d[b]=function(a){return g(O,a)};break;default:throw B("Invalid isolate scope definition for directive "+
   17.45 -C.name+": "+a);}})}t&&m(t,function(a){var b={$scope:d,$element:q,$attrs:n,$transclude:g};s=a.controller;s=="@"&&(s=n[a.name]);q.data("$"+a.name+"Controller",r(s,b))});f=0;for(w=l.length;f<w;f++)try{K=l[f],K(d,q,n,K.require&&h(K.require,q))}catch(y){k(y,pa(q))}a&&a(d,e.childNodes,p,g);f=0;for(w=ba.length;f<w;f++)try{K=ba[f],K(d,q,n,K.require&&h(K.require,q))}catch(Ha){k(Ha,pa(q))}}for(var n=-Number.MAX_VALUE,l=[],ba=[],s=null,C=null,A=null,y=c.$$element=u(b),z,H,X,D,v=d,t,x,Y,E=0,G=a.length;E<G;E++){z=
   17.46 -a[E];X=p;if(n>z.priority)break;if(Y=z.scope)M("isolated scope",C,z,y),L(Y)&&(q(y,"ng-isolate-scope"),C=z),q(y,"ng-scope"),s=s||z;H=z.name;if(Y=z.controller)t=t||{},M("'"+H+"' controller",t[H],z,y),t[H]=z;if(Y=z.transclude)M("transclusion",D,z,y),D=z,n=z.priority,Y=="element"?(X=u(b),y=c.$$element=u("<\!-- "+H+": "+c[H]+" --\>"),b=y[0],Ga(e,u(X[0]),b),v=w(X,d,n)):(X=u(cb(b)).contents(),y.html(""),v=w(X,d));if(Y=z.template)if(M("template",A,z,y),A=z,Y=Ha(Y),z.replace){X=u("<div>"+R(Y)+"</div>").contents();
   17.47 -b=X[0];if(X.length!=1||b.nodeType!==1)throw new B(g+Y);Ga(e,y,b);H={$attr:{}};a=a.concat(O(b,a.splice(E+1,a.length-(E+1)),H));K(c,H);G=a.length}else y.html(Y);if(z.templateUrl)M("template",A,z,y),A=z,j=W(a.splice(E,a.length-E),j,y,c,e,z.replace,v),G=a.length;else if(z.compile)try{x=z.compile(y,c,v),N(x)?f(null,x):x&&f(x.pre,x.post)}catch(I){k(I,pa(y))}if(z.terminal)j.terminal=!0,n=Math.max(n,z.priority)}j.scope=s&&s.scope;j.transclude=D&&v;return j}function A(d,e,g,h){var j=!1;if(a.hasOwnProperty(e))for(var n,
   17.48 -e=b.get(e+c),o=0,l=e.length;o<l;o++)try{if(n=e[o],(h===p||h>n.priority)&&n.restrict.indexOf(g)!=-1)d.push(n),j=!0}catch(r){k(r)}return j}function K(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){f=="class"?(q(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):f=="style"?e.attr("style",e.attr("style")+";"+b):f.charAt(0)!="$"&&!a.hasOwnProperty(f)&&(a[f]=b,d[f]=c[f])})}function W(a,b,c,d,e,
   17.49 -f,k){var h=[],n,o,r=c[0],q=a.shift(),w=x({},q,{controller:null,templateUrl:null,transclude:null,scope:null});c.html("");j.get(q.templateUrl,{cache:l}).success(function(j){var l,q,j=Ha(j);if(f){q=u("<div>"+R(j)+"</div>").contents();l=q[0];if(q.length!=1||l.nodeType!==1)throw new B(g+j);j={$attr:{}};Ga(e,c,l);O(l,a,j);K(d,j)}else l=r,c.html(j);a.unshift(w);n=C(a,c,d,k);for(o=s(c.contents(),k);h.length;){var ba=h.pop(),j=h.pop();q=h.pop();var y=h.pop(),m=l;q!==r&&(m=cb(l),Ga(j,u(q),m));n(function(){b(o,
   17.50 -y,m,e,ba)},y,m,e,ba)}h=null}).error(function(a,b,c,d){throw B("Failed to load template: "+d.url);});return function(a,c,d,e,f){h?(h.push(c),h.push(d),h.push(e),h.push(f)):n(function(){b(o,c,d,e,f)},c,d,e,f)}}function y(a,b){return b.priority-a.priority}function M(a,b,c,d){if(b)throw B("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+pa(d));}function H(a,b){var c=h(b,!0);c&&a.push({priority:0,compile:I(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);q(d.data("$binding",
   17.51 -e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function X(a,b,c,d){var e=h(c,!0);e&&b.push({priority:100,compile:I(function(a,b,c){b=c.$$observers||(c.$$observers={});d==="class"&&(e=h(c[d],!0));c[d]=p;(b[d]||(b[d]=[])).$$inter=!0;(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function Ga(a,b,c){var d=b[0],e=d.parentNode,f,g;if(a){f=0;for(g=a.length;f<g;f++)if(a[f]==d){a[f]=c;break}}e&&e.replaceChild(c,d);c[u.expando]=d[u.expando];b[0]=c}var ea=
   17.52 -function(a,b){this.$$element=a;this.$attr=b||{}};ea.prototype={$normalize:fa,$set:function(a,b,c,d){var e=yb(this.$$element[0],a),f=this.$$observers;e&&(this.$$element.prop(a,b),d=e);this[a]=b;d?this.$attr[a]=d:(d=this.$attr[a])||(this.$attr[a]=d=$a(a,"-"));c!==!1&&(b===null||b===p?this.$$element.removeAttr(d):this.$$element.attr(d,b));f&&m(f[a],function(a){try{a(b)}catch(c){k(c)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers={}),e=d[a]||(d[a]=[]);e.push(b);n.$evalAsync(function(){e.$$inter||
   17.53 -b(c[a])});return b}};var D=h.startSymbol(),ba=h.endSymbol(),Ha=D=="{{"||ba=="}}"?ma:function(a){return a.replace(/\{\{/g,D).replace(/}}/g,ba)};return w}]}function fa(b){return rb(b.replace(Ac,""))}function Bc(){var b={};this.register=function(a,c){L(a)?x(b,a):b[a]=c};this.$get=["$injector","$window",function(a,c){return function(d,e){if(F(d)){var g=d,d=b.hasOwnProperty(g)?b[g]:fb(e.$scope,g,!0)||fb(c,g,!0);ra(d,g,!0)}return a.instantiate(d,e)}}]}function Cc(){this.$get=["$window",function(b){return u(b.document)}]}
   17.54 -function Dc(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Ec(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse",function(c){function d(d,f){for(var h,k,j=0,l=[],o=d.length,r=!1,n=[];j<o;)(h=d.indexOf(b,j))!=-1&&(k=d.indexOf(a,h+e))!=-1?(j!=h&&l.push(d.substring(j,h)),l.push(j=c(r=d.substring(h+e,k))),j.exp=r,j=k+g,r=!0):(j!=o&&l.push(d.substring(j)),j=o);if(!(o=
   17.55 -l.length))l.push(""),o=1;if(!f||r)return n.length=o,j=function(a){for(var b=0,c=o,d;b<c;b++){if(typeof(d=l[b])=="function")d=d(a),d==null||d==p?d="":typeof d!="string"&&(d=da(d));n[b]=d}return n.join("")},j.exp=d,j.parts=l,j}var e=b.length,g=a.length;d.startSymbol=function(){return b};d.endSymbol=function(){return a};return d}]}function Eb(b){for(var b=b.split("/"),a=b.length;a--;)b[a]=Za(b[a]);return b.join("/")}function va(b,a){var c=Fb.exec(b),c={protocol:c[1],host:c[3],port:G(c[5])||Gb[c[1]]||
   17.56 -null,path:c[6]||"/",search:c[8],hash:c[10]};if(a)a.$$protocol=c.protocol,a.$$host=c.host,a.$$port=c.port;return c}function ka(b,a,c){return b+"://"+a+(c==Gb[b]?"":":"+c)}function Fc(b,a,c){var d=va(b);return decodeURIComponent(d.path)!=a||t(d.hash)||d.hash.indexOf(c)!==0?b:ka(d.protocol,d.host,d.port)+a.substr(0,a.lastIndexOf("/"))+d.hash.substr(c.length)}function Gc(b,a,c){var d=va(b);if(decodeURIComponent(d.path)==a)return b;else{var e=d.search&&"?"+d.search||"",g=d.hash&&"#"+d.hash||"",i=a.substr(0,
   17.57 -a.lastIndexOf("/")),f=d.path.substr(i.length);if(d.path.indexOf(i)!==0)throw B('Invalid url "'+b+'", missing path prefix "'+i+'" !');return ka(d.protocol,d.host,d.port)+a+"#"+c+f+e+g}}function gb(b,a,c){a=a||"";this.$$parse=function(b){var c=va(b,this);if(c.path.indexOf(a)!==0)throw B('Invalid url "'+b+'", missing path prefix "'+a+'" !');this.$$path=decodeURIComponent(c.path.substr(a.length));this.$$search=Xa(c.search);this.$$hash=c.hash&&decodeURIComponent(c.hash)||"";this.$$compose()};this.$$compose=
   17.58 -function(){var b=ob(this.$$search),c=this.$$hash?"#"+Za(this.$$hash):"";this.$$url=Eb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=ka(this.$$protocol,this.$$host,this.$$port)+a+this.$$url};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Ia(b,a,c){var d;this.$$parse=function(b){var c=va(b,this);if(c.hash&&c.hash.indexOf(a)!==0)throw B('Invalid url "'+b+'", missing hash prefix "'+a+'" !');d=c.path+(c.search?"?"+c.search:"");c=Hc.exec((c.hash||"").substr(a.length));
   17.59 -this.$$path=c[1]?(c[1].charAt(0)=="/"?"":"/")+decodeURIComponent(c[1]):"";this.$$search=Xa(c[3]);this.$$hash=c[5]&&decodeURIComponent(c[5])||"";this.$$compose()};this.$$compose=function(){var b=ob(this.$$search),c=this.$$hash?"#"+Za(this.$$hash):"";this.$$url=Eb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=ka(this.$$protocol,this.$$host,this.$$port)+d+(this.$$url?"#"+a+this.$$url:"")};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Hb(b,a,c,d){Ia.apply(this,arguments);
   17.60 -this.$$rewriteAppUrl=function(b){if(b.indexOf(c)==0)return c+d+"#"+a+b.substr(c.length)}}function Ja(b){return function(){return this[b]}}function Ib(b,a){return function(c){if(t(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Ic(){var b="",a=!1;this.hashPrefix=function(a){return v(a)?(b=a,this):b};this.html5Mode=function(b){return v(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function i(a){c.$broadcast("$locationChangeSuccess",
   17.61 -f.absUrl(),a)}var f,h,k,j=d.url(),l=va(j);a?(h=d.baseHref()||"/",k=h.substr(0,h.lastIndexOf("/")),l=ka(l.protocol,l.host,l.port)+k+"/",f=e.history?new gb(Fc(j,h,b),k,l):new Hb(Gc(j,h,b),b,l,h.substr(k.length+1))):(l=ka(l.protocol,l.host,l.port)+(l.path||"")+(l.search?"?"+l.search:"")+"#"+b+"/",f=new Ia(j,b,l));g.bind("click",function(a){if(!a.ctrlKey&&!(a.metaKey||a.which==2)){for(var b=u(a.target);E(b[0].nodeName)!=="a";)if(b[0]===g[0]||!(b=b.parent())[0])return;var d=b.prop("href"),e=f.$$rewriteAppUrl(d);
   17.62 -d&&!b.attr("target")&&e&&(f.$$parse(e),c.$apply(),a.preventDefault(),U.angular["ff-684208-preventDefault"]=!0)}});f.absUrl()!=j&&d.url(f.absUrl(),!0);d.onUrlChange(function(a){f.absUrl()!=a&&(c.$evalAsync(function(){var b=f.absUrl();f.$$parse(a);i(b)}),c.$$phase||c.$digest())});var o=0;c.$watch(function(){var a=d.url(),b=f.$$replace;if(!o||a!=f.absUrl())o++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",f.absUrl(),a).defaultPrevented?f.$$parse(a):(d.url(f.absUrl(),b),i(a))});f.$$replace=
   17.63 -!1;return o});return f}]}function Jc(){this.$get=["$window",function(b){function a(a){a instanceof B&&(a.stack?a=a.message&&a.stack.indexOf(a.message)===-1?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function c(c){var e=b.console||{},g=e[c]||e.log||D;return g.apply?function(){var b=[];m(arguments,function(c){b.push(a(c))});return g.apply(e,b)}:function(a,b){g(a,b)}}return{log:c("log"),warn:c("warn"),info:c("info"),error:c("error")}}]}function Kc(b,
   17.64 -a){function c(a){return a.indexOf(q)!=-1}function d(){return n+1<b.length?b.charAt(n+1):!1}function e(a){return"0"<=a&&a<="9"}function g(a){return a==" "||a=="\r"||a=="\t"||a=="\n"||a=="\u000b"||a=="\u00a0"}function i(a){return"a"<=a&&a<="z"||"A"<=a&&a<="Z"||"_"==a||a=="$"}function f(a){return a=="-"||a=="+"||e(a)}function h(a,c,d){d=d||n;throw B("Lexer Error: "+a+" at column"+(v(c)?"s "+c+"-"+n+" ["+b.substring(c,d)+"]":" "+d)+" in expression ["+b+"].");}function k(){for(var a="",c=n;n<b.length;){var k=
   17.65 -E(b.charAt(n));if(k=="."||e(k))a+=k;else{var g=d();if(k=="e"&&f(g))a+=k;else if(f(k)&&g&&e(g)&&a.charAt(a.length-1)=="e")a+=k;else if(f(k)&&(!g||!e(g))&&a.charAt(a.length-1)=="e")h("Invalid exponent");else break}n++}a*=1;o.push({index:c,text:a,json:!0,fn:function(){return a}})}function j(){for(var c="",d=n,f,k,h;n<b.length;){var j=b.charAt(n);if(j=="."||i(j)||e(j))j=="."&&(f=n),c+=j;else break;n++}if(f)for(k=n;k<b.length;){j=b.charAt(k);if(j=="("){h=c.substr(f-d+1);c=c.substr(0,f-d);n=k;break}if(g(j))k++;
   17.66 -else break}d={index:d,text:c};if(Ka.hasOwnProperty(c))d.fn=d.json=Ka[c];else{var l=Jb(c,a);d.fn=x(function(a,b){return l(a,b)},{assign:function(a,b){return Kb(a,c,b)}})}o.push(d);h&&(o.push({index:f,text:".",json:!1}),o.push({index:f+1,text:h,json:!1}))}function l(a){var c=n;n++;for(var d="",e=a,f=!1;n<b.length;){var k=b.charAt(n);e+=k;if(f)k=="u"?(k=b.substring(n+1,n+5),k.match(/[\da-f]{4}/i)||h("Invalid unicode escape [\\u"+k+"]"),n+=4,d+=String.fromCharCode(parseInt(k,16))):(f=Lc[k],d+=f?f:k),
   17.67 -f=!1;else if(k=="\\")f=!0;else if(k==a){n++;o.push({index:c,text:e,string:d,json:!0,fn:function(){return d}});return}else d+=k;n++}h("Unterminated quote",c)}for(var o=[],r,n=0,w=[],q,s=":";n<b.length;){q=b.charAt(n);if(c("\"'"))l(q);else if(e(q)||c(".")&&e(d()))k();else if(i(q)){if(j(),"{,".indexOf(s)!=-1&&w[0]=="{"&&(r=o[o.length-1]))r.json=r.text.indexOf(".")==-1}else if(c("(){}[].,;:"))o.push({index:n,text:q,json:":[,".indexOf(s)!=-1&&c("{[")||c("}]:,")}),c("{[")&&w.unshift(q),c("}]")&&w.shift(),
   17.68 -n++;else if(g(q)){n++;continue}else{var m=q+d(),C=Ka[q],A=Ka[m];A?(o.push({index:n,text:m,fn:A}),n+=2):C?(o.push({index:n,text:q,fn:C,json:"[,:".indexOf(s)!=-1&&c("+-")}),n+=1):h("Unexpected next character ",n,n+1)}s=q}return o}function Mc(b,a,c,d){function e(a,c){throw B("Syntax Error: Token '"+c.text+"' "+a+" at column "+(c.index+1)+" of the expression ["+b+"] starting at ["+b.substring(c.index)+"].");}function g(){if(M.length===0)throw B("Unexpected end of expression: "+b);return M[0]}function i(a,
   17.69 -b,c,d){if(M.length>0){var e=M[0],f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return!1}function f(b,c,d,f){return(b=i(b,c,d,f))?(a&&!b.json&&e("is not valid json",b),M.shift(),b):!1}function h(a){f(a)||e("is unexpected, expecting ["+a+"]",i())}function k(a,b){return function(c,d){return a(c,d,b)}}function j(a,b,c){return function(d,e){return b(d,e,a,c)}}function l(){for(var a=[];;)if(M.length>0&&!i("}",")",";","]")&&a.push(v()),!f(";"))return a.length==1?a[0]:function(b,c){for(var d,
   17.70 -e=0;e<a.length;e++){var f=a[e];f&&(d=f(b,c))}return d}}function o(){for(var a=f(),b=c(a.text),d=[];;)if(a=f(":"))d.push(H());else{var e=function(a,c,e){for(var e=[e],f=0;f<d.length;f++)e.push(d[f](a,c));return b.apply(a,e)};return function(){return e}}}function r(){for(var a=n(),b;;)if(b=f("||"))a=j(a,b.fn,n());else return a}function n(){var a=w(),b;if(b=f("&&"))a=j(a,b.fn,n());return a}function w(){var a=q(),b;if(b=f("==","!="))a=j(a,b.fn,w());return a}function q(){var a;a=s();for(var b;b=f("+",
   17.71 -"-");)a=j(a,b.fn,s());if(b=f("<",">","<=",">="))a=j(a,b.fn,q());return a}function s(){for(var a=m(),b;b=f("*","/","%");)a=j(a,b.fn,m());return a}function m(){var a;return f("+")?C():(a=f("-"))?j(W,a.fn,m()):(a=f("!"))?k(a.fn,m()):C()}function C(){var a;if(f("("))a=v(),h(")");else if(f("["))a=A();else if(f("{"))a=K();else{var b=f();(a=b.fn)||e("not a primary expression",b)}for(var c;b=f("(","[",".");)b.text==="("?(a=u(a,c),c=null):b.text==="["?(c=a,a=ea(a)):b.text==="."?(c=a,a=t(a)):e("IMPOSSIBLE");
   17.72 -return a}function A(){var a=[];if(g().text!="]"){do a.push(H());while(f(","))}h("]");return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}}function K(){var a=[];if(g().text!="}"){do{var b=f(),b=b.string||b.text;h(":");var c=H();a.push({key:b,value:c})}while(f(","))}h("}");return function(b,c){for(var d={},e=0;e<a.length;e++){var f=a[e],k=f.value(b,c);d[f.key]=k}return d}}var W=I(0),y,M=Kc(b,d),H=function(){var a=r(),c,d;return(d=f("="))?(a.assign||e("implies assignment but ["+
   17.73 -b.substring(0,d.index)+"] can not be assigned to",d),c=r(),function(b,d){return a.assign(b,c(b,d),d)}):a},u=function(a,b){var c=[];if(g().text!=")"){do c.push(H());while(f(","))}h(")");return function(d,e){for(var f=[],k=b?b(d,e):d,h=0;h<c.length;h++)f.push(c[h](d,e));h=a(d,e)||D;return h.apply?h.apply(k,f):h(f[0],f[1],f[2],f[3],f[4])}},t=function(a){var b=f().text,c=Jb(b,d);return x(function(b,d){return c(a(b,d),d)},{assign:function(c,d,e){return Kb(a(c,e),b,d)}})},ea=function(a){var b=H();h("]");
   17.74 -return x(function(c,d){var e=a(c,d),f=b(c,d),k;if(!e)return p;if((e=e[f])&&e.then){k=e;if(!("$$v"in e))k.$$v=p,k.then(function(a){k.$$v=a});e=e.$$v}return e},{assign:function(c,d,e){return a(c,e)[b(c,e)]=d}})},v=function(){for(var a=H(),b;;)if(b=f("|"))a=j(a,b.fn,o());else return a};a?(H=r,u=t=ea=v=function(){e("is not valid json",{text:b,index:0})},y=C()):y=l();M.length!==0&&e("is an unexpected token",M[0]);return y}function Kb(b,a,c){for(var a=a.split("."),d=0;a.length>1;d++){var e=a.shift(),g=
   17.75 -b[e];g||(g={},b[e]=g);b=g}return b[a.shift()]=c}function fb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,g=a.length,i=0;i<g;i++)d=a[i],b&&(b=(e=b)[d]);return!c&&N(b)?Va(e,b):b}function Lb(b,a,c,d,e){return function(g,i){var f=i&&i.hasOwnProperty(b)?i:g,h;if(f===null||f===p)return f;if((f=f[b])&&f.then){if(!("$$v"in f))h=f,h.$$v=p,h.then(function(a){h.$$v=a});f=f.$$v}if(!a||f===null||f===p)return f;if((f=f[a])&&f.then){if(!("$$v"in f))h=f,h.$$v=p,h.then(function(a){h.$$v=a});f=f.$$v}if(!c||f===
   17.76 -null||f===p)return f;if((f=f[c])&&f.then){if(!("$$v"in f))h=f,h.$$v=p,h.then(function(a){h.$$v=a});f=f.$$v}if(!d||f===null||f===p)return f;if((f=f[d])&&f.then){if(!("$$v"in f))h=f,h.$$v=p,h.then(function(a){h.$$v=a});f=f.$$v}if(!e||f===null||f===p)return f;if((f=f[e])&&f.then){if(!("$$v"in f))h=f,h.$$v=p,h.then(function(a){h.$$v=a});f=f.$$v}return f}}function Jb(b,a){if(hb.hasOwnProperty(b))return hb[b];var c=b.split("."),d=c.length,e;if(a)e=d<6?Lb(c[0],c[1],c[2],c[3],c[4]):function(a,b){var e=0,
   17.77 -k;do k=Lb(c[e++],c[e++],c[e++],c[e++],c[e++])(a,b),b=p,a=k;while(e<d);return k};else{var g="var l, fn, p;\n";m(c,function(a,b){g+="if(s === null || s === undefined) return s;\nl=s;\ns="+(b?"s":'((k&&k.hasOwnProperty("'+a+'"))?k:s)')+'["'+a+'"];\nif (s && s.then) {\n if (!("$$v" in s)) {\n p=s;\n p.$$v = undefined;\n p.then(function(v) {p.$$v=v;});\n}\n s=s.$$v\n}\n'});g+="return s;";e=Function("s","k",g);e.toString=function(){return g}}return hb[b]=e}function Nc(){var b={};this.$get=["$filter","$sniffer",
   17.78 -function(a,c){return function(d){switch(typeof d){case "string":return b.hasOwnProperty(d)?b[d]:b[d]=Mc(d,!1,a,c.csp);case "function":return d;default:return D}}}]}function Oc(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return Pc(function(a){b.$evalAsync(a)},a)}]}function Pc(b,a){function c(a){return a}function d(a){return i(a)}var e=function(){var f=[],h,k;return k={resolve:function(a){if(f){var c=f;f=p;h=g(a);c.length&&b(function(){for(var a,b=0,d=c.length;b<d;b++)a=c[b],h.then(a[0],
   17.79 -a[1])})}},reject:function(a){k.resolve(i(a))},promise:{then:function(b,k){var g=e(),i=function(d){try{g.resolve((b||c)(d))}catch(e){a(e),g.reject(e)}},n=function(b){try{g.resolve((k||d)(b))}catch(c){a(c),g.reject(c)}};f?f.push([i,n]):h.then(i,n);return g.promise}}}},g=function(a){return a&&a.then?a:{then:function(c){var d=e();b(function(){d.resolve(c(a))});return d.promise}}},i=function(a){return{then:function(c,k){var g=e();b(function(){g.resolve((k||d)(a))});return g.promise}}};return{defer:e,reject:i,
   17.80 -when:function(f,h,k){var j=e(),l,o=function(b){try{return(h||c)(b)}catch(d){return a(d),i(d)}},r=function(b){try{return(k||d)(b)}catch(c){return a(c),i(c)}};b(function(){g(f).then(function(a){l||(l=!0,j.resolve(g(a).then(o,r)))},function(a){l||(l=!0,j.resolve(r(a)))})});return j.promise},all:function(a){var b=e(),c=a.length,d=[];c?m(a,function(a,e){g(a).then(function(a){e in d||(d[e]=a,--c||b.resolve(d))},function(a){e in d||b.reject(a)})}):b.resolve(d);return b.promise}}}function Qc(){var b={};this.when=
   17.81 -function(a,c){b[a]=x({reloadOnSearch:!0},c);if(a){var d=a[a.length-1]=="/"?a.substr(0,a.length-1):a+"/";b[d]={redirectTo:a}}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache",function(a,c,d,e,g,i,f){function h(){var b=k(),h=r.current;if(b&&h&&b.$route===h.$route&&ha(b.pathParams,h.pathParams)&&!b.reloadOnSearch&&!o)h.params=b.params,V(h.params,d),a.$broadcast("$routeUpdate",h);else if(b||
   17.82 -h)o=!1,a.$broadcast("$routeChangeStart",b,h),(r.current=b)&&b.redirectTo&&(F(b.redirectTo)?c.path(j(b.redirectTo,b.params)).search(b.params).replace():c.url(b.redirectTo(b.pathParams,c.path(),c.search())).replace()),e.when(b).then(function(){if(b){var a=[],c=[],d;m(b.resolve||{},function(b,d){a.push(d);c.push(F(b)?g.get(b):g.invoke(b))});if(!v(d=b.template))if(v(d=b.templateUrl))d=i.get(d,{cache:f}).then(function(a){return a.data});v(d)&&(a.push("$template"),c.push(d));return e.all(c).then(function(b){var c=
   17.83 -{};m(b,function(b,d){c[a[d]]=b});return c})}}).then(function(c){if(b==r.current){if(b)b.locals=c,V(b.params,d);a.$broadcast("$routeChangeSuccess",b,h)}},function(c){b==r.current&&a.$broadcast("$routeChangeError",b,h,c)})}function k(){var a,d;m(b,function(b,e){if(!d&&(a=l(c.path(),e)))d=ya(b,{params:x({},c.search(),a),pathParams:a}),d.$route=b});return d||b[null]&&ya(b[null],{params:{},pathParams:{}})}function j(a,b){var c=[];m((a||"").split(":"),function(a,d){if(d==0)c.push(a);else{var e=a.match(/(\w+)(.*)/),
   17.84 -f=e[1];c.push(b[f]);c.push(e[2]||"");delete b[f]}});return c.join("")}var l=function(a,b){var c="^"+b.replace(/([\.\\\(\)\^\$])/g,"\\$1")+"$",d=[],e={};m(b.split(/\W/),function(a){if(a){var b=RegExp(":"+a+"([\\W])");c.match(b)&&(c=c.replace(b,"([^\\/]*)$1"),d.push(a))}});var f=a.match(RegExp(c));f&&m(d,function(a,b){e[a]=f[b+1]});return f?e:null},o=!1,r={routes:b,reload:function(){o=!0;a.$evalAsync(h)}};a.$on("$locationChangeSuccess",h);return r}]}function Rc(){this.$get=I({})}function Sc(){var b=
   17.85 -10;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse",function(a,c,d){function e(){this.$id=xa();this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this["this"]=this.$root=this;this.$$asyncQueue=[];this.$$listeners={}}function g(a){if(h.$$phase)throw B(h.$$phase+" already in progress");h.$$phase=a}function i(a,b){var c=d(a);ra(c,b);return c}function f(){}e.prototype={$new:function(a){if(N(a))throw B("API-CHANGE: Use $controller to instantiate controllers.");
   17.86 -a?(a=new e,a.$root=this.$root):(a=function(){},a.prototype=this,a=new a,a.$id=xa());a["this"]=a;a.$$listeners={};a.$parent=this;a.$$asyncQueue=[];a.$$watchers=a.$$nextSibling=a.$$childHead=a.$$childTail=null;a.$$prevSibling=this.$$childTail;this.$$childHead?this.$$childTail=this.$$childTail.$$nextSibling=a:this.$$childHead=this.$$childTail=a;return a},$watch:function(a,b,c){var d=i(a,"watch"),e=this.$$watchers,g={fn:b,last:f,get:d,exp:a,eq:!!c};if(!N(b)){var h=i(b||D,"listener");g.fn=function(a,b,
   17.87 -c){h(c)}}if(!e)e=this.$$watchers=[];e.unshift(g);return function(){Ua(e,g)}},$digest:function(){var a,d,e,i,r,n,m,q=b,s,p=[],C,A;g("$digest");do{m=!1;s=this;do{for(r=s.$$asyncQueue;r.length;)try{s.$eval(r.shift())}catch(K){c(K)}if(i=s.$$watchers)for(n=i.length;n--;)try{if(a=i[n],(d=a.get(s))!==(e=a.last)&&!(a.eq?ha(d,e):typeof d=="number"&&typeof e=="number"&&isNaN(d)&&isNaN(e)))m=!0,a.last=a.eq?V(d):d,a.fn(d,e===f?d:e,s),q<5&&(C=4-q,p[C]||(p[C]=[]),A=N(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):
   17.88 -a.exp,A+="; newVal: "+da(d)+"; oldVal: "+da(e),p[C].push(A))}catch(W){c(W)}if(!(i=s.$$childHead||s!==this&&s.$$nextSibling))for(;s!==this&&!(i=s.$$nextSibling);)s=s.$parent}while(s=i);if(m&&!q--)throw h.$$phase=null,B(b+" $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: "+da(p));}while(m||r.length);h.$$phase=null},$destroy:function(){if(h!=this){var a=this.$parent;this.$broadcast("$destroy");if(a.$$childHead==this)a.$$childHead=this.$$nextSibling;if(a.$$childTail==
   17.89 -this)a.$$childTail=this.$$prevSibling;if(this.$$prevSibling)this.$$prevSibling.$$nextSibling=this.$$nextSibling;if(this.$$nextSibling)this.$$nextSibling.$$prevSibling=this.$$prevSibling;this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null}},$eval:function(a,b){return d(a)(this,b)},$evalAsync:function(a){this.$$asyncQueue.push(a)},$apply:function(a){try{return g("$apply"),this.$eval(a)}catch(b){c(b)}finally{h.$$phase=null;try{h.$digest()}catch(d){throw c(d),d;}}},
   17.90 -$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);return function(){c[za(c,b)]=null}},$emit:function(a,b){var d=[],e,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},i=[h].concat(ia.call(arguments,1)),m,p;do{e=f.$$listeners[a]||d;h.currentScope=f;m=0;for(p=e.length;m<p;m++)if(e[m])try{if(e[m].apply(null,i),g)return h}catch(C){c(C)}else e.splice(m,1),m--,p--;f=f.$parent}while(f);
   17.91 -return h},$broadcast:function(a,b){var d=this,e=this,f={name:a,targetScope:this,preventDefault:function(){f.defaultPrevented=!0},defaultPrevented:!1},g=[f].concat(ia.call(arguments,1)),h,i;do{d=e;f.currentScope=d;e=d.$$listeners[a]||[];h=0;for(i=e.length;h<i;h++)if(e[h])try{e[h].apply(null,g)}catch(m){c(m)}else e.splice(h,1),h--,i--;if(!(e=d.$$childHead||d!==this&&d.$$nextSibling))for(;d!==this&&!(e=d.$$nextSibling);)d=d.$parent}while(d=e);return f}};var h=new e;return h}]}function Tc(){this.$get=
   17.92 -["$window",function(b){var a={},c=G((/android (\d+)/.exec(E(b.navigator.userAgent))||[])[1]);return{history:!(!b.history||!b.history.pushState||c<4),hashchange:"onhashchange"in b&&(!b.document.documentMode||b.document.documentMode>7),hasEvent:function(c){if(c=="input"&&aa==9)return!1;if(t(a[c])){var e=b.document.createElement("div");a[c]="on"+c in e}return a[c]},csp:!1}}]}function Uc(){this.$get=I(U)}function Mb(b){var a={},c,d,e;if(!b)return a;m(b.split("\n"),function(b){e=b.indexOf(":");c=E(R(b.substr(0,
   17.93 -e)));d=R(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Nb(b){var a=L(b)?b:p;return function(c){a||(a=Mb(b));return c?a[E(c)]||null:a}}function Ob(b,a,c){if(N(c))return c(b,a);m(c,function(c){b=c(b,a)});return b}function Vc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){F(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=nb(d,!0)));return d}],transformRequest:[function(a){return L(a)&&Sa.apply(a)!=="[object File]"?da(a):a}],
   17.94 -headers:{common:{Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}}},e=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,h,k,j){function l(a){function c(a){var b=x({},a,{data:Ob(a.data,a.headers,f)});return 200<=a.status&&a.status<300?b:k.reject(b)}a.method=la(a.method);var e=a.transformRequest||
   17.95 -d.transformRequest,f=a.transformResponse||d.transformResponse,h=d.headers,h=x({"X-XSRF-TOKEN":b.cookies()["XSRF-TOKEN"]},h.common,h[E(a.method)],a.headers),e=Ob(a.data,Nb(h),e),g;t(a.data)&&delete h["Content-Type"];g=o(a,e,h);g=g.then(c,c);m(w,function(a){g=a(g)});g.success=function(b){g.then(function(c){b(c.data,c.status,c.headers,a)});return g};g.error=function(b){g.then(null,function(c){b(c.data,c.status,c.headers,a)});return g};return g}function o(b,c,d){function e(a,b,c){m&&(200<=a&&a<300?m.put(w,
   17.96 -[a,b,Mb(c)]):m.remove(w));f(b,a,c);h.$apply()}function f(a,c,d){c=Math.max(c,0);(200<=c&&c<300?j.resolve:j.reject)({data:a,status:c,headers:Nb(d),config:b})}function i(){var a=za(l.pendingRequests,b);a!==-1&&l.pendingRequests.splice(a,1)}var j=k.defer(),o=j.promise,m,p,w=r(b.url,b.params);l.pendingRequests.push(b);o.then(i,i);b.cache&&b.method=="GET"&&(m=L(b.cache)?b.cache:n);if(m)if(p=m.get(w))if(p.then)return p.then(i,i),p;else J(p)?f(p[1],p[0],V(p[2])):f(p,200,{});else m.put(w,o);p||a(b.method,
   17.97 -w,c,e,d,b.timeout,b.withCredentials);return o}function r(a,b){if(!b)return a;var c=[];ec(b,function(a,b){a==null||a==p||(L(a)&&(a=da(a)),c.push(encodeURIComponent(b)+"="+encodeURIComponent(a)))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var n=c("$http"),w=[];m(e,function(a){w.push(F(a)?j.get(a):j.invoke(a))});l.pendingRequests=[];(function(a){m(arguments,function(a){l[a]=function(b,c){return l(x(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){l[a]=
   17.98 -function(b,c,d){return l(x(d||{},{method:a,url:b,data:c}))}})})("post","put");l.defaults=d;return l}]}function Wc(){this.$get=["$browser","$window","$document",function(b,a,c){return Xc(b,Yc,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function Xc(b,a,c,d,e,g){function i(a,b){var c=e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;aa?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=
   17.99 -d;e.body.appendChild(c)}return function(e,h,k,j,l,o,r){function n(a,c,d,e){c=(h.match(Fb)||["",g])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(D)}b.$$incOutstandingRequestCount();h=h||b.url();if(E(e)=="jsonp"){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a};i(h.replace("JSON_CALLBACK","angular.callbacks."+p),function(){d[p].data?n(j,200,d[p].data):n(j,-2);delete d[p]})}else{var q=new a;q.open(e,h,!0);m(l,function(a,b){a&&q.setRequestHeader(b,a)});
  17.100 -var s;q.onreadystatechange=function(){q.readyState==4&&n(j,s||q.status,q.responseText,q.getAllResponseHeaders())};if(r)q.withCredentials=!0;q.send(k||"");o>0&&c(function(){s=-1;q.abort()},o)}}}function Zc(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},
  17.101 -DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",
  17.102 -shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function $c(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,f,h){var k=c.defer(),j=k.promise,l=v(h)&&!h,f=a.defer(function(){try{k.resolve(e())}catch(a){k.reject(a),d(a)}l||b.$apply()},f),h=function(){delete g[j.$$timeoutId]};j.$$timeoutId=f;g[f]=k;j.then(h,h);return j}var g={};e.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)):
  17.103 -!1};return e}]}function Pb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Qb);a("date",Rb);a("filter",ad);a("json",bd);a("limitTo",cd);a("lowercase",dd);a("number",Sb);a("orderBy",Tb);a("uppercase",ed)}function ad(){return function(b,a){if(!(b instanceof Array))return b;var c=[];c.check=function(a){for(var b=0;b<c.length;b++)if(!c[b](a))return!1;return!0};var d=function(a,b){if(b.charAt(0)===
  17.104 -"!")return!d(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return(""+a).toLowerCase().indexOf(b)>-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;c<a.length;c++)if(d(a[c],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a={$:a};case "object":for(var e in a)e=="$"?function(){var b=(""+a[e]).toLowerCase();b&&c.push(function(a){return d(a,b)})}():function(){var b=e,f=
  17.105 -(""+a[e]).toLowerCase();f&&c.push(function(a){return d(fb(a,b),f)})}();break;case "function":c.push(a);break;default:return b}for(var g=[],i=0;i<b.length;i++){var f=b[i];c.check(f)&&g.push(f)}return g}}function Qb(b){var a=b.NUMBER_FORMATS;return function(b,d){if(t(d))d=a.CURRENCY_SYM;return Ub(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,2).replace(/\u00A4/g,d)}}function Sb(b){var a=b.NUMBER_FORMATS;return function(b,d){return Ub(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Ub(b,a,c,d,e){if(isNaN(b)||
  17.106 -!isFinite(b))return"";var g=b<0,b=Math.abs(b),i=b+"",f="",h=[],k=!1;if(i.indexOf("e")!==-1){var j=i.match(/([\d\.]+)e(-?)(\d+)/);j&&j[2]=="-"&&j[3]>e+1?i="0":(f=i,k=!0)}if(!k){i=(i.split(Vb)[1]||"").length;t(e)&&(e=Math.min(Math.max(a.minFrac,i),a.maxFrac));var i=Math.pow(10,e),b=Math.round(b*i)/i,b=(""+b).split(Vb),i=b[0],b=b[1]||"",k=0,j=a.lgSize,l=a.gSize;if(i.length>=j+l)for(var k=i.length-j,o=0;o<k;o++)(k-o)%l===0&&o!==0&&(f+=c),f+=i.charAt(o);for(o=k;o<i.length;o++)(i.length-o)%j===0&&o!==0&&
  17.107 -(f+=c),f+=i.charAt(o);for(;b.length<e;)b+="0";e&&(f+=d+b.substr(0,e))}h.push(g?a.negPre:a.posPre);h.push(f);h.push(g?a.negSuf:a.posSuf);return h.join("")}function ib(b,a,c){var d="";b<0&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function P(b,a,c,d){return function(e){e=e["get"+b]();if(c>0||e>-c)e+=c;e===0&&c==-12&&(e=12);return ib(e,a,d)}}function La(b,a){return function(c,d){var e=c["get"+b](),g=la(a?"SHORT"+b:b);return d[g][e]}}function Rb(b){function a(a){var b;
  17.108 -if(b=a.match(c)){var a=new Date(0),g=0,i=0;b[9]&&(g=G(b[9]+b[10]),i=G(b[9]+b[11]));a.setUTCFullYear(G(b[1]),G(b[2])-1,G(b[3]));a.setUTCHours(G(b[4]||0)-g,G(b[5]||0)-i,G(b[6]||0),G(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g="",i=[],f,h,e=e||"mediumDate",e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=fd.test(c)?G(c):a(c));wa(c)&&(c=new Date(c));if(!na(c))return c;for(;e;)(h=gd.exec(e))?(i=i.concat(ia.call(h,
  17.109 -1)),e=i.pop()):(i.push(e),e=null);m(i,function(a){f=hd[a];g+=f?f(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function bd(){return function(b){return da(b,!0)}}function cd(){return function(b,a){if(!(b instanceof Array))return b;var a=G(a),c=[],d,e;if(!b||!(b instanceof Array))return c;a>b.length?a=b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function Tb(b){return function(a,c,d){function e(a,b){return Wa(b)?
  17.110 -function(b,c){return a(c,b)}:a}if(!(a instanceof Array))return a;if(!c)return a;for(var c=J(c)?c:[c],c=Ta(c,function(a){var c=!1,d=a||ma;if(F(a)){if(a.charAt(0)=="+"||a.charAt(0)=="-")c=a.charAt(0)=="-",a=a.substring(1);d=b(a)}return e(function(a,b){var c;c=d(a);var e=d(b),f=typeof c,g=typeof e;f==g?(f=="string"&&(c=c.toLowerCase()),f=="string"&&(e=e.toLowerCase()),c=c===e?0:c<e?-1:1):c=f<g?-1:1;return c},c)}),g=[],i=0;i<a.length;i++)g.push(a[i]);return g.sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=
  17.111 -c[d](a,b);if(e!==0)return e}return 0},d))}}function S(b){N(b)&&(b={link:b});b.restrict=b.restrict||"AC";return I(b)}function Wb(b,a){function c(a,c){c=c?"-"+$a(c,"-"):"";b.removeClass((a?Ma:Na)+c).addClass((a?Na:Ma)+c)}var d=this,e=b.parent().controller("form")||Oa,g=0,i=d.$error={};d.$name=a.name;d.$dirty=!1;d.$pristine=!0;d.$valid=!0;d.$invalid=!1;e.$addControl(d);b.addClass(Pa);c(!0);d.$addControl=function(a){a.$name&&!d.hasOwnProperty(a.$name)&&(d[a.$name]=a)};d.$removeControl=function(a){a.$name&&
  17.112 -d[a.$name]===a&&delete d[a.$name];m(i,function(b,c){d.$setValidity(c,!0,a)})};d.$setValidity=function(a,b,k){var j=i[a];if(b){if(j&&(Ua(j,k),!j.length)){g--;if(!g)c(b),d.$valid=!0,d.$invalid=!1;i[a]=!1;c(!0,a);e.$setValidity(a,!0,d)}}else{g||c(b);if(j){if(za(j,k)!=-1)return}else i[a]=j=[],g++,c(!1,a),e.$setValidity(a,!1,d);j.push(k);d.$valid=!1;d.$invalid=!0}};d.$setDirty=function(){b.removeClass(Pa).addClass(Xb);d.$dirty=!0;d.$pristine=!1;e.$setDirty()}}function T(b){return t(b)||b===""||b===null||
  17.113 -b!==b}function Qa(b,a,c,d,e,g){var i=function(){var c=R(a.val());d.$viewValue!==c&&b.$apply(function(){d.$setViewValue(c)})};if(e.hasEvent("input"))a.bind("input",i);else{var f;a.bind("keydown",function(a){a=a.keyCode;a===91||15<a&&a<19||37<=a&&a<=40||f||(f=g.defer(function(){i();f=null}))});a.bind("change",i)}d.$render=function(){a.val(T(d.$viewValue)?"":d.$viewValue)};var h=c.ngPattern,k=function(a,b){return T(b)||a.test(b)?(d.$setValidity("pattern",!0),b):(d.$setValidity("pattern",!1),p)};h&&(h.match(/^\/(.*)\/$/)?
  17.114 -(h=RegExp(h.substr(1,h.length-2)),e=function(a){return k(h,a)}):e=function(a){var c=b.$eval(h);if(!c||!c.test)throw new B("Expected "+h+" to be a RegExp but was "+c);return k(c,a)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var j=G(c.ngMinlength),e=function(a){return!T(a)&&a.length<j?(d.$setValidity("minlength",!1),p):(d.$setValidity("minlength",!0),a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var l=G(c.ngMaxlength),c=function(a){return!T(a)&&a.length>l?(d.$setValidity("maxlength",
  17.115 -!1),p):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(c);d.$formatters.push(c)}}function jb(b,a){b="ngClass"+b;return S(function(c,d,e){function g(b,d){if(a===!0||c.$index%2===a)d&&b!==d&&i(d),f(b)}function i(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));d.removeClass(J(a)?a.join(" "):a)}function f(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));a&&d.addClass(J(a)?a.join(" "):a)}c.$watch(e[b],g,!0);e.$observe("class",function(){var a=c.$eval(e[b]);g(a,a)});b!=="ngClass"&&c.$watch("$index",
  17.116 -function(d,g){var j=d%2;j!==g%2&&(j==a?f(c.$eval(e[b])):i(c.$eval(e[b])))})})}var E=function(b){return F(b)?b.toLowerCase():b},la=function(b){return F(b)?b.toUpperCase():b},B=U.Error,aa=G((/msie (\d+)/.exec(E(navigator.userAgent))||[])[1]),u,ja,ia=[].slice,Ra=[].push,Sa=Object.prototype.toString,Yb=U.angular||(U.angular={}),ta,Cb,Z=["0","0","0"];D.$inject=[];ma.$inject=[];Cb=aa<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?la(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?
  17.117 -b.nodeName:b[0].nodeName};var kc=/[A-Z]/g,id={full:"1.0.3",major:1,minor:0,dot:3,codeName:"bouncy-thunder"},Ba=Q.cache={},Aa=Q.expando="ng-"+(new Date).getTime(),oc=1,Zb=U.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},db=U.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},mc=/([\:\-\_]+(.))/g,nc=/^moz([A-Z])/,ua=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}
  17.118 -var c=!1;this.bind("DOMContentLoaded",a);Q(U).bind("load",a)},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?u(this[b]):u(this[this.length+b])},length:0,push:Ra,sort:[].sort,splice:[].splice},Ea={};m("multiple,selected,checked,disabled,readOnly,required".split(","),function(b){Ea[E(b)]=b});var zb={};m("input,select,option,textarea,button,form".split(","),function(b){zb[la(b)]=!0});m({data:ub,inheritedData:Da,scope:function(b){return Da(b,
  17.119 -"$scope")},controller:xb,injector:function(b){return Da(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Ca,css:function(b,a,c){a=rb(a);if(v(c))b.style[a]=c;else{var d;aa<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];aa<=8&&(d=d===""?p:d);return d}},attr:function(b,a,c){var d=E(a);if(Ea[d])if(v(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||D).specified?d:p;else if(v(c))b.setAttribute(a,
  17.120 -c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?p:b},prop:function(b,a,c){if(v(c))b[a]=c;else return b[a]},text:x(aa<9?function(b,a){if(b.nodeType==1){if(t(a))return b.innerText;b.innerText=a}else{if(t(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(t(a))return b.textContent;b.textContent=a},{$dv:""}),val:function(b,a){if(t(a))return b.value;b.value=a},html:function(b,a){if(t(a))return b.innerHTML;for(var c=0,d=b.childNodes;c<d.length;c++)sa(d[c]);b.innerHTML=a}},function(b,
  17.121 -a){Q.prototype[a]=function(a,d){var e,g;if((b.length==2&&b!==Ca&&b!==xb?a:d)===p)if(L(a)){for(e=0;e<this.length;e++)if(b===ub)b(this[e],a);else for(g in a)b(this[e],g,a[g]);return this}else{if(this.length)return b(this[0],a,d)}else{for(e=0;e<this.length;e++)b(this[e],a,d);return this}return b.$dv}});m({removeData:sb,dealoc:sa,bind:function a(c,d,e){var g=$(c,"events"),i=$(c,"handle");g||$(c,"events",g={});i||$(c,"handle",i=pc(c,g));m(d.split(" "),function(d){var h=g[d];if(!h){if(d=="mouseenter"||
  17.122 -d=="mouseleave"){var k=0;g.mouseenter=[];g.mouseleave=[];a(c,"mouseover",function(a){k++;k==1&&i(a,"mouseenter")});a(c,"mouseout",function(a){k--;k==0&&i(a,"mouseleave")})}else Zb(c,d,i),g[d]=[];h=g[d]}h.push(e)})},unbind:tb,replaceWith:function(a,c){var d,e=a.parentNode;sa(a);m(new Q(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];m(a.childNodes,function(a){a.nodeName!="#text"&&c.push(a)});return c},contents:function(a){return a.childNodes},
  17.123 -append:function(a,c){m(new Q(c),function(c){a.nodeType===1&&a.appendChild(c)})},prepend:function(a,c){if(a.nodeType===1){var d=a.firstChild;m(new Q(c),function(c){d?a.insertBefore(c,d):(a.appendChild(c),d=c)})}},wrap:function(a,c){var c=u(c)[0],d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:function(a){sa(a);var c=a.parentNode;c&&c.removeChild(a)},after:function(a,c){var d=a,e=a.parentNode;m(new Q(c),function(a){e.insertBefore(a,d.nextSibling);d=a})},addClass:wb,removeClass:vb,toggleClass:function(a,
  17.124 -c,d){t(d)&&(d=!Ca(a,c));(d?wb:vb)(a,c)},parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},next:function(a){return a.nextSibling},find:function(a,c){return a.getElementsByTagName(c)},clone:cb,triggerHandler:function(a,c){var d=($(a,"events")||{})[c];m(d,function(c){c.call(a,null)})}},function(a,c){Q.prototype[c]=function(c,e){for(var g,i=0;i<this.length;i++)g==p?(g=a(this[i],c,e),g!==p&&(g=u(g))):bb(g,a(this[i],c,e));return g==p?this:g}});Fa.prototype={put:function(a,c){this[ga(a)]=
  17.125 -c},get:function(a){return this[ga(a)]},remove:function(a){var c=this[a=ga(a)];delete this[a];return c}};eb.prototype={push:function(a,c){var d=this[a=ga(a)];d?d.push(c):this[a]=[c]},shift:function(a){var c=this[a=ga(a)];if(c)return c.length==1?(delete this[a],c[0]):c.shift()},peek:function(a){if(a=this[ga(a)])return a[0]}};var rc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,sc=/,/,tc=/^\s*(_?)(\S+?)\1\s*$/,qc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Db="Non-assignable model expression: ";Bb.$inject=["$provide"];
  17.126 -var Ac=/^(x[\:\-_]|data[\:\-_])/i,Fb=/^([^:]+):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,$b=/^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,Hc=$b,Gb={http:80,https:443,ftp:21};gb.prototype={$$replace:!1,absUrl:Ja("$$absUrl"),url:function(a,c){if(t(a))return this.$$url;var d=$b.exec(a);d[1]&&this.path(decodeURIComponent(d[1]));if(d[2]||d[1])this.search(d[3]||"");this.hash(d[5]||"",c);return this},protocol:Ja("$$protocol"),host:Ja("$$host"),port:Ja("$$port"),path:Ib("$$path",function(a){return a.charAt(0)==
  17.127 -"/"?a:"/"+a}),search:function(a,c){if(t(a))return this.$$search;v(c)?c===null?delete this.$$search[a]:this.$$search[a]=c:this.$$search=F(a)?Xa(a):a;this.$$compose();return this},hash:Ib("$$hash",ma),replace:function(){this.$$replace=!0;return this}};Ia.prototype=ya(gb.prototype);Hb.prototype=ya(Ia.prototype);var Ka={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:D,"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return v(d)?v(e)?d+e:d:v(e)?e:p},"-":function(a,
  17.128 -c,d,e){d=d(a,c);e=e(a,c);return(v(d)?d:0)-(v(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"^":function(a,c,d,e){return d(a,c)^e(a,c)},"=":D,"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,
  17.129 -c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Lc={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},hb={},Yc=U.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw new B("This browser does not support XMLHttpRequest.");
  17.130 -};Pb.$inject=["$provide"];Qb.$inject=["$locale"];Sb.$inject=["$locale"];var Vb=".",hd={yyyy:P("FullYear",4),yy:P("FullYear",2,0,!0),y:P("FullYear",1),MMMM:La("Month"),MMM:La("Month",!0),MM:P("Month",2,1),M:P("Month",1,1),dd:P("Date",2),d:P("Date",1),HH:P("Hours",2),H:P("Hours",1),hh:P("Hours",2,-12),h:P("Hours",1,-12),mm:P("Minutes",2),m:P("Minutes",1),ss:P("Seconds",2),s:P("Seconds",1),EEEE:La("Day"),EEE:La("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=a.getTimezoneOffset();
  17.131 -return ib(a/60,2)+ib(Math.abs(a%60),2)}},gd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,fd=/^\d+$/;Rb.$inject=["$locale"];var dd=I(E),ed=I(la);Tb.$inject=["$parse"];var jd=I({restrict:"E",compile:function(a,c){c.href||c.$set("href","");return function(a,c){c.bind("click",function(a){if(!c.attr("href"))return a.preventDefault(),!1})}}}),kb={};m(Ea,function(a,c){var d=fa("ng-"+c);kb[d]=function(){return{priority:100,compile:function(){return function(a,g,i){a.$watch(i[d],
  17.132 -function(a){i.$set(c,!!a)})}}}}});m(["src","href"],function(a){var c=fa("ng-"+a);kb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),aa&&e.prop(a,c))})}}}});var Oa={$addControl:D,$removeControl:D,$setValidity:D,$setDirty:D};Wb.$inject=["$element","$attrs","$scope"];var Ra=function(a){return["$timeout",function(c){var d={name:"form",restrict:"E",controller:Wb,compile:function(){return{pre:function(a,d,i,f){if(!i.action){var h=function(a){a.preventDefault?
  17.133 -a.preventDefault():a.returnValue=!1};Zb(d[0],"submit",h);d.bind("$destroy",function(){c(function(){db(d[0],"submit",h)},0,!1)})}var k=d.parent().controller("form"),j=i.name||i.ngForm;j&&(a[j]=f);k&&d.bind("$destroy",function(){k.$removeControl(f);j&&(a[j]=p);x(f,Oa)})}}}};return a?x(V(d),{restrict:"EAC"}):d}]},kd=Ra(),ld=Ra(!0),md=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,nd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,od=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,
  17.134 -ac={text:Qa,number:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);e.$parsers.push(function(a){var c=T(a);return c||od.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),p)});e.$formatters.push(function(a){return T(a)?"":""+a});if(d.min){var f=parseFloat(d.min),a=function(a){return!T(a)&&a<f?(e.$setValidity("min",!1),p):(e.$setValidity("min",!0),a)};e.$parsers.push(a);e.$formatters.push(a)}if(d.max){var h=parseFloat(d.max),d=function(a){return!T(a)&&a>h?(e.$setValidity("max",
  17.135 -!1),p):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return T(a)||wa(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),p)})},url:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||md.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),p)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||nd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email",
  17.136 -!1),p)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){t(d.name)&&c.attr("name",xa());c.bind("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,i=d.ngFalseValue;F(g)||(g=!0);F(i)||(i=!1);c.bind("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a===
  17.137 -g});e.$parsers.push(function(a){return a?g:i})},hidden:D,button:D,submit:D,reset:D},bc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,i){i&&(ac[E(g.type)]||ac.text)(d,e,g,i,c,a)}}}],Na="ng-valid",Ma="ng-invalid",Pa="ng-pristine",Xb="ng-dirty",pd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function i(a,c){c=c?"-"+$a(c,"-"):"";e.removeClass((a?Ma:Na)+c).addClass((a?Na:Ma)+c)}this.$modelValue=this.$viewValue=Number.NaN;
  17.138 -this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var f=g(d.ngModel),h=f.assign;if(!h)throw B(Db+d.ngModel+" ("+pa(e)+")");this.$render=D;var k=e.inheritedData("$formController")||Oa,j=0,l=this.$error={};e.addClass(Pa);i(!0);this.$setValidity=function(a,c){if(l[a]!==!c){if(c){if(l[a]&&j--,!j)i(!0),this.$valid=!0,this.$invalid=!1}else i(!1),this.$invalid=!0,this.$valid=!1,j++;l[a]=!c;i(c,a);k.$setValidity(a,
  17.139 -c,this)}};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=!0,this.$pristine=!1,e.removeClass(Pa).addClass(Xb),k.$setDirty();m(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,h(a,d),m(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};var o=this;a.$watch(function(){var c=f(a);if(o.$modelValue!==c){var d=o.$formatters,e=d.length;for(o.$modelValue=c;e--;)c=d[e](c);if(o.$viewValue!==c)o.$viewValue=c,o.$render()}})}],qd=function(){return{require:["ngModel",
  17.140 -"^?form"],controller:pd,link:function(a,c,d,e){var g=e[0],i=e[1]||Oa;i.$addControl(g);c.bind("$destroy",function(){i.$removeControl(g)})}}},rd=I({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),cc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&(T(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);
  17.141 -d.$observe("required",function(){g(e.$viewValue)})}}}},sd=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&m(a.split(g),function(a){a&&c.push(R(a))});return c});e.$formatters.push(function(a){return J(a)?a.join(", "):p})}}},td=/^(true|false|\d+)$/,ud=function(){return{priority:100,compile:function(a,c){return td.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a,
  17.142 -c,g){a.$watch(g.ngValue,function(a){g.$set("value",a,!1)})}}}},vd=S(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==p?"":a)})}),wd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],xd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe,
  17.143 -function(a){c.html(a||"")})}}],yd=jb("",!0),zd=jb("Odd",0),Ad=jb("Even",1),Bd=S({compile:function(a,c){c.$set("ngCloak",p);a.removeClass("ng-cloak")}}),Cd=[function(){return{scope:!0,controller:"@"}}],Dd=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],dc={};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave".split(" "),function(a){var c=fa("ng-"+a);dc[c]=["$parse",function(d){return function(e,g,i){var f=d(i[c]);g.bind(E(a),function(a){e.$apply(function(){f(e,
  17.144 -{$event:a})})})}}]});var Ed=S(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),Fd=["$http","$templateCache","$anchorScroll","$compile",function(a,c,d,e){return{restrict:"ECA",terminal:!0,compile:function(g,i){var f=i.ngInclude||i.src,h=i.onload||"",k=i.autoscroll;return function(g,i){var o=0,m,n=function(){m&&(m.$destroy(),m=null);i.html("")};g.$watch(f,function(f){var p=++o;f?a.get(f,{cache:c}).success(function(a){p===o&&(m&&m.$destroy(),m=g.$new(),i.html(a),e(i.contents())(m),
  17.145 -v(k)&&(!k||g.$eval(k))&&d(),m.$emit("$includeContentLoaded"),g.$eval(h))}).error(function(){p===o&&n()}):n()})}}}}],Gd=S({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Hd=S({terminal:!0,priority:1E3}),Id=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,i){var f=i.count,h=g.attr(i.$attr.when),k=i.offset||0,j=e.$eval(h),l={},o=c.startSymbol(),r=c.endSymbol();m(j,function(a,e){l[e]=c(a.replace(d,o+f+"-"+k+r))});e.$watch(function(){var c=
  17.146 -parseFloat(e.$eval(f));return isNaN(c)?"":(j[c]||(c=a.pluralCat(c-k)),l[c](e,g,!0))},function(a){g.text(a)})}}}],Jd=S({transclude:"element",priority:1E3,terminal:!0,compile:function(a,c,d){return function(a,c,i){var f=i.ngRepeat,i=f.match(/^\s*(.+)\s+in\s+(.*)\s*$/),h,k,j;if(!i)throw B("Expected ngRepeat in form of '_item_ in _collection_' but got '"+f+"'.");f=i[1];h=i[2];i=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!i)throw B("'item' in 'item in collection' should be identifier or (key, value) but got '"+
  17.147 -f+"'.");k=i[3]||i[1];j=i[2];var l=new eb;a.$watch(function(a){var e,f,i=a.$eval(h),m=gc(i,!0),p,u=new eb,C,A,v,t,y=c;if(J(i))v=i||[];else{v=[];for(C in i)i.hasOwnProperty(C)&&C.charAt(0)!="$"&&v.push(C);v.sort()}e=0;for(f=v.length;e<f;e++){C=i===v?e:v[e];A=i[C];if(t=l.shift(A)){p=t.scope;u.push(A,t);if(e!==t.index)t.index=e,y.after(t.element);y=t.element}else p=a.$new();p[k]=A;j&&(p[j]=C);p.$index=e;p.$first=e===0;p.$last=e===m-1;p.$middle=!(p.$first||p.$last);t||d(p,function(a){y.after(a);t={scope:p,
  17.148 -element:y=a,index:e};u.push(A,t)})}for(C in l)if(l.hasOwnProperty(C))for(v=l[C];v.length;)A=v.pop(),A.element.remove(),A.scope.$destroy();l=u})}}}),Kd=S(function(a,c,d){a.$watch(d.ngShow,function(a){c.css("display",Wa(a)?"":"none")})}),Ld=S(function(a,c,d){a.$watch(d.ngHide,function(a){c.css("display",Wa(a)?"none":"")})}),Md=S(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&m(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Nd=I({restrict:"EA",compile:function(a,c){var d=c.ngSwitch||c.on,
  17.149 -e={};a.data("ng-switch",e);return function(a,i){var f,h,k;a.$watch(d,function(d){h&&(k.$destroy(),h.remove(),h=k=null);if(f=e["!"+d]||e["?"])a.$eval(c.change),k=a.$new(),f(k,function(a){h=a;i.append(a)})})}}}),Od=S({transclude:"element",priority:500,compile:function(a,c,d){a=a.inheritedData("ng-switch");qa(a);a["!"+c.ngSwitchWhen]=d}}),Pd=S({transclude:"element",priority:500,compile:function(a,c,d){a=a.inheritedData("ng-switch");qa(a);a["?"]=d}}),Qd=S({controller:["$transclude","$element",function(a,
  17.150 -c){a(function(a){c.append(a)})}]}),Rd=["$http","$templateCache","$route","$anchorScroll","$compile","$controller",function(a,c,d,e,g,i){return{restrict:"ECA",terminal:!0,link:function(a,c,k){function j(){var j=d.current&&d.current.locals,k=j&&j.$template;if(k){c.html(k);l&&(l.$destroy(),l=null);var k=g(c.contents()),p=d.current;l=p.scope=a.$new();if(p.controller)j.$scope=l,j=i(p.controller,j),c.contents().data("$ngControllerController",j);k(l);l.$emit("$viewContentLoaded");l.$eval(m);e()}else c.html(""),
  17.151 -l&&(l.$destroy(),l=null)}var l,m=k.onload||"";a.$on("$routeChangeSuccess",j);j()}}}],Sd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){d.type=="text/ng-template"&&a.put(d.id,c[0].text)}}}],Td=I({terminal:!0}),Ud=["$compile","$parse",function(a,c){var d=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,e={$setViewValue:D};return{restrict:"E",require:["select",
  17.152 -"?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var h=this,k={},j=e,l;h.databound=d.ngModel;h.init=function(a,c,d){j=a;l=d};h.addOption=function(c){k[c]=!0;j.$viewValue==c&&(a.val(c),l.parent()&&l.remove())};h.removeOption=function(a){this.hasOption(a)&&(delete k[a],j.$viewValue==a&&this.renderUnknownOption(a))};h.renderUnknownOption=function(c){c="? "+ga(c)+" ?";l.val(c);a.prepend(l);a.val(c);l.prop("selected",!0)};h.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",
  17.153 -function(){h.renderUnknownOption=D})}],link:function(e,i,f,h){function k(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(A.parent()&&A.remove(),c.val(a),a===""&&s.prop("selected",!0)):t(a)&&s?c.val(""):e.renderUnknownOption(a)};c.bind("change",function(){a.$apply(function(){A.parent()&&A.remove();d.$setViewValue(c.val())})})}function j(a,c,d){var e;d.$render=function(){var a=new Fa(d.$viewValue);m(c.children(),function(c){c.selected=v(a.get(c.value))})};a.$watch(function(){ha(e,d.$viewValue)||
  17.154 -(e=V(d.$viewValue),d.$render())});c.bind("change",function(){a.$apply(function(){var a=[];m(c.children(),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function l(e,f,g){function h(){var a={"":[]},c=[""],d,i,s,t,u;s=g.$modelValue;t=r(e)||[];var y=l?lb(t):t,A,w,x;w={};u=!1;var z,B;if(n)u=new Fa(s);else if(s===null||q)a[""].push({selected:s===null,id:"",label:""}),u=!0;for(x=0;A=y.length,x<A;x++){w[k]=t[l?w[l]=y[x]:x];d=m(e,w)||"";if(!(i=a[d]))i=a[d]=[],c.push(d);n?d=u.remove(o(e,
  17.155 -w))!=p:(d=s===o(e,w),u=u||d);z=j(e,w);z=z===p?"":z;i.push({id:l?y[x]:x,label:z,selected:d})}!n&&!u&&a[""].unshift({id:"?",label:"",selected:!0});w=0;for(y=c.length;w<y;w++){d=c[w];i=a[d];if(v.length<=w)s={element:C.clone().attr("label",d),label:i.label},t=[s],v.push(t),f.append(s.element);else if(t=v[w],s=t[0],s.label!=d)s.element.attr("label",s.label=d);z=null;x=0;for(A=i.length;x<A;x++)if(d=i[x],u=t[x+1]){z=u.element;if(u.label!==d.label)z.text(u.label=d.label);if(u.id!==d.id)z.val(u.id=d.id);if(u.element.selected!==
  17.156 -d.selected)z.prop("selected",u.selected=d.selected)}else d.id===""&&q?B=q:(B=D.clone()).val(d.id).attr("selected",d.selected).text(d.label),t.push({element:B,label:d.label,id:d.id,selected:d.selected}),z?z.after(B):s.element.append(B),z=B;for(x++;t.length>x;)t.pop().element.remove()}for(;v.length>w;)v.pop()[0].element.remove()}var i;if(!(i=w.match(d)))throw B("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+w+"'.");var j=c(i[2]||i[1]),k=i[4]||
  17.157 -i[6],l=i[5],m=c(i[3]||""),o=c(i[2]?i[1]:k),r=c(i[7]),v=[[{element:f,label:""}]];q&&(a(q)(e),q.removeClass("ng-scope"),q.remove());f.html("");f.bind("change",function(){e.$apply(function(){var a,c=r(e)||[],d={},h,i,j,m,q,s;if(n){i=[];m=0;for(s=v.length;m<s;m++){a=v[m];j=1;for(q=a.length;j<q;j++)if((h=a[j].element)[0].selected)h=h.val(),l&&(d[l]=h),d[k]=c[h],i.push(o(e,d))}}else h=f.val(),h=="?"?i=p:h==""?i=null:(d[k]=c[h],l&&(d[l]=h),i=o(e,d));g.$setViewValue(i)})});g.$render=h;e.$watch(h)}if(h[1]){for(var o=
  17.158 -h[0],r=h[1],n=f.multiple,w=f.ngOptions,q=!1,s,D=u(ca.createElement("option")),C=u(ca.createElement("optgroup")),A=D.clone(),h=0,x=i.children(),E=x.length;h<E;h++)if(x[h].value==""){s=q=x.eq(h);break}o.init(r,q,A);if(n&&(f.required||f.ngRequired)){var y=function(a){r.$setValidity("required",!f.required||a&&a.length);return a};r.$parsers.push(y);r.$formatters.unshift(y);f.$observe("required",function(){y(r.$viewValue)})}w?l(e,i,r):n?j(e,i,r):k(e,i,r,o)}}}}],Vd=["$interpolate",function(a){var c={addOption:D,
  17.159 -removeOption:D};return{restrict:"E",priority:100,compile:function(d,e){if(t(e.value)){var g=a(d.text(),!0);g||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),j=k.data("$selectController")||k.parent().data("$selectController");j&&j.databound?d.prop("selected",!1):j=c;g?a.$watch(g,function(a,c){e.$set("value",a);a!==c&&j.removeOption(c);j.addOption(a)}):j.addOption(e.value);d.bind("$destroy",function(){j.removeOption(e.value)})}}}}],Wd=I({restrict:"E",terminal:!0});(ja=U.jQuery)?(u=
  17.160 -ja,x(ja.fn,{scope:ua.scope,controller:ua.controller,injector:ua.injector,inheritedData:ua.inheritedData}),ab("remove",!0),ab("empty"),ab("html")):u=Q;Yb.element=u;(function(a){x(a,{bootstrap:pb,copy:V,extend:x,equals:ha,element:u,forEach:m,injector:qb,noop:D,bind:Va,toJson:da,fromJson:nb,identity:ma,isUndefined:t,isDefined:v,isString:F,isFunction:N,isObject:L,isNumber:wa,isElement:fc,isArray:J,version:id,isDate:na,lowercase:E,uppercase:la,callbacks:{counter:0}});ta=lc(U);try{ta("ngLocale")}catch(c){ta("ngLocale",
  17.161 -[]).provider("$locale",Zc)}ta("ng",["ngLocale"],["$provide",function(a){a.provider("$compile",Bb).directive({a:jd,input:bc,textarea:bc,form:kd,script:Sd,select:Ud,style:Wd,option:Vd,ngBind:vd,ngBindHtmlUnsafe:xd,ngBindTemplate:wd,ngClass:yd,ngClassEven:Ad,ngClassOdd:zd,ngCsp:Dd,ngCloak:Bd,ngController:Cd,ngForm:ld,ngHide:Ld,ngInclude:Fd,ngInit:Gd,ngNonBindable:Hd,ngPluralize:Id,ngRepeat:Jd,ngShow:Kd,ngSubmit:Ed,ngStyle:Md,ngSwitch:Nd,ngSwitchWhen:Od,ngSwitchDefault:Pd,ngOptions:Td,ngView:Rd,ngTransclude:Qd,
  17.162 -ngModel:qd,ngList:sd,ngChange:rd,required:cc,ngRequired:cc,ngValue:ud}).directive(kb).directive(dc);a.provider({$anchorScroll:uc,$browser:wc,$cacheFactory:xc,$controller:Bc,$document:Cc,$exceptionHandler:Dc,$filter:Pb,$interpolate:Ec,$http:Vc,$httpBackend:Wc,$location:Ic,$log:Jc,$parse:Nc,$route:Qc,$routeParams:Rc,$rootScope:Sc,$q:Oc,$sniffer:Tc,$templateCache:yc,$timeout:$c,$window:Uc})}])})(Yb);u(ca).ready(function(){jc(ca,pb)})})(window,document);angular.element(document).find("head").append('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}</style>');
    18.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js	Tue Apr 29 15:25:58 2014 +0200
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,224 +0,0 @@
    18.4 -// 'use strict';
    18.5 -
    18.6 -// Declare app level module which depends on filters, and services
    18.7 -angular.module('bck2brwsr', []).
    18.8 -  directive('uiCodemirror', ['$timeout', function($timeout) {
    18.9 -        'use strict';
   18.10 -
   18.11 -        var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"];
   18.12 -        return {
   18.13 -            restrict: 'A',
   18.14 -            require: 'ngModel',
   18.15 -            link: function(scope, elm, attrs, ngModel) {
   18.16 -                var options, opts, onChange, deferCodeMirror, codeMirror, timeoutId, val;
   18.17 -
   18.18 -                if (elm[0].type !== 'textarea') {
   18.19 -                    throw new Error('uiCodemirror3 can only be applied to a textarea element');
   18.20 -                }
   18.21 -
   18.22 -                options = /* uiConfig.codemirror  || */ {};
   18.23 -                opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror));
   18.24 -
   18.25 -                onChange = function(instance, changeObj) {                    
   18.26 -                    val = instance.getValue();
   18.27 -                    $timeout.cancel(timeoutId);
   18.28 -                    timeoutId = $timeout(function() {
   18.29 -                        ngModel.$setViewValue(val);                        
   18.30 -                      }, 500);                    
   18.31 -                };
   18.32 -                
   18.33 -                deferCodeMirror = function() {
   18.34 -                    codeMirror = CodeMirror.fromTextArea(elm[0], opts);
   18.35 -                    elm[0].codeMirror = codeMirror;
   18.36 -                    // codeMirror.on("change", onChange(opts.onChange));
   18.37 -                    codeMirror.on("change", onChange);
   18.38 -
   18.39 -                    for (var i = 0, n = events.length, aEvent; i < n; ++i) {
   18.40 -                        aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)];
   18.41 -                        if (aEvent === void 0)
   18.42 -                            continue;
   18.43 -                        if (typeof aEvent !== "function")
   18.44 -                            continue;
   18.45 -                                                
   18.46 -                        var bound = _.bind( aEvent, scope );
   18.47 -                        
   18.48 -                        codeMirror.on(events[i], bound);
   18.49 -                    }
   18.50 -
   18.51 -                    // CodeMirror expects a string, so make sure it gets one.
   18.52 -                    // This does not change the model.
   18.53 -                    ngModel.$formatters.push(function(value) {
   18.54 -                        if (angular.isUndefined(value) || value === null) {
   18.55 -                            return '';
   18.56 -                        }
   18.57 -                        else if (angular.isObject(value) || angular.isArray(value)) {
   18.58 -                            throw new Error('ui-codemirror cannot use an object or an array as a model');
   18.59 -                        }
   18.60 -                        return value;
   18.61 -                    });
   18.62 -
   18.63 -                    // Override the ngModelController $render method, which is what gets called when the model is updated.
   18.64 -                    // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
   18.65 -                    ngModel.$render = function() {
   18.66 -                        codeMirror.setValue(ngModel.$viewValue);
   18.67 -                    };
   18.68 -
   18.69 -                };
   18.70 -
   18.71 -                $timeout(deferCodeMirror);
   18.72 -
   18.73 -            }
   18.74 -        };
   18.75 -}]);
   18.76 -
   18.77 -function DevCtrl( $scope, $http ) {
   18.78 -    var templateHtml = 
   18.79 -"<html><body>\n" +
   18.80 -"  <input data-bind=\"value: value, valueUpdate: 'afterkeydown'\" \n" +
   18.81 -"     value=\"0\" type=\"number\">\n" +
   18.82 -"  </input>\n" +
   18.83 -"  * <span data-bind=\"text: value\">0</span> \n" +
   18.84 -"  = <span data-bind=\"text: powerValue\">0</span>\n" +
   18.85 -"  <br/>\n" +
   18.86 -"  <button id='dupl'>Duplicate!</button>\n" +
   18.87 -"  <button id=\"clear\">Clear!</button>" +
   18.88 -" <hr/>\n" +
   18.89 -"\n" +
   18.90 -"\n" +
   18.91 -"\n" +
   18.92 -"\n" +
   18.93 -"\n" +
   18.94 -"\n" +
   18.95 -"\n" +
   18.96 -"\n" +
   18.97 -"\n" +
   18.98 -"\n" +
   18.99 -"\n" +
  18.100 -"\n" +
  18.101 -"\n" +
  18.102 -"\n" +
  18.103 -"\n" +
  18.104 -"\n" +
  18.105 -"\n" +
  18.106 -"\n" +
  18.107 -"\n" +
  18.108 -"\n" +
  18.109 -" <script src=\"/bck2brwsr.js\"></script>\n" +
  18.110 -" <script type=\"text/javascript\">\n" +
  18.111 -"   function ldCls(res) {\n" +
  18.112 -"     var request = new XMLHttpRequest();\n" +
  18.113 -"     request.open('GET', '/classes/' + res, false);\n" +
  18.114 -"     request.send();\n" +
  18.115 -"     var arr = eval('(' + request.responseText + ')');\n" +
  18.116 -"     return arr;\n" +
  18.117 -"   }\n" +
  18.118 -"   var vm = bck2brwsr(ldCls);\n" +
  18.119 -"   vm.loadClass('${fqn}');\n" +
  18.120 -" </script>\n" +
  18.121 -"</body></html>";
  18.122 -    var templateJava = 
  18.123 -"package bck2brwsr.demo;\n" +
  18.124 -"import org.apidesign.bck2brwsr.htmlpage.api.*;\n" +
  18.125 -"import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;\n" +
  18.126 -"\n" +
  18.127 -"@Page(xhtml=\"index.html\", className=\"Index\", properties={\n" +
  18.128 -"  @Property(name=\"value\", type=int.class)\n" +
  18.129 -"})\n" +
  18.130 -"class YourFirstHTML5PageInRealLanguage {\n" +
  18.131 -"  static { new Index().applyBindings(); }\n" +
  18.132 -"  @On(event=CLICK, id=\"dupl\") static void duplicateValue(Index m) {\n" +
  18.133 -"    m.setValue(m.getValue() * 2);\n" +
  18.134 -"  }\n" +
  18.135 -"  @On(event=CLICK, id=\"clear\") static void zeroTheValue(Index m) {\n" +
  18.136 -"     m.setValue(0);;\n" +
  18.137 -"  }\n" +
  18.138 -"  @ComputedProperty static int powerValue(int value) {\n" +
  18.139 -"    return value * value;\n" +
  18.140 -"  }\n" +
  18.141 -"}";
  18.142 -
  18.143 -    
  18.144 -    $scope.makeMarker = function( editor, line ) {
  18.145 -        var marker = document.createElement("div");
  18.146 -        marker.innerHTML = " ";
  18.147 -        marker.className = "issue";
  18.148 -        
  18.149 -        var info = editor.lineInfo(line);
  18.150 -        editor.setGutterMarker(line, "issues", info.markers ? null : marker);
  18.151 -        
  18.152 -        return marker;
  18.153 -    };
  18.154 -    
  18.155 -    
  18.156 -    // Returns a function, that, as long as it continues to be invoked, will not
  18.157 -    // be triggered. The function will be called after it stops being called for
  18.158 -    // N milliseconds. If `immediate` is passed, trigger the function on the
  18.159 -    // leading edge, instead of the trailing.
  18.160 -    $scope.debounce = function(func, wait, immediate) {
  18.161 -      var timeout, result;
  18.162 -      return function() {
  18.163 -        var context = this, args = arguments;
  18.164 -        var later = function() {
  18.165 -          timeout = null;
  18.166 -          if (!immediate) result = func.apply(context, args);
  18.167 -        };
  18.168 -        var callNow = immediate && !timeout;
  18.169 -        clearTimeout(timeout);
  18.170 -        timeout = setTimeout(later, wait);
  18.171 -        if (callNow) result = func.apply(context, args);
  18.172 -        return result;
  18.173 -      };
  18.174 -    };
  18.175 -    
  18.176 -    $scope.reload = function() {
  18.177 -        $scope.errors = null;
  18.178 -        var frame = document.getElementById("result");        
  18.179 -        frame.src = "result.html";
  18.180 -        frame.contentDocument.location.reload(true);
  18.181 -        frame.contentWindow.location.reload();
  18.182 -        document.getElementById("editorJava").codeMirror.clearGutter("issues");   
  18.183 -    };
  18.184 -    
  18.185 -    $scope.fail = function( data ) {
  18.186 -        $scope.errors = eval( data );
  18.187 -        var editor = document.getElementById("editorJava").codeMirror;   
  18.188 -        editor.clearGutter( "issues" );
  18.189 -        
  18.190 -        for( var i = 0; i < $scope.errors.length; i ++ ) {
  18.191 -            $scope.makeMarker( editor, $scope.errors[i].line - 1 );
  18.192 -        }
  18.193 -        
  18.194 -    };
  18.195 -    
  18.196 -    $scope.post = function() {
  18.197 -        return $http({url: ".",
  18.198 -            method: "POST",
  18.199 -            //headers: this.headers,
  18.200 -            data: { html : $scope.html, java : $scope.java} 
  18.201 -        }).success( $scope.reload ).error( $scope.fail );
  18.202 -    };
  18.203 -    
  18.204 -    $scope.errorClass = function( kind ) {
  18.205 -        switch( kind ) {
  18.206 -            case "ERROR" :
  18.207 -                return "error";
  18.208 -            default :         
  18.209 -                return "warning";   
  18.210 -        }
  18.211 -    };
  18.212 -    
  18.213 -    $scope.gotoError = function( line, col ) {
  18.214 -        var editor = document.getElementById("editorJava").codeMirror;   
  18.215 -        editor.setCursor({ line: line - 1, ch : col - 1 });
  18.216 -        editor.focus();
  18.217 -    };
  18.218 -    
  18.219 -    $scope.tab = "html";
  18.220 -    $scope.html= templateHtml;  
  18.221 -    $scope.java = templateJava;  
  18.222 -    
  18.223 -    $scope.$watch( "html", $scope.debounce( $scope.post, 2000 ) );
  18.224 -    $scope.$watch( "java", $scope.debounce( $scope.post, 2000 ) );
  18.225 -    $scope.post();
  18.226 -    
  18.227 -}
    19.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css	Tue Apr 29 15:25:58 2014 +0200
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,239 +0,0 @@
    19.4 -/* BASICS */
    19.5 -
    19.6 -.CodeMirror {
    19.7 -  /* Set height, width, borders, and global font properties here */
    19.8 -  font-family: monospace;
    19.9 -  height: 300px;
   19.10 -}
   19.11 -.CodeMirror-scroll {
   19.12 -  /* Set scrolling behaviour here */
   19.13 -  overflow: auto;
   19.14 -}
   19.15 -
   19.16 -/* PADDING */
   19.17 -
   19.18 -.CodeMirror-lines {
   19.19 -  padding: 4px 0; /* Vertical padding around content */
   19.20 -}
   19.21 -.CodeMirror pre {
   19.22 -  padding: 0 4px; /* Horizontal padding of content */
   19.23 -}
   19.24 -
   19.25 -.CodeMirror-scrollbar-filler {
   19.26 -  background-color: white; /* The little square between H and V scrollbars */
   19.27 -}
   19.28 -
   19.29 -/* GUTTER */
   19.30 -
   19.31 -.CodeMirror-gutters {
   19.32 -  border-right: 1px solid #ddd;
   19.33 -  background-color: #f7f7f7;
   19.34 -}
   19.35 -.CodeMirror-linenumbers {}
   19.36 -.CodeMirror-linenumber {
   19.37 -  padding: 0 3px 0 5px;
   19.38 -  min-width: 20px;
   19.39 -  text-align: right;
   19.40 -  color: #999;
   19.41 -}
   19.42 -
   19.43 -/* CURSOR */
   19.44 -
   19.45 -.CodeMirror pre.CodeMirror-cursor {
   19.46 -  border-left: 1px solid black;
   19.47 -}
   19.48 -/* Shown when moving in bi-directional text */
   19.49 -.CodeMirror pre.CodeMirror-secondarycursor {
   19.50 -  border-left: 1px solid silver;
   19.51 -}
   19.52 -.cm-keymap-fat-cursor pre.CodeMirror-cursor {
   19.53 -  width: auto;
   19.54 -  border: 0;
   19.55 -  background: transparent;
   19.56 -  background: rgba(0, 200, 0, .4);
   19.57 -  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
   19.58 -}
   19.59 -/* Kludge to turn off filter in ie9+, which also accepts rgba */
   19.60 -.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
   19.61 -  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
   19.62 -}
   19.63 -/* Can style cursor different in overwrite (non-insert) mode */
   19.64 -.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
   19.65 -
   19.66 -/* DEFAULT THEME */
   19.67 -
   19.68 -.cm-s-default .cm-keyword {color: #708;}
   19.69 -.cm-s-default .cm-atom {color: #219;}
   19.70 -.cm-s-default .cm-number {color: #164;}
   19.71 -.cm-s-default .cm-def {color: #00f;}
   19.72 -.cm-s-default .cm-variable {color: black;}
   19.73 -.cm-s-default .cm-variable-2 {color: #05a;}
   19.74 -.cm-s-default .cm-variable-3 {color: #085;}
   19.75 -.cm-s-default .cm-property {color: black;}
   19.76 -.cm-s-default .cm-operator {color: black;}
   19.77 -.cm-s-default .cm-comment {color: #a50;}
   19.78 -.cm-s-default .cm-string {color: #a11;}
   19.79 -.cm-s-default .cm-string-2 {color: #f50;}
   19.80 -.cm-s-default .cm-meta {color: #555;}
   19.81 -.cm-s-default .cm-error {color: #f00;}
   19.82 -.cm-s-default .cm-qualifier {color: #555;}
   19.83 -.cm-s-default .cm-builtin {color: #30a;}
   19.84 -.cm-s-default .cm-bracket {color: #997;}
   19.85 -.cm-s-default .cm-tag {color: #170;}
   19.86 -.cm-s-default .cm-attribute {color: #00c;}
   19.87 -.cm-s-default .cm-header {color: blue;}
   19.88 -.cm-s-default .cm-quote {color: #090;}
   19.89 -.cm-s-default .cm-hr {color: #999;}
   19.90 -.cm-s-default .cm-link {color: #00c;}
   19.91 -
   19.92 -.cm-negative {color: #d44;}
   19.93 -.cm-positive {color: #292;}
   19.94 -.cm-header, .cm-strong {font-weight: bold;}
   19.95 -.cm-em {font-style: italic;}
   19.96 -.cm-emstrong {font-style: italic; font-weight: bold;}
   19.97 -.cm-link {text-decoration: underline;}
   19.98 -
   19.99 -.cm-invalidchar {color: #f00;}
  19.100 -
  19.101 -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
  19.102 -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
  19.103 -
  19.104 -/* STOP */
  19.105 -
  19.106 -/* The rest of this file contains styles related to the mechanics of
  19.107 -   the editor. You probably shouldn't touch them. */
  19.108 -
  19.109 -.CodeMirror {
  19.110 -  line-height: 1;
  19.111 -  position: relative;
  19.112 -  overflow: hidden;
  19.113 -}
  19.114 -
  19.115 -.CodeMirror-scroll {
  19.116 -  /* 30px is the magic margin used to hide the element's real scrollbars */
  19.117 -  /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
  19.118 -  margin-bottom: -30px; margin-right: -30px;
  19.119 -  padding-bottom: 30px; padding-right: 30px;
  19.120 -  height: 100%;
  19.121 -  outline: none; /* Prevent dragging from highlighting the element */
  19.122 -  position: relative;
  19.123 -}
  19.124 -.CodeMirror-sizer {
  19.125 -  position: relative;
  19.126 -}
  19.127 -
  19.128 -/* The fake, visible scrollbars. Used to force redraw during scrolling
  19.129 -   before actuall scrolling happens, thus preventing shaking and
  19.130 -   flickering artifacts. */
  19.131 -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
  19.132 -  position: absolute;
  19.133 -  z-index: 6;
  19.134 -  display: none;
  19.135 -}
  19.136 -.CodeMirror-vscrollbar {
  19.137 -  right: 0; top: 0;
  19.138 -  overflow-x: hidden;
  19.139 -  overflow-y: scroll;
  19.140 -}
  19.141 -.CodeMirror-hscrollbar {
  19.142 -  bottom: 0; left: 0;
  19.143 -  overflow-y: hidden;
  19.144 -  overflow-x: scroll;
  19.145 -}
  19.146 -.CodeMirror-scrollbar-filler {
  19.147 -  right: 0; bottom: 0;
  19.148 -  z-index: 6;
  19.149 -}
  19.150 -
  19.151 -.CodeMirror-gutters {
  19.152 -  position: absolute; left: 0; top: 0;
  19.153 -  height: 100%;
  19.154 -  z-index: 3;
  19.155 -}
  19.156 -.CodeMirror-gutter {
  19.157 -  height: 100%;
  19.158 -  display: inline-block;
  19.159 -  /* Hack to make IE7 behave */
  19.160 -  *zoom:1;
  19.161 -  *display:inline;
  19.162 -}
  19.163 -.CodeMirror-gutter-elt {
  19.164 -  position: absolute;
  19.165 -  cursor: default;
  19.166 -  z-index: 4;
  19.167 -}
  19.168 -
  19.169 -.CodeMirror-lines {
  19.170 -  cursor: text;
  19.171 -}
  19.172 -.CodeMirror pre {
  19.173 -  /* Reset some styles that the rest of the page might have set */
  19.174 -  -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
  19.175 -  border-width: 0;
  19.176 -  background: transparent;
  19.177 -  font-family: inherit;
  19.178 -  font-size: inherit;
  19.179 -  margin: 0;
  19.180 -  white-space: pre;
  19.181 -  word-wrap: normal;
  19.182 -  line-height: inherit;
  19.183 -  color: inherit;
  19.184 -  z-index: 2;
  19.185 -  position: relative;
  19.186 -  overflow: visible;
  19.187 -}
  19.188 -.CodeMirror-wrap pre {
  19.189 -  word-wrap: break-word;
  19.190 -  white-space: pre-wrap;
  19.191 -  word-break: normal;
  19.192 -}
  19.193 -.CodeMirror-linebackground {
  19.194 -  position: absolute;
  19.195 -  left: 0; right: 0; top: 0; bottom: 0;
  19.196 -  z-index: 0;
  19.197 -}
  19.198 -
  19.199 -.CodeMirror-linewidget {
  19.200 -  position: relative;
  19.201 -  z-index: 2;
  19.202 -}
  19.203 -
  19.204 -.CodeMirror-wrap .CodeMirror-scroll {
  19.205 -  overflow-x: hidden;
  19.206 -}
  19.207 -
  19.208 -.CodeMirror-measure {
  19.209 -  position: absolute;
  19.210 -  width: 100%; height: 0px;
  19.211 -  overflow: hidden;
  19.212 -  visibility: hidden;
  19.213 -}
  19.214 -.CodeMirror-measure pre { position: static; }
  19.215 -
  19.216 -.CodeMirror pre.CodeMirror-cursor {
  19.217 -  position: absolute;
  19.218 -  visibility: hidden;
  19.219 -  border-right: none;
  19.220 -  width: 0;
  19.221 -}
  19.222 -.CodeMirror-focused pre.CodeMirror-cursor {
  19.223 -  visibility: visible;
  19.224 -}
  19.225 -
  19.226 -.CodeMirror-selected { background: #d9d9d9; }
  19.227 -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
  19.228 -
  19.229 -.CodeMirror-searching {
  19.230 -  background: #ffa;
  19.231 -  background: rgba(255, 255, 0, .4);
  19.232 -}
  19.233 -
  19.234 -/* IE7 hack to prevent it from returning funny offsetTops on the spans */
  19.235 -.CodeMirror span { *vertical-align: text-bottom; }
  19.236 -
  19.237 -@media print {
  19.238 -  /* Hide the cursor when printing */
  19.239 -  .CodeMirror pre.CodeMirror-cursor {
  19.240 -    visibility: hidden;
  19.241 -  }
  19.242 -}
    20.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js	Tue Apr 29 15:25:58 2014 +0200
    20.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.3 @@ -1,4553 +0,0 @@
    20.4 -// CodeMirror version 3.0
    20.5 -//
    20.6 -// CodeMirror is the only global var we claim
    20.7 -window.CodeMirror = (function() {
    20.8 -  "use strict";
    20.9 -
   20.10 -  // BROWSER SNIFFING
   20.11 -
   20.12 -  // Crude, but necessary to handle a number of hard-to-feature-detect
   20.13 -  // bugs and behavior differences.
   20.14 -  var gecko = /gecko\/\d/i.test(navigator.userAgent);
   20.15 -  var ie = /MSIE \d/.test(navigator.userAgent);
   20.16 -  var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
   20.17 -  var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
   20.18 -  var webkit = /WebKit\//.test(navigator.userAgent);
   20.19 -  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
   20.20 -  var chrome = /Chrome\//.test(navigator.userAgent);
   20.21 -  var opera = /Opera\//.test(navigator.userAgent);
   20.22 -  var safari = /Apple Computer/.test(navigator.vendor);
   20.23 -  var khtml = /KHTML\//.test(navigator.userAgent);
   20.24 -  var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
   20.25 -  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
   20.26 -  var phantom = /PhantomJS/.test(navigator.userAgent);
   20.27 -
   20.28 -  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
   20.29 -  // This is woefully incomplete. Suggestions for alternative methods welcome.
   20.30 -  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent);
   20.31 -  var mac = ios || /Mac/.test(navigator.platform);
   20.32 -
   20.33 -  // Optimize some code when these features are not used
   20.34 -  var sawReadOnlySpans = false, sawCollapsedSpans = false;
   20.35 -
   20.36 -  // CONSTRUCTOR
   20.37 -
   20.38 -  function CodeMirror(place, options) {
   20.39 -    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
   20.40 -    
   20.41 -    this.options = options = options || {};
   20.42 -    // Determine effective options based on given values and defaults.
   20.43 -    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
   20.44 -      options[opt] = defaults[opt];
   20.45 -    setGuttersForLineNumbers(options);
   20.46 -
   20.47 -    var display = this.display = makeDisplay(place);
   20.48 -    display.wrapper.CodeMirror = this;
   20.49 -    updateGutters(this);
   20.50 -    if (options.autofocus && !mobile) focusInput(this);
   20.51 -
   20.52 -    this.view = makeView(new BranchChunk([new LeafChunk([makeLine("", null, textHeight(display))])]));
   20.53 -    this.nextOpId = 0;
   20.54 -    loadMode(this);
   20.55 -    themeChanged(this);
   20.56 -    if (options.lineWrapping)
   20.57 -      this.display.wrapper.className += " CodeMirror-wrap";
   20.58 -
   20.59 -    // Initialize the content.
   20.60 -    this.setValue(options.value || "");
   20.61 -    // Override magic textarea content restore that IE sometimes does
   20.62 -    // on our hidden textarea on reload
   20.63 -    if (ie) setTimeout(bind(resetInput, this, true), 20);
   20.64 -    this.view.history = makeHistory();
   20.65 -
   20.66 -    registerEventHandlers(this);
   20.67 -    // IE throws unspecified error in certain cases, when
   20.68 -    // trying to access activeElement before onload
   20.69 -    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
   20.70 -    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
   20.71 -    else onBlur(this);
   20.72 -
   20.73 -    operation(this, function() {
   20.74 -      for (var opt in optionHandlers)
   20.75 -        if (optionHandlers.propertyIsEnumerable(opt))
   20.76 -          optionHandlers[opt](this, options[opt], Init);
   20.77 -      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
   20.78 -    })();
   20.79 -  }
   20.80 -
   20.81 -  // DISPLAY CONSTRUCTOR
   20.82 -
   20.83 -  function makeDisplay(place) {
   20.84 -    var d = {};
   20.85 -    var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none;");
   20.86 -    input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
   20.87 -    // Wraps and hides input textarea
   20.88 -    d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
   20.89 -    // The actual fake scrollbars.
   20.90 -    d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
   20.91 -    d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
   20.92 -    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
   20.93 -    // DIVs containing the selection and the actual code
   20.94 -    d.lineDiv = elt("div");
   20.95 -    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
   20.96 -    // Blinky cursor, and element used to ensure cursor fits at the end of a line
   20.97 -    d.cursor = elt("pre", "\u00a0", "CodeMirror-cursor");
   20.98 -    // Secondary cursor, shown when on a 'jump' in bi-directional text
   20.99 -    d.otherCursor = elt("pre", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
  20.100 -    // Used to measure text size
  20.101 -    d.measure = elt("div", null, "CodeMirror-measure");
  20.102 -    // Wraps everything that needs to exist inside the vertically-padded coordinate system
  20.103 -    d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
  20.104 -                         null, "position: relative; outline: none");
  20.105 -    // Moved around its parent to cover visible view
  20.106 -    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
  20.107 -    // Set to the height of the text, causes scrolling
  20.108 -    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
  20.109 -    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
  20.110 -    d.heightForcer = elt("div", "\u00a0", null, "position: absolute; height: " + scrollerCutOff + "px");
  20.111 -    // Will contain the gutters, if any
  20.112 -    d.gutters = elt("div", null, "CodeMirror-gutters");
  20.113 -    d.lineGutter = null;
  20.114 -    // Helper element to properly size the gutter backgrounds
  20.115 -    var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%");
  20.116 -    // Provides scrolling
  20.117 -    d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll");
  20.118 -    d.scroller.setAttribute("tabIndex", "-1");
  20.119 -    // The element in which the editor lives.
  20.120 -    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
  20.121 -                            d.scrollbarFiller, d.scroller], "CodeMirror");
  20.122 -    // Work around IE7 z-index bug
  20.123 -    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
  20.124 -    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
  20.125 -
  20.126 -    // Needed to hide big blue blinking cursor on Mobile Safari
  20.127 -    if (ios) input.style.width = "0px";
  20.128 -    if (!webkit) d.scroller.draggable = true;
  20.129 -    // Needed to handle Tab key in KHTML
  20.130 -    if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
  20.131 -    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
  20.132 -    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
  20.133 -
  20.134 -    // Current visible range (may be bigger than the view window).
  20.135 -    d.viewOffset = d.showingFrom = d.showingTo = d.lastSizeC = 0;
  20.136 -
  20.137 -    // Used to only resize the line number gutter when necessary (when
  20.138 -    // the amount of lines crosses a boundary that makes its width change)
  20.139 -    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
  20.140 -    // See readInput and resetInput
  20.141 -    d.prevInput = "";
  20.142 -    // Set to true when a non-horizontal-scrolling widget is added. As
  20.143 -    // an optimization, widget aligning is skipped when d is false.
  20.144 -    d.alignWidgets = false;
  20.145 -    // Flag that indicates whether we currently expect input to appear
  20.146 -    // (after some event like 'keypress' or 'input') and are polling
  20.147 -    // intensively.
  20.148 -    d.pollingFast = false;
  20.149 -    // Self-resetting timeout for the poller
  20.150 -    d.poll = new Delayed();
  20.151 -    // True when a drag from the editor is active
  20.152 -    d.draggingText = false;
  20.153 -
  20.154 -    d.cachedCharWidth = d.cachedTextHeight = null;
  20.155 -    d.measureLineCache = [];
  20.156 -    d.measureLineCachePos = 0;
  20.157 -
  20.158 -    // Tracks when resetInput has punted to just putting a short
  20.159 -    // string instead of the (large) selection.
  20.160 -    d.inaccurateSelection = false;
  20.161 -
  20.162 -    // Used to adjust overwrite behaviour when a paste has been
  20.163 -    // detected
  20.164 -    d.pasteIncoming = false;
  20.165 -
  20.166 -    return d;
  20.167 -  }
  20.168 -
  20.169 -  // VIEW CONSTRUCTOR
  20.170 -
  20.171 -  function makeView(doc) {
  20.172 -    var selPos = {line: 0, ch: 0};
  20.173 -    return {
  20.174 -      doc: doc,
  20.175 -      // frontier is the point up to which the content has been parsed,
  20.176 -      frontier: 0, highlight: new Delayed(),
  20.177 -      sel: {from: selPos, to: selPos, head: selPos, anchor: selPos, shift: false, extend: false},
  20.178 -      scrollTop: 0, scrollLeft: 0,
  20.179 -      overwrite: false, focused: false,
  20.180 -      // Tracks the maximum line length so that
  20.181 -      // the horizontal scrollbar can be kept
  20.182 -      // static when scrolling.
  20.183 -      maxLine: getLine(doc, 0),
  20.184 -      maxLineLength: 0,
  20.185 -      maxLineChanged: false,
  20.186 -      suppressEdits: false,
  20.187 -      goalColumn: null,
  20.188 -      cantEdit: false,
  20.189 -      keyMaps: []
  20.190 -    };
  20.191 -  }
  20.192 -
  20.193 -  // STATE UPDATES
  20.194 -
  20.195 -  // Used to get the editor into a consistent state again when options change.
  20.196 -
  20.197 -  function loadMode(cm) {
  20.198 -    var doc = cm.view.doc;
  20.199 -    cm.view.mode = CodeMirror.getMode(cm.options, cm.options.mode);
  20.200 -    doc.iter(0, doc.size, function(line) { line.stateAfter = null; });
  20.201 -    cm.view.frontier = 0;
  20.202 -    startWorker(cm, 100);
  20.203 -  }
  20.204 -
  20.205 -  function wrappingChanged(cm) {
  20.206 -    var doc = cm.view.doc, th = textHeight(cm.display);
  20.207 -    if (cm.options.lineWrapping) {
  20.208 -      cm.display.wrapper.className += " CodeMirror-wrap";
  20.209 -      var perLine = cm.display.scroller.clientWidth / charWidth(cm.display) - 3;
  20.210 -      doc.iter(0, doc.size, function(line) {
  20.211 -        if (line.height == 0) return;
  20.212 -        var guess = Math.ceil(line.text.length / perLine) || 1;
  20.213 -        if (guess != 1) updateLineHeight(line, guess * th);
  20.214 -      });
  20.215 -      cm.display.sizer.style.minWidth = "";
  20.216 -    } else {
  20.217 -      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
  20.218 -      computeMaxLength(cm.view);
  20.219 -      doc.iter(0, doc.size, function(line) {
  20.220 -        if (line.height != 0) updateLineHeight(line, th);
  20.221 -      });
  20.222 -    }
  20.223 -    regChange(cm, 0, doc.size);
  20.224 -    clearCaches(cm);
  20.225 -    setTimeout(function(){updateScrollbars(cm.display, cm.view.doc.height);}, 100);
  20.226 -  }
  20.227 -
  20.228 -  function keyMapChanged(cm) {
  20.229 -    var style = keyMap[cm.options.keyMap].style;
  20.230 -    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
  20.231 -      (style ? " cm-keymap-" + style : "");
  20.232 -  }
  20.233 -
  20.234 -  function themeChanged(cm) {
  20.235 -    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
  20.236 -      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
  20.237 -    clearCaches(cm);
  20.238 -  }
  20.239 -
  20.240 -  function guttersChanged(cm) {
  20.241 -    updateGutters(cm);
  20.242 -    updateDisplay(cm, true);
  20.243 -  }
  20.244 -
  20.245 -  function updateGutters(cm) {
  20.246 -    var gutters = cm.display.gutters, specs = cm.options.gutters;
  20.247 -    removeChildren(gutters);
  20.248 -    for (var i = 0; i < specs.length; ++i) {
  20.249 -      var gutterClass = specs[i];
  20.250 -      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
  20.251 -      if (gutterClass == "CodeMirror-linenumbers") {
  20.252 -        cm.display.lineGutter = gElt;
  20.253 -        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
  20.254 -      }
  20.255 -    }
  20.256 -    gutters.style.display = i ? "" : "none";
  20.257 -  }
  20.258 -
  20.259 -  function lineLength(doc, line) {
  20.260 -    if (line.height == 0) return 0;
  20.261 -    var len = line.text.length, merged, cur = line;
  20.262 -    while (merged = collapsedSpanAtStart(cur)) {
  20.263 -      var found = merged.find();
  20.264 -      cur = getLine(doc, found.from.line);
  20.265 -      len += found.from.ch - found.to.ch;
  20.266 -    }
  20.267 -    cur = line;
  20.268 -    while (merged = collapsedSpanAtEnd(cur)) {
  20.269 -      var found = merged.find();
  20.270 -      len -= cur.text.length - found.from.ch;
  20.271 -      cur = getLine(doc, found.to.line);
  20.272 -      len += cur.text.length - found.to.ch;
  20.273 -    }
  20.274 -    return len;
  20.275 -  }
  20.276 -
  20.277 -  function computeMaxLength(view) {
  20.278 -    view.maxLine = getLine(view.doc, 0);
  20.279 -    view.maxLineLength = lineLength(view.doc, view.maxLine);
  20.280 -    view.maxLineChanged = true;
  20.281 -    view.doc.iter(1, view.doc.size, function(line) {
  20.282 -      var len = lineLength(view.doc, line);
  20.283 -      if (len > view.maxLineLength) {
  20.284 -        view.maxLineLength = len;
  20.285 -        view.maxLine = line;
  20.286 -      }
  20.287 -    });
  20.288 -  }
  20.289 -
  20.290 -  // Make sure the gutters options contains the element
  20.291 -  // "CodeMirror-linenumbers" when the lineNumbers option is true.
  20.292 -  function setGuttersForLineNumbers(options) {
  20.293 -    var found = false;
  20.294 -    for (var i = 0; i < options.gutters.length; ++i) {
  20.295 -      if (options.gutters[i] == "CodeMirror-linenumbers") {
  20.296 -        if (options.lineNumbers) found = true;
  20.297 -        else options.gutters.splice(i--, 1);
  20.298 -      }
  20.299 -    }
  20.300 -    if (!found && options.lineNumbers)
  20.301 -      options.gutters.push("CodeMirror-linenumbers");
  20.302 -  }
  20.303 -
  20.304 -  // SCROLLBARS
  20.305 -
  20.306 -  // Re-synchronize the fake scrollbars with the actual size of the
  20.307 -  // content. Optionally force a scrollTop.
  20.308 -  function updateScrollbars(d /* display */, docHeight) {
  20.309 -    var totalHeight = docHeight + 2 * paddingTop(d);
  20.310 -    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
  20.311 -    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
  20.312 -    var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
  20.313 -    var needsV = scrollHeight > d.scroller.clientHeight;
  20.314 -    if (needsV) {
  20.315 -      d.scrollbarV.style.display = "block";
  20.316 -      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
  20.317 -      d.scrollbarV.firstChild.style.height = 
  20.318 -        (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
  20.319 -    } else d.scrollbarV.style.display = "";
  20.320 -    if (needsH) {
  20.321 -      d.scrollbarH.style.display = "block";
  20.322 -      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
  20.323 -      d.scrollbarH.firstChild.style.width =
  20.324 -        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
  20.325 -    } else d.scrollbarH.style.display = "";
  20.326 -    if (needsH && needsV) {
  20.327 -      d.scrollbarFiller.style.display = "block";
  20.328 -      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
  20.329 -    } else d.scrollbarFiller.style.display = "";
  20.330 -
  20.331 -    if (mac_geLion && scrollbarWidth(d.measure) === 0)
  20.332 -      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
  20.333 -  }
  20.334 -
  20.335 -  function visibleLines(display, doc, viewPort) {
  20.336 -    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
  20.337 -    if (typeof viewPort == "number") top = viewPort;
  20.338 -    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
  20.339 -    top = Math.floor(top - paddingTop(display));
  20.340 -    var bottom = Math.ceil(top + height);
  20.341 -    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
  20.342 -  }
  20.343 -
  20.344 -  // LINE NUMBERS
  20.345 -
  20.346 -  function alignHorizontally(cm) {
  20.347 -    var display = cm.display;
  20.348 -    if (!display.alignWidgets && !display.gutters.firstChild) return;
  20.349 -    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.view.scrollLeft;
  20.350 -    var gutterW = display.gutters.offsetWidth, l = comp + "px";
  20.351 -    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
  20.352 -      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
  20.353 -    }
  20.354 -    display.gutters.style.left = (comp + gutterW) + "px";
  20.355 -  }
  20.356 -
  20.357 -  function maybeUpdateLineNumberWidth(cm) {
  20.358 -    if (!cm.options.lineNumbers) return false;
  20.359 -    var doc = cm.view.doc, last = lineNumberFor(cm.options, doc.size - 1), display = cm.display;
  20.360 -    if (last.length != display.lineNumChars) {
  20.361 -      var test = display.measure.appendChild(elt("div", [elt("div", last)],
  20.362 -                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
  20.363 -      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
  20.364 -      display.lineGutter.style.width = "";
  20.365 -      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
  20.366 -      display.lineNumWidth = display.lineNumInnerWidth + padding;
  20.367 -      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
  20.368 -      display.lineGutter.style.width = display.lineNumWidth + "px";
  20.369 -      return true;
  20.370 -    }
  20.371 -    return false;
  20.372 -  }
  20.373 -
  20.374 -  function lineNumberFor(options, i) {
  20.375 -    return String(options.lineNumberFormatter(i + options.firstLineNumber));
  20.376 -  }
  20.377 -  function compensateForHScroll(display) {
  20.378 -    return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
  20.379 -  }
  20.380 -
  20.381 -  // DISPLAY DRAWING
  20.382 -
  20.383 -  function updateDisplay(cm, changes, viewPort) {
  20.384 -    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo;
  20.385 -    var updated = updateDisplayInner(cm, changes, viewPort);
  20.386 -    if (updated) {
  20.387 -      signalLater(cm, cm, "update", cm);
  20.388 -      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
  20.389 -        signalLater(cm, cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
  20.390 -    }
  20.391 -    updateSelection(cm);
  20.392 -    updateScrollbars(cm.display, cm.view.doc.height);
  20.393 -
  20.394 -    return updated;
  20.395 -  }
  20.396 -
  20.397 -  // Uses a set of changes plus the current scroll position to
  20.398 -  // determine which DOM updates have to be made, and makes the
  20.399 -  // updates.
  20.400 -  function updateDisplayInner(cm, changes, viewPort) {
  20.401 -    var display = cm.display, doc = cm.view.doc;
  20.402 -    if (!display.wrapper.clientWidth) {
  20.403 -      display.showingFrom = display.showingTo = display.viewOffset = 0;
  20.404 -      return;
  20.405 -    }
  20.406 -
  20.407 -    // Compute the new visible window
  20.408 -    // If scrollTop is specified, use that to determine which lines
  20.409 -    // to render instead of the current scrollbar position.
  20.410 -    var visible = visibleLines(display, doc, viewPort);
  20.411 -    // Bail out if the visible area is already rendered and nothing changed.
  20.412 -    if (changes !== true && changes.length == 0 &&
  20.413 -        visible.from > display.showingFrom && visible.to < display.showingTo)
  20.414 -      return;
  20.415 -
  20.416 -    if (changes && maybeUpdateLineNumberWidth(cm))
  20.417 -      changes = true;
  20.418 -    display.sizer.style.marginLeft = display.scrollbarH.style.left = display.gutters.offsetWidth + "px";
  20.419 -
  20.420 -    // When merged lines are present, the line that needs to be
  20.421 -    // redrawn might not be the one that was changed.
  20.422 -    if (changes !== true && sawCollapsedSpans)
  20.423 -      for (var i = 0; i < changes.length; ++i) {
  20.424 -        var ch = changes[i], merged;
  20.425 -        while (merged = collapsedSpanAtStart(getLine(doc, ch.from))) {
  20.426 -          var from = merged.find().from.line;
  20.427 -          if (ch.diff) ch.diff -= ch.from - from;
  20.428 -          ch.from = from;
  20.429 -        }
  20.430 -      }
  20.431 -
  20.432 -    // Used to determine which lines need their line numbers updated
  20.433 -    var positionsChangedFrom = changes === true ? 0 : Infinity;
  20.434 -    if (cm.options.lineNumbers && changes && changes !== true)
  20.435 -      for (var i = 0; i < changes.length; ++i)
  20.436 -        if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
  20.437 -
  20.438 -    var from = Math.max(visible.from - cm.options.viewportMargin, 0);
  20.439 -    var to = Math.min(doc.size, visible.to + cm.options.viewportMargin);
  20.440 -    if (display.showingFrom < from && from - display.showingFrom < 20) from = display.showingFrom;
  20.441 -    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(doc.size, display.showingTo);
  20.442 -    if (sawCollapsedSpans) {
  20.443 -      from = lineNo(visualLine(doc, getLine(doc, from)));
  20.444 -      while (to < doc.size && lineIsHidden(getLine(doc, to))) ++to;
  20.445 -    }
  20.446 -
  20.447 -    // Create a range of theoretically intact lines, and punch holes
  20.448 -    // in that using the change info.
  20.449 -    var intact = changes === true ? [] :
  20.450 -      computeIntact([{from: display.showingFrom, to: display.showingTo}], changes);
  20.451 -    // Clip off the parts that won't be visible
  20.452 -    var intactLines = 0;
  20.453 -    for (var i = 0; i < intact.length; ++i) {
  20.454 -      var range = intact[i];
  20.455 -      if (range.from < from) range.from = from;
  20.456 -      if (range.to > to) range.to = to;
  20.457 -      if (range.from >= range.to) intact.splice(i--, 1);
  20.458 -      else intactLines += range.to - range.from;
  20.459 -    }
  20.460 -    if (intactLines == to - from && from == display.showingFrom && to == display.showingTo)
  20.461 -      return;
  20.462 -    intact.sort(function(a, b) {return a.from - b.from;});
  20.463 -
  20.464 -    if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
  20.465 -    patchDisplay(cm, from, to, intact, positionsChangedFrom);
  20.466 -    display.lineDiv.style.display = "";
  20.467 -
  20.468 -    var different = from != display.showingFrom || to != display.showingTo ||
  20.469 -      display.lastSizeC != display.wrapper.clientHeight;
  20.470 -    // This is just a bogus formula that detects when the editor is
  20.471 -    // resized or the font size changes.
  20.472 -    if (different) display.lastSizeC = display.wrapper.clientHeight;
  20.473 -    display.showingFrom = from; display.showingTo = to;
  20.474 -    startWorker(cm, 100);
  20.475 -
  20.476 -    var prevBottom = display.lineDiv.offsetTop;
  20.477 -    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
  20.478 -      if (ie_lt8) {
  20.479 -        var bot = node.offsetTop + node.offsetHeight;
  20.480 -        height = bot - prevBottom;
  20.481 -        prevBottom = bot;
  20.482 -      } else {
  20.483 -        var box = node.getBoundingClientRect();
  20.484 -        height = box.bottom - box.top;
  20.485 -      }
  20.486 -      var diff = node.lineObj.height - height;
  20.487 -      if (height < 2) height = textHeight(display);
  20.488 -      if (diff > .001 || diff < -.001)
  20.489 -        updateLineHeight(node.lineObj, height);
  20.490 -    }
  20.491 -    display.viewOffset = heightAtLine(cm, getLine(doc, from));
  20.492 -    // Position the mover div to align with the current virtual scroll position
  20.493 -    display.mover.style.top = display.viewOffset + "px";
  20.494 -    return true;
  20.495 -  }
  20.496 -
  20.497 -  function computeIntact(intact, changes) {
  20.498 -    for (var i = 0, l = changes.length || 0; i < l; ++i) {
  20.499 -      var change = changes[i], intact2 = [], diff = change.diff || 0;
  20.500 -      for (var j = 0, l2 = intact.length; j < l2; ++j) {
  20.501 -        var range = intact[j];
  20.502 -        if (change.to <= range.from && change.diff) {
  20.503 -          intact2.push({from: range.from + diff, to: range.to + diff});
  20.504 -        } else if (change.to <= range.from || change.from >= range.to) {
  20.505 -          intact2.push(range);
  20.506 -        } else {
  20.507 -          if (change.from > range.from)
  20.508 -            intact2.push({from: range.from, to: change.from});
  20.509 -          if (change.to < range.to)
  20.510 -            intact2.push({from: change.to + diff, to: range.to + diff});
  20.511 -        }
  20.512 -      }
  20.513 -      intact = intact2;
  20.514 -    }
  20.515 -    return intact;
  20.516 -  }
  20.517 -
  20.518 -  function getDimensions(cm) {
  20.519 -    var d = cm.display, left = {}, width = {};
  20.520 -    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
  20.521 -      left[cm.options.gutters[i]] = n.offsetLeft;
  20.522 -      width[cm.options.gutters[i]] = n.offsetWidth;
  20.523 -    }
  20.524 -    return {fixedPos: compensateForHScroll(d),
  20.525 -            gutterTotalWidth: d.gutters.offsetWidth,
  20.526 -            gutterLeft: left,
  20.527 -            gutterWidth: width,
  20.528 -            wrapperWidth: d.wrapper.clientWidth};
  20.529 -  }
  20.530 -
  20.531 -  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
  20.532 -    var dims = getDimensions(cm);
  20.533 -    var display = cm.display, lineNumbers = cm.options.lineNumbers;
  20.534 -    // IE does bad things to nodes when .innerHTML = "" is used on a parent
  20.535 -    // we still need widgets and markers intact to add back to the new content later
  20.536 -    if (!intact.length && !ie && (!webkit || !cm.display.currentWheelTarget))
  20.537 -      removeChildren(display.lineDiv);
  20.538 -    var container = display.lineDiv, cur = container.firstChild;
  20.539 -
  20.540 -    function rm(node) {
  20.541 -      var next = node.nextSibling;
  20.542 -      if (webkit && mac && cm.display.currentWheelTarget == node) {
  20.543 -        node.style.display = "none";
  20.544 -        node.lineObj = null;
  20.545 -      } else {
  20.546 -        container.removeChild(node);
  20.547 -      }
  20.548 -      return next;
  20.549 -    }
  20.550 -
  20.551 -    var nextIntact = intact.shift(), lineNo = from;
  20.552 -    cm.view.doc.iter(from, to, function(line) {
  20.553 -      if (nextIntact && nextIntact.to == lineNo) nextIntact = intact.shift();
  20.554 -      if (lineIsHidden(line)) {
  20.555 -        if (line.height != 0) updateLineHeight(line, 0);
  20.556 -      } else if (nextIntact && nextIntact.from <= lineNo && nextIntact.to > lineNo) {
  20.557 -        // This line is intact. Skip to the actual node. Update its
  20.558 -        // line number if needed.
  20.559 -        while (cur.lineObj != line) cur = rm(cur);
  20.560 -        if (lineNumbers && updateNumbersFrom <= lineNo && cur.lineNumber)
  20.561 -          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineNo));
  20.562 -        cur = cur.nextSibling;
  20.563 -      } else {
  20.564 -        // This line needs to be generated.
  20.565 -        var lineNode = buildLineElement(cm, line, lineNo, dims);
  20.566 -        container.insertBefore(lineNode, cur);
  20.567 -        lineNode.lineObj = line;
  20.568 -      }
  20.569 -      ++lineNo;
  20.570 -    });
  20.571 -    while (cur) cur = rm(cur);
  20.572 -  }
  20.573 -
  20.574 -  function buildLineElement(cm, line, lineNo, dims) {
  20.575 -    var lineElement = lineContent(cm, line);
  20.576 -    var markers = line.gutterMarkers, display = cm.display;
  20.577 -
  20.578 -    if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass &&
  20.579 -        (!line.widgets || !line.widgets.length)) return lineElement;
  20.580 -
  20.581 -    // Lines with gutter elements or a background class need
  20.582 -    // to be wrapped again, and have the extra elements added
  20.583 -    // to the wrapper div
  20.584 -
  20.585 -    var wrap = elt("div", null, line.wrapClass, "position: relative");
  20.586 -    if (cm.options.lineNumbers || markers) {
  20.587 -      var gutterWrap = wrap.appendChild(elt("div", null, null, "position: absolute; left: " +
  20.588 -                                            dims.fixedPos + "px"));
  20.589 -      wrap.alignable = [gutterWrap];
  20.590 -      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
  20.591 -        wrap.lineNumber = gutterWrap.appendChild(
  20.592 -          elt("div", lineNumberFor(cm.options, lineNo),
  20.593 -              "CodeMirror-linenumber CodeMirror-gutter-elt",
  20.594 -              "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
  20.595 -              + display.lineNumInnerWidth + "px"));
  20.596 -      if (markers)
  20.597 -        for (var k = 0; k < cm.options.gutters.length; ++k) {
  20.598 -          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
  20.599 -          if (found)
  20.600 -            gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
  20.601 -                                       dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
  20.602 -        }
  20.603 -    }
  20.604 -    // Kludge to make sure the styled element lies behind the selection (by z-index)
  20.605 -    if (line.bgClass)
  20.606 -      wrap.appendChild(elt("div", "\u00a0", line.bgClass + " CodeMirror-linebackground"));
  20.607 -    wrap.appendChild(lineElement);
  20.608 -    if (line.widgets)
  20.609 -      for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
  20.610 -        var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
  20.611 -        node.widget = widget;
  20.612 -        if (widget.noHScroll) {
  20.613 -          (wrap.alignable || (wrap.alignable = [])).push(node);
  20.614 -          var width = dims.wrapperWidth;
  20.615 -          node.style.left = dims.fixedPos + "px";
  20.616 -          if (!widget.coverGutter) {
  20.617 -            width -= dims.gutterTotalWidth;
  20.618 -            node.style.paddingLeft = dims.gutterTotalWidth + "px";
  20.619 -          }
  20.620 -          node.style.width = width + "px";
  20.621 -        }
  20.622 -        if (widget.coverGutter) {
  20.623 -          node.style.zIndex = 5;
  20.624 -          node.style.position = "relative";
  20.625 -          if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
  20.626 -        }
  20.627 -        if (widget.above)
  20.628 -          wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
  20.629 -        else
  20.630 -          wrap.appendChild(node);
  20.631 -      }
  20.632 -
  20.633 -    if (ie_lt8) wrap.style.zIndex = 2;
  20.634 -    return wrap;
  20.635 -  }
  20.636 -
  20.637 -  // SELECTION / CURSOR
  20.638 -
  20.639 -  function updateSelection(cm) {
  20.640 -    var display = cm.display;
  20.641 -    var collapsed = posEq(cm.view.sel.from, cm.view.sel.to);
  20.642 -    if (collapsed || cm.options.showCursorWhenSelecting)
  20.643 -      updateSelectionCursor(cm);
  20.644 -    else
  20.645 -      display.cursor.style.display = display.otherCursor.style.display = "none";
  20.646 -    if (!collapsed)
  20.647 -      updateSelectionRange(cm);
  20.648 -    else
  20.649 -      display.selectionDiv.style.display = "none";
  20.650 -
  20.651 -    // Move the hidden textarea near the cursor to prevent scrolling artifacts
  20.652 -    var headPos = cursorCoords(cm, cm.view.sel.head, "div");
  20.653 -    var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
  20.654 -    display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
  20.655 -                                                      headPos.top + lineOff.top - wrapOff.top)) + "px";
  20.656 -    display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
  20.657 -                                                       headPos.left + lineOff.left - wrapOff.left)) + "px";
  20.658 -  }
  20.659 -
  20.660 -  // No selection, plain cursor
  20.661 -  function updateSelectionCursor(cm) {
  20.662 -    var display = cm.display, pos = cursorCoords(cm, cm.view.sel.head, "div");
  20.663 -    display.cursor.style.left = pos.left + "px";
  20.664 -    display.cursor.style.top = pos.top + "px";
  20.665 -    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
  20.666 -    display.cursor.style.display = "";
  20.667 -
  20.668 -    if (pos.other) {
  20.669 -      display.otherCursor.style.display = "";
  20.670 -      display.otherCursor.style.left = pos.other.left + "px";
  20.671 -      display.otherCursor.style.top = pos.other.top + "px";
  20.672 -      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
  20.673 -    } else { display.otherCursor.style.display = "none"; }
  20.674 -  }
  20.675 -
  20.676 -  // Highlight selection
  20.677 -  function updateSelectionRange(cm) {
  20.678 -    var display = cm.display, doc = cm.view.doc, sel = cm.view.sel;
  20.679 -    var fragment = document.createDocumentFragment();
  20.680 -    var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
  20.681 -
  20.682 -    function add(left, top, width, bottom) {
  20.683 -      if (top < 0) top = 0;
  20.684 -      fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
  20.685 -                               "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
  20.686 -                               "px; height: " + (bottom - top) + "px"));
  20.687 -    }
  20.688 -
  20.689 -    function drawForLine(line, fromArg, toArg, retTop) {
  20.690 -      var lineObj = getLine(doc, line);
  20.691 -      var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
  20.692 -      function coords(ch) {
  20.693 -        return charCoords(cm, {line: line, ch: ch}, "div", lineObj);
  20.694 -      }
  20.695 -
  20.696 -      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
  20.697 -        var leftPos = coords(dir == "rtl" ? to - 1 : from);
  20.698 -        var rightPos = coords(dir == "rtl" ? from : to - 1);
  20.699 -        var left = leftPos.left, right = rightPos.right;
  20.700 -        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
  20.701 -          add(left, leftPos.top, null, leftPos.bottom);
  20.702 -          left = pl;
  20.703 -          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
  20.704 -        }
  20.705 -        if (toArg == null && to == lineLen) right = clientWidth;
  20.706 -        if (fromArg == null && from == 0) left = pl;
  20.707 -        rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
  20.708 -        if (left < pl + 1) left = pl;
  20.709 -        add(left, rightPos.top, right - left, rightPos.bottom);
  20.710 -      });
  20.711 -      return rVal;
  20.712 -    }
  20.713 -
  20.714 -    if (sel.from.line == sel.to.line) {
  20.715 -      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
  20.716 -    } else {
  20.717 -      var fromObj = getLine(doc, sel.from.line);
  20.718 -      var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
  20.719 -      while (merged = collapsedSpanAtEnd(cur)) {
  20.720 -        var found = merged.find();
  20.721 -        path.push(found.from.ch, found.to.line, found.to.ch);
  20.722 -        if (found.to.line == sel.to.line) {
  20.723 -          path.push(sel.to.ch);
  20.724 -          singleLine = true;
  20.725 -          break;
  20.726 -        }
  20.727 -        cur = getLine(doc, found.to.line);
  20.728 -      }
  20.729 -
  20.730 -      // This is a single, merged line
  20.731 -      if (singleLine) {
  20.732 -        for (var i = 0; i < path.length; i += 3)
  20.733 -          drawForLine(path[i], path[i+1], path[i+2]);
  20.734 -      } else {
  20.735 -        var middleTop, middleBot, toObj = getLine(doc, sel.to.line);
  20.736 -        if (sel.from.ch)
  20.737 -          // Draw the first line of selection.
  20.738 -          middleTop = drawForLine(sel.from.line, sel.from.ch, null, false);
  20.739 -        else
  20.740 -          // Simply include it in the middle block.
  20.741 -          middleTop = heightAtLine(cm, fromObj) - display.viewOffset;
  20.742 -
  20.743 -        if (!sel.to.ch)
  20.744 -          middleBot = heightAtLine(cm, toObj) - display.viewOffset;
  20.745 -        else
  20.746 -          middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true);
  20.747 -
  20.748 -        if (middleTop < middleBot) add(pl, middleTop, null, middleBot);
  20.749 -      }
  20.750 -    }
  20.751 -
  20.752 -    removeChildrenAndAdd(display.selectionDiv, fragment);
  20.753 -    display.selectionDiv.style.display = "";
  20.754 -  }
  20.755 -
  20.756 -  // Cursor-blinking
  20.757 -  function restartBlink(cm) {
  20.758 -    var display = cm.display;
  20.759 -    clearInterval(display.blinker);
  20.760 -    var on = true;
  20.761 -    display.cursor.style.visibility = display.otherCursor.style.visibility = "";
  20.762 -    display.blinker = setInterval(function() {
  20.763 -      if (!display.cursor.offsetHeight) return;
  20.764 -      display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
  20.765 -    }, cm.options.cursorBlinkRate);
  20.766 -  }
  20.767 -
  20.768 -  // HIGHLIGHT WORKER
  20.769 -
  20.770 -  function startWorker(cm, time) {
  20.771 -    if (cm.view.frontier < cm.display.showingTo)
  20.772 -      cm.view.highlight.set(time, bind(highlightWorker, cm));
  20.773 -  }
  20.774 -
  20.775 -  function highlightWorker(cm) {
  20.776 -    var view = cm.view, doc = view.doc;
  20.777 -    if (view.frontier >= cm.display.showingTo) return;
  20.778 -    var end = +new Date + cm.options.workTime;
  20.779 -    var state = copyState(view.mode, getStateBefore(cm, view.frontier));
  20.780 -    var changed = [], prevChange;
  20.781 -    doc.iter(view.frontier, Math.min(doc.size, cm.display.showingTo + 500), function(line) {
  20.782 -      if (view.frontier >= cm.display.showingFrom) { // Visible
  20.783 -        if (highlightLine(cm, line, state) && view.frontier >= cm.display.showingFrom) {
  20.784 -          if (prevChange && prevChange.end == view.frontier) prevChange.end++;
  20.785 -          else changed.push(prevChange = {start: view.frontier, end: view.frontier + 1});
  20.786 -        }
  20.787 -        line.stateAfter = copyState(view.mode, state);
  20.788 -      } else {
  20.789 -        processLine(cm, line, state);
  20.790 -        line.stateAfter = view.frontier % 5 == 0 ? copyState(view.mode, state) : null;
  20.791 -      }
  20.792 -      ++view.frontier;
  20.793 -      if (+new Date > end) {
  20.794 -        startWorker(cm, cm.options.workDelay);
  20.795 -        return true;
  20.796 -      }
  20.797 -    });
  20.798 -    if (changed.length)
  20.799 -      operation(cm, function() {
  20.800 -        for (var i = 0; i < changed.length; ++i)
  20.801 -          regChange(this, changed[i].start, changed[i].end);
  20.802 -      })();
  20.803 -  }
  20.804 -
  20.805 -  // Finds the line to start with when starting a parse. Tries to
  20.806 -  // find a line with a stateAfter, so that it can start with a
  20.807 -  // valid state. If that fails, it returns the line with the
  20.808 -  // smallest indentation, which tends to need the least context to
  20.809 -  // parse correctly.
  20.810 -  function findStartLine(cm, n) {
  20.811 -    var minindent, minline, doc = cm.view.doc;
  20.812 -    for (var search = n, lim = n - 100; search > lim; --search) {
  20.813 -      if (search == 0) return 0;
  20.814 -      var line = getLine(doc, search-1);
  20.815 -      if (line.stateAfter) return search;
  20.816 -      var indented = countColumn(line.text, null, cm.options.tabSize);
  20.817 -      if (minline == null || minindent > indented) {
  20.818 -        minline = search - 1;
  20.819 -        minindent = indented;
  20.820 -      }
  20.821 -    }
  20.822 -    return minline;
  20.823 -  }
  20.824 -
  20.825 -  function getStateBefore(cm, n) {
  20.826 -    var view = cm.view;
  20.827 -    var pos = findStartLine(cm, n), state = pos && getLine(view.doc, pos-1).stateAfter;
  20.828 -    if (!state) state = startState(view.mode);
  20.829 -    else state = copyState(view.mode, state);
  20.830 -    view.doc.iter(pos, n, function(line) {
  20.831 -      processLine(cm, line, state);
  20.832 -      var save = pos == n - 1 || pos % 5 == 0 || pos >= view.showingFrom && pos < view.showingTo;
  20.833 -      line.stateAfter = save ? copyState(view.mode, state) : null;
  20.834 -      ++pos;
  20.835 -    });
  20.836 -    return state;
  20.837 -  }
  20.838 -
  20.839 -  // POSITION MEASUREMENT
  20.840 -  
  20.841 -  function paddingTop(display) {return display.lineSpace.offsetTop;}
  20.842 -  function paddingLeft(display) {
  20.843 -    var e = removeChildrenAndAdd(display.measure, elt("pre")).appendChild(elt("span", "x"));
  20.844 -    return e.offsetLeft;
  20.845 -  }
  20.846 -
  20.847 -  function measureChar(cm, line, ch, data) {
  20.848 -    var data = data || measureLine(cm, line), dir = -1;
  20.849 -    for (var pos = ch;; pos += dir) {
  20.850 -      var r = data[pos];
  20.851 -      if (r) break;
  20.852 -      if (dir < 0 && pos == 0) dir = 1;
  20.853 -    }
  20.854 -    return {left: pos < ch ? r.right : r.left,
  20.855 -            right: pos > ch ? r.left : r.right,
  20.856 -            top: r.top, bottom: r.bottom};
  20.857 -  }
  20.858 -
  20.859 -  function measureLine(cm, line) {
  20.860 -    // First look in the cache
  20.861 -    var display = cm.display, cache = cm.display.measureLineCache;
  20.862 -    for (var i = 0; i < cache.length; ++i) {
  20.863 -      var memo = cache[i];
  20.864 -      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
  20.865 -          display.scroller.clientWidth == memo.width)
  20.866 -        return memo.measure;
  20.867 -    }
  20.868 -    
  20.869 -    var measure = measureLineInner(cm, line);
  20.870 -    // Store result in the cache
  20.871 -    var memo = {text: line.text, width: display.scroller.clientWidth,
  20.872 -                markedSpans: line.markedSpans, measure: measure};
  20.873 -    if (cache.length == 16) cache[++display.measureLineCachePos % 16] = memo;
  20.874 -    else cache.push(memo);
  20.875 -    return measure;
  20.876 -  }
  20.877 -
  20.878 -  function measureLineInner(cm, line) {
  20.879 -    var display = cm.display, measure = emptyArray(line.text.length);
  20.880 -    var pre = lineContent(cm, line, measure);
  20.881 -
  20.882 -    // IE does not cache element positions of inline elements between
  20.883 -    // calls to getBoundingClientRect. This makes the loop below,
  20.884 -    // which gathers the positions of all the characters on the line,
  20.885 -    // do an amount of layout work quadratic to the number of
  20.886 -    // characters. When line wrapping is off, we try to improve things
  20.887 -    // by first subdividing the line into a bunch of inline blocks, so
  20.888 -    // that IE can reuse most of the layout information from caches
  20.889 -    // for those blocks. This does interfere with line wrapping, so it
  20.890 -    // doesn't work when wrapping is on, but in that case the
  20.891 -    // situation is slightly better, since IE does cache line-wrapping
  20.892 -    // information and only recomputes per-line.
  20.893 -    if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
  20.894 -      var fragment = document.createDocumentFragment();
  20.895 -      var chunk = 10, n = pre.childNodes.length;
  20.896 -      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
  20.897 -        var wrap = elt("div", null, null, "display: inline-block");
  20.898 -        for (var j = 0; j < chunk && n; ++j) {
  20.899 -          wrap.appendChild(pre.firstChild);
  20.900 -          --n;
  20.901 -        }
  20.902 -        fragment.appendChild(wrap);
  20.903 -      }
  20.904 -      pre.appendChild(fragment);
  20.905 -    }
  20.906 -
  20.907 -    removeChildrenAndAdd(display.measure, pre);
  20.908 -
  20.909 -    var outer = display.lineDiv.getBoundingClientRect();
  20.910 -    var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
  20.911 -    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
  20.912 -      var size = cur.getBoundingClientRect();
  20.913 -      var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
  20.914 -      for (var j = 0; j < vranges.length; j += 2) {
  20.915 -        var rtop = vranges[j], rbot = vranges[j+1];
  20.916 -        if (rtop > bot || rbot < top) continue;
  20.917 -        if (rtop <= top && rbot >= bot ||
  20.918 -            top <= rtop && bot >= rbot ||
  20.919 -            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
  20.920 -          vranges[j] = Math.min(top, rtop);
  20.921 -          vranges[j+1] = Math.max(bot, rbot);
  20.922 -          break;
  20.923 -        }
  20.924 -      }
  20.925 -      if (j == vranges.length) vranges.push(top, bot);
  20.926 -      data[i] = {left: size.left - outer.left, right: size.right - outer.left, top: j};
  20.927 -    }
  20.928 -    for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
  20.929 -      var vr = cur.top;
  20.930 -      cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
  20.931 -    }
  20.932 -    return data;
  20.933 -  }
  20.934 -
  20.935 -  function clearCaches(cm) {
  20.936 -    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
  20.937 -    cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
  20.938 -    cm.view.maxLineChanged = true;
  20.939 -  }
  20.940 -
  20.941 -  // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
  20.942 -  function intoCoordSystem(cm, lineObj, rect, context) {
  20.943 -    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
  20.944 -      var size = lineObj.widgets[i].node.offsetHeight;
  20.945 -      rect.top += size; rect.bottom += size;
  20.946 -    }
  20.947 -    if (context == "line") return rect;
  20.948 -    if (!context) context = "local";
  20.949 -    var yOff = heightAtLine(cm, lineObj);
  20.950 -    if (context != "local") yOff -= cm.display.viewOffset;
  20.951 -    if (context == "page") {
  20.952 -      var lOff = cm.display.lineSpace.getBoundingClientRect();
  20.953 -      yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
  20.954 -      var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
  20.955 -      rect.left += xOff; rect.right += xOff;
  20.956 -    }
  20.957 -    rect.top += yOff; rect.bottom += yOff;
  20.958 -    return rect;
  20.959 -  }
  20.960 -
  20.961 -  function charCoords(cm, pos, context, lineObj) {
  20.962 -    if (!lineObj) lineObj = getLine(cm.view.doc, pos.line);
  20.963 -    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context);
  20.964 -  }
  20.965 -
  20.966 -  function cursorCoords(cm, pos, context, lineObj, measurement) {
  20.967 -    lineObj = lineObj || getLine(cm.view.doc, pos.line);
  20.968 -    if (!measurement) measurement = measureLine(cm, lineObj);
  20.969 -    function get(ch, right) {
  20.970 -      var m = measureChar(cm, lineObj, ch, measurement);
  20.971 -      if (right) m.left = m.right; else m.right = m.left;
  20.972 -      return intoCoordSystem(cm, lineObj, m, context);
  20.973 -    }
  20.974 -    var order = getOrder(lineObj), ch = pos.ch;
  20.975 -    if (!order) return get(ch);
  20.976 -    var main, other, linedir = order[0].level;
  20.977 -    for (var i = 0; i < order.length; ++i) {
  20.978 -      var part = order[i], rtl = part.level % 2, nb, here;
  20.979 -      if (part.from < ch && part.to > ch) return get(ch, rtl);
  20.980 -      var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
  20.981 -      if (left == ch) {
  20.982 -        // Opera and IE return bogus offsets and widths for edges
  20.983 -        // where the direction flips, but only for the side with the
  20.984 -        // lower level. So we try to use the side with the higher
  20.985 -        // level.
  20.986 -        if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
  20.987 -        else here = get(rtl && part.from != part.to ? ch - 1 : ch);
  20.988 -        if (rtl == linedir) main = here; else other = here;
  20.989 -      } else if (right == ch) {
  20.990 -        var nb = i < order.length - 1 && order[i+1];
  20.991 -        if (!rtl && nb && nb.from == nb.to) continue;
  20.992 -        if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from);
  20.993 -        else here = get(rtl ? ch : ch - 1, true);
  20.994 -        if (rtl == linedir) main = here; else other = here;
  20.995 -      }
  20.996 -    }
  20.997 -    if (linedir && !ch) other = get(order[0].to - 1);
  20.998 -    if (!main) return other;
  20.999 -    if (other) main.other = other;
 20.1000 -    return main;
 20.1001 -  }
 20.1002 -
 20.1003 -  // Coords must be lineSpace-local
 20.1004 -  function coordsChar(cm, x, y) {
 20.1005 -    var doc = cm.view.doc;
 20.1006 -    y += cm.display.viewOffset;
 20.1007 -    if (y < 0) return {line: 0, ch: 0, outside: true};
 20.1008 -    var lineNo = lineAtHeight(doc, y);
 20.1009 -    if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc, doc.size - 1).text.length};
 20.1010 -    if (x < 0) x = 0;
 20.1011 -
 20.1012 -    for (;;) {
 20.1013 -      var lineObj = getLine(doc, lineNo);
 20.1014 -      var found = coordsCharInner(cm, lineObj, lineNo, x, y);
 20.1015 -      var merged = collapsedSpanAtEnd(lineObj);
 20.1016 -      if (merged && found.ch == lineRight(lineObj))
 20.1017 -        lineNo = merged.find().to.line;
 20.1018 -      else
 20.1019 -        return found;
 20.1020 -    }
 20.1021 -  }
 20.1022 -
 20.1023 -  function coordsCharInner(cm, lineObj, lineNo, x, y) {
 20.1024 -    var innerOff = y - heightAtLine(cm, lineObj);
 20.1025 -    var wrongLine = false, cWidth = cm.display.wrapper.clientWidth;
 20.1026 -    var measurement = measureLine(cm, lineObj);
 20.1027 -
 20.1028 -    function getX(ch) {
 20.1029 -      var sp = cursorCoords(cm, {line: lineNo, ch: ch}, "line",
 20.1030 -                            lineObj, measurement);
 20.1031 -      wrongLine = true;
 20.1032 -      if (innerOff > sp.bottom) return Math.max(0, sp.left - cWidth);
 20.1033 -      else if (innerOff < sp.top) return sp.left + cWidth;
 20.1034 -      else wrongLine = false;
 20.1035 -      return sp.left;
 20.1036 -    }
 20.1037 -
 20.1038 -    var bidi = getOrder(lineObj), dist = lineObj.text.length;
 20.1039 -    var from = lineLeft(lineObj), to = lineRight(lineObj);
 20.1040 -    var fromX = paddingLeft(cm.display), toX = getX(to);
 20.1041 -
 20.1042 -    if (x > toX) return {line: lineNo, ch: to, outside: wrongLine};
 20.1043 -    // Do a binary search between these bounds.
 20.1044 -    for (;;) {
 20.1045 -      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
 20.1046 -        var after = x - fromX < toX - x, ch = after ? from : to;
 20.1047 -        while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
 20.1048 -        return {line: lineNo, ch: ch, after: after, outside: wrongLine};
 20.1049 -      }
 20.1050 -      var step = Math.ceil(dist / 2), middle = from + step;
 20.1051 -      if (bidi) {
 20.1052 -        middle = from;
 20.1053 -        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
 20.1054 -      }
 20.1055 -      var middleX = getX(middle);
 20.1056 -      if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; dist -= step;}
 20.1057 -      else {from = middle; fromX = middleX; dist = step;}
 20.1058 -    }
 20.1059 -  }
 20.1060 -
 20.1061 -  var measureText;
 20.1062 -  function textHeight(display) {
 20.1063 -    if (display.cachedTextHeight != null) return display.cachedTextHeight;
 20.1064 -    if (measureText == null) {
 20.1065 -      measureText = elt("pre");
 20.1066 -      // Measure a bunch of lines, for browsers that compute
 20.1067 -      // fractional heights.
 20.1068 -      for (var i = 0; i < 49; ++i) {
 20.1069 -        measureText.appendChild(document.createTextNode("x"));
 20.1070 -        measureText.appendChild(elt("br"));
 20.1071 -      }
 20.1072 -      measureText.appendChild(document.createTextNode("x"));
 20.1073 -    }
 20.1074 -    removeChildrenAndAdd(display.measure, measureText);
 20.1075 -    var height = measureText.offsetHeight / 50;
 20.1076 -    if (height > 3) display.cachedTextHeight = height;
 20.1077 -    removeChildren(display.measure);
 20.1078 -    return height || 1;
 20.1079 -  }
 20.1080 -
 20.1081 -  function charWidth(display) {
 20.1082 -    if (display.cachedCharWidth != null) return display.cachedCharWidth;
 20.1083 -    var anchor = elt("span", "x");
 20.1084 -    var pre = elt("pre", [anchor]);
 20.1085 -    removeChildrenAndAdd(display.measure, pre);
 20.1086 -    var width = anchor.offsetWidth;
 20.1087 -    if (width > 2) display.cachedCharWidth = width;
 20.1088 -    return width || 10;
 20.1089 -  }
 20.1090 -
 20.1091 -  // OPERATIONS
 20.1092 -
 20.1093 -  // Operations are used to wrap changes in such a way that each
 20.1094 -  // change won't have to update the cursor and display (which would
 20.1095 -  // be awkward, slow, and error-prone), but instead updates are
 20.1096 -  // batched and then all combined and executed at once.
 20.1097 -
 20.1098 -  function startOperation(cm) {
 20.1099 -    if (cm.curOp) ++cm.curOp.depth;
 20.1100 -    else cm.curOp = {
 20.1101 -      // Nested operations delay update until the outermost one
 20.1102 -      // finishes.
 20.1103 -      depth: 1,
 20.1104 -      // An array of ranges of lines that have to be updated. See
 20.1105 -      // updateDisplay.
 20.1106 -      changes: [],
 20.1107 -      delayedCallbacks: [],
 20.1108 -      updateInput: null,
 20.1109 -      userSelChange: null,
 20.1110 -      textChanged: null,
 20.1111 -      selectionChanged: false,
 20.1112 -      updateMaxLine: false,
 20.1113 -      id: ++cm.nextOpId
 20.1114 -    };
 20.1115 -  }
 20.1116 -
 20.1117 -  function endOperation(cm) {
 20.1118 -    var op = cm.curOp;
 20.1119 -    if (--op.depth) return;
 20.1120 -    cm.curOp = null;
 20.1121 -    var view = cm.view, display = cm.display;
 20.1122 -    if (op.updateMaxLine) computeMaxLength(view);
 20.1123 -    if (view.maxLineChanged && !cm.options.lineWrapping) {
 20.1124 -      var width = measureChar(cm, view.maxLine, view.maxLine.text.length).right;
 20.1125 -      display.sizer.style.minWidth = (width + 3 + scrollerCutOff) + "px";
 20.1126 -      view.maxLineChanged = false;
 20.1127 -    }
 20.1128 -    var newScrollPos, updated;
 20.1129 -    if (op.selectionChanged) {
 20.1130 -      var coords = cursorCoords(cm, view.sel.head);
 20.1131 -      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
 20.1132 -    }
 20.1133 -    if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null)
 20.1134 -      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
 20.1135 -    if (!updated && op.selectionChanged) updateSelection(cm);
 20.1136 -    if (newScrollPos) scrollCursorIntoView(cm);
 20.1137 -    if (op.selectionChanged) restartBlink(cm);
 20.1138 -
 20.1139 -    if (view.focused && op.updateInput)
 20.1140 -      resetInput(cm, op.userSelChange);
 20.1141 -
 20.1142 -    if (op.textChanged)
 20.1143 -      signal(cm, "change", cm, op.textChanged);
 20.1144 -    if (op.selectionChanged) signal(cm, "cursorActivity", cm);
 20.1145 -    for (var i = 0; i < op.delayedCallbacks.length; ++i) op.delayedCallbacks[i](cm);
 20.1146 -  }
 20.1147 -
 20.1148 -  // Wraps a function in an operation. Returns the wrapped function.
 20.1149 -  function operation(cm1, f) {
 20.1150 -    return function() {
 20.1151 -      var cm = cm1 || this;
 20.1152 -      startOperation(cm);
 20.1153 -      try {var result = f.apply(cm, arguments);}
 20.1154 -      finally {endOperation(cm);}
 20.1155 -      return result;
 20.1156 -    };
 20.1157 -  }
 20.1158 -
 20.1159 -  function regChange(cm, from, to, lendiff) {
 20.1160 -    cm.curOp.changes.push({from: from, to: to, diff: lendiff});
 20.1161 -  }
 20.1162 -
 20.1163 -  // INPUT HANDLING
 20.1164 -
 20.1165 -  function slowPoll(cm) {
 20.1166 -    if (cm.view.pollingFast) return;
 20.1167 -    cm.display.poll.set(cm.options.pollInterval, function() {
 20.1168 -      readInput(cm);
 20.1169 -      if (cm.view.focused) slowPoll(cm);
 20.1170 -    });
 20.1171 -  }
 20.1172 -
 20.1173 -  function fastPoll(cm) {
 20.1174 -    var missed = false;
 20.1175 -    cm.display.pollingFast = true;
 20.1176 -    function p() {
 20.1177 -      var changed = readInput(cm);
 20.1178 -      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
 20.1179 -      else {cm.display.pollingFast = false; slowPoll(cm);}
 20.1180 -    }
 20.1181 -    cm.display.poll.set(20, p);
 20.1182 -  }
 20.1183 -
 20.1184 -  // prevInput is a hack to work with IME. If we reset the textarea
 20.1185 -  // on every change, that breaks IME. So we look for changes
 20.1186 -  // compared to the previous content instead. (Modern browsers have
 20.1187 -  // events that indicate IME taking place, but these are not widely
 20.1188 -  // supported or compatible enough yet to rely on.)
 20.1189 -  function readInput(cm) {
 20.1190 -    var input = cm.display.input, prevInput = cm.display.prevInput, view = cm.view, sel = view.sel;
 20.1191 -    if (!view.focused || hasSelection(input) || isReadOnly(cm)) return false;
 20.1192 -    var text = input.value;
 20.1193 -    if (text == prevInput && posEq(sel.from, sel.to)) return false;
 20.1194 -    startOperation(cm);
 20.1195 -    view.sel.shift = false;
 20.1196 -    var same = 0, l = Math.min(prevInput.length, text.length);
 20.1197 -    while (same < l && prevInput[same] == text[same]) ++same;
 20.1198 -    var from = sel.from, to = sel.to;
 20.1199 -    if (same < prevInput.length)
 20.1200 -      from = {line: from.line, ch: from.ch - (prevInput.length - same)};
 20.1201 -    else if (view.overwrite && posEq(from, to) && !cm.display.pasteIncoming)
 20.1202 -      to = {line: to.line, ch: Math.min(getLine(cm.view.doc, to.line).text.length, to.ch + (text.length - same))};
 20.1203 -    var updateInput = cm.curOp.updateInput;
 20.1204 -    updateDoc(cm, from, to, splitLines(text.slice(same)), "end",
 20.1205 -              cm.display.pasteIncoming ? "paste" : "input", {from: from, to: to});
 20.1206 -    cm.curOp.updateInput = updateInput;
 20.1207 -    if (text.length > 1000) input.value = cm.display.prevInput = "";
 20.1208 -    else cm.display.prevInput = text;
 20.1209 -    endOperation(cm);
 20.1210 -    cm.display.pasteIncoming = false;
 20.1211 -    return true;
 20.1212 -  }
 20.1213 -
 20.1214 -  function resetInput(cm, user) {
 20.1215 -    var view = cm.view, minimal, selected;
 20.1216 -    if (!posEq(view.sel.from, view.sel.to)) {
 20.1217 -      cm.display.prevInput = "";
 20.1218 -      minimal = hasCopyEvent &&
 20.1219 -        (view.sel.to.line - view.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
 20.1220 -      if (minimal) cm.display.input.value = "-";
 20.1221 -      else cm.display.input.value = selected || cm.getSelection();
 20.1222 -      if (view.focused) selectInput(cm.display.input);
 20.1223 -    } else if (user) cm.display.prevInput = cm.display.input.value = "";
 20.1224 -    cm.display.inaccurateSelection = minimal;
 20.1225 -  }
 20.1226 -
 20.1227 -  function focusInput(cm) {
 20.1228 -    if (cm.options.readOnly != "nocursor" && (ie || document.activeElement != cm.display.input))
 20.1229 -      cm.display.input.focus();
 20.1230 -  }
 20.1231 -
 20.1232 -  function isReadOnly(cm) {
 20.1233 -    return cm.options.readOnly || cm.view.cantEdit;
 20.1234 -  }
 20.1235 -
 20.1236 -  // EVENT HANDLERS
 20.1237 -
 20.1238 -  function registerEventHandlers(cm) {
 20.1239 -    var d = cm.display;
 20.1240 -    on(d.scroller, "mousedown", operation(cm, onMouseDown));
 20.1241 -    on(d.scroller, "dblclick", operation(cm, e_preventDefault));
 20.1242 -    on(d.lineSpace, "selectstart", function(e) {
 20.1243 -      if (!mouseEventInWidget(d, e)) e_preventDefault(e);
 20.1244 -    });
 20.1245 -    // Gecko browsers fire contextmenu *after* opening the menu, at
 20.1246 -    // which point we can't mess with it anymore. Context menu is
 20.1247 -    // handled in onMouseDown for Gecko.
 20.1248 -    if (!gecko) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
 20.1249 -
 20.1250 -    on(d.scroller, "scroll", function() {
 20.1251 -      setScrollTop(cm, d.scroller.scrollTop);
 20.1252 -      setScrollLeft(cm, d.scroller.scrollLeft, true);
 20.1253 -      signal(cm, "scroll", cm);
 20.1254 -    });
 20.1255 -    on(d.scrollbarV, "scroll", function() {
 20.1256 -      setScrollTop(cm, d.scrollbarV.scrollTop);
 20.1257 -    });
 20.1258 -    on(d.scrollbarH, "scroll", function() {
 20.1259 -      setScrollLeft(cm, d.scrollbarH.scrollLeft);
 20.1260 -    });
 20.1261 -
 20.1262 -    on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
 20.1263 -    on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
 20.1264 -
 20.1265 -    function reFocus() { if (cm.view.focused) setTimeout(bind(focusInput, cm), 0); }
 20.1266 -    on(d.scrollbarH, "mousedown", reFocus);
 20.1267 -    on(d.scrollbarV, "mousedown", reFocus);
 20.1268 -    // Prevent wrapper from ever scrolling
 20.1269 -    on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
 20.1270 -    on(window, "resize", function resizeHandler() {
 20.1271 -      // Might be a text scaling operation, clear size caches.
 20.1272 -      d.cachedCharWidth = d.cachedTextHeight = null;
 20.1273 -      clearCaches(cm);
 20.1274 -      if (d.wrapper.parentNode) updateDisplay(cm, true);
 20.1275 -      else off(window, "resize", resizeHandler);
 20.1276 -    });
 20.1277 -
 20.1278 -    on(d.input, "keyup", operation(cm, function(e) {
 20.1279 -      if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
 20.1280 -      if (e_prop(e, "keyCode") == 16) cm.view.sel.shift = false;
 20.1281 -    }));
 20.1282 -    on(d.input, "input", bind(fastPoll, cm));
 20.1283 -    on(d.input, "keydown", operation(cm, onKeyDown));
 20.1284 -    on(d.input, "keypress", operation(cm, onKeyPress));
 20.1285 -    on(d.input, "focus", bind(onFocus, cm));
 20.1286 -    on(d.input, "blur", bind(onBlur, cm));
 20.1287 -
 20.1288 -    function drag_(e) {
 20.1289 -      if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
 20.1290 -      e_stop(e);
 20.1291 -    }
 20.1292 -    if (cm.options.dragDrop) {
 20.1293 -      on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
 20.1294 -      on(d.scroller, "dragenter", drag_);
 20.1295 -      on(d.scroller, "dragover", drag_);
 20.1296 -      on(d.scroller, "drop", operation(cm, onDrop));
 20.1297 -    }
 20.1298 -    on(d.scroller, "paste", function(){focusInput(cm); fastPoll(cm);});
 20.1299 -    on(d.input, "paste", function() {
 20.1300 -      d.pasteIncoming = true;
 20.1301 -      fastPoll(cm);
 20.1302 -    });
 20.1303 -
 20.1304 -    function prepareCopy() {
 20.1305 -      if (d.inaccurateSelection) {
 20.1306 -        d.prevInput = "";
 20.1307 -        d.inaccurateSelection = false;
 20.1308 -        d.input.value = cm.getSelection();
 20.1309 -        selectInput(d.input);
 20.1310 -      }
 20.1311 -    }
 20.1312 -    on(d.input, "cut", prepareCopy);
 20.1313 -    on(d.input, "copy", prepareCopy);
 20.1314 -
 20.1315 -    // Needed to handle Tab key in KHTML
 20.1316 -    if (khtml) on(d.sizer, "mouseup", function() {
 20.1317 -        if (document.activeElement == d.input) d.input.blur();
 20.1318 -        focusInput(cm);
 20.1319 -    });
 20.1320 -  }
 20.1321 -
 20.1322 -  function mouseEventInWidget(display, e) {
 20.1323 -    for (var n = e_target(e); n != display.wrapper; n = n.parentNode)
 20.1324 -      if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
 20.1325 -          n.parentNode == display.sizer && n != display.mover) return true;
 20.1326 -  }
 20.1327 -
 20.1328 -  function posFromMouse(cm, e, liberal) {
 20.1329 -    var display = cm.display;
 20.1330 -    if (!liberal) {
 20.1331 -      var target = e_target(e);
 20.1332 -      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
 20.1333 -          target == display.scrollbarV || target == display.scrollbarV.firstChild ||
 20.1334 -          target == display.scrollbarFiller) return null;
 20.1335 -    }
 20.1336 -    var x, y, space = display.lineSpace.getBoundingClientRect();
 20.1337 -    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
 20.1338 -    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
 20.1339 -    return coordsChar(cm, x - space.left, y - space.top);
 20.1340 -  }
 20.1341 -
 20.1342 -  var lastClick, lastDoubleClick;
 20.1343 -  function onMouseDown(e) {
 20.1344 -    var cm = this, display = cm.display, view = cm.view, sel = view.sel, doc = view.doc;
 20.1345 -    sel.shift = e_prop(e, "shiftKey");
 20.1346 -
 20.1347 -    if (mouseEventInWidget(display, e)) {
 20.1348 -      if (!webkit) {
 20.1349 -        display.scroller.draggable = false;
 20.1350 -        setTimeout(function(){display.scroller.draggable = true;}, 100);
 20.1351 -      }
 20.1352 -      return;
 20.1353 -    }
 20.1354 -    if (clickInGutter(cm, e)) return;
 20.1355 -    var start = posFromMouse(cm, e);
 20.1356 -
 20.1357 -    switch (e_button(e)) {
 20.1358 -    case 3:
 20.1359 -      if (gecko) onContextMenu.call(cm, cm, e);
 20.1360 -      return;
 20.1361 -    case 2:
 20.1362 -      if (start) extendSelection(cm, start);
 20.1363 -      setTimeout(bind(focusInput, cm), 20);
 20.1364 -      e_preventDefault(e);
 20.1365 -      return;
 20.1366 -    }
 20.1367 -    // For button 1, if it was clicked inside the editor
 20.1368 -    // (posFromMouse returning non-null), we have to adjust the
 20.1369 -    // selection.
 20.1370 -    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
 20.1371 -
 20.1372 -    if (!view.focused) onFocus(cm);
 20.1373 -
 20.1374 -    var now = +new Date, type = "single";
 20.1375 -    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
 20.1376 -      type = "triple";
 20.1377 -      e_preventDefault(e);
 20.1378 -      setTimeout(bind(focusInput, cm), 20);
 20.1379 -      selectLine(cm, start.line);
 20.1380 -    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
 20.1381 -      type = "double";
 20.1382 -      lastDoubleClick = {time: now, pos: start};
 20.1383 -      e_preventDefault(e);
 20.1384 -      var word = findWordAt(getLine(doc, start.line).text, start);
 20.1385 -      extendSelection(cm, word.from, word.to);
 20.1386 -    } else { lastClick = {time: now, pos: start}; }
 20.1387 -
 20.1388 -    var last = start;
 20.1389 -    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
 20.1390 -        !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
 20.1391 -      var dragEnd = operation(cm, function(e2) {
 20.1392 -        if (webkit) display.scroller.draggable = false;
 20.1393 -        view.draggingText = false;
 20.1394 -        off(document, "mouseup", dragEnd);
 20.1395 -        off(display.scroller, "drop", dragEnd);
 20.1396 -        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
 20.1397 -          e_preventDefault(e2);
 20.1398 -          extendSelection(cm, start);
 20.1399 -          focusInput(cm);
 20.1400 -        }
 20.1401 -      });
 20.1402 -      // Let the drag handler handle this.
 20.1403 -      if (webkit) display.scroller.draggable = true;
 20.1404 -      view.draggingText = dragEnd;
 20.1405 -      // IE's approach to draggable
 20.1406 -      if (display.scroller.dragDrop) display.scroller.dragDrop();
 20.1407 -      on(document, "mouseup", dragEnd);
 20.1408 -      on(display.scroller, "drop", dragEnd);
 20.1409 -      return;
 20.1410 -    }
 20.1411 -    e_preventDefault(e);
 20.1412 -    if (type == "single") extendSelection(cm, clipPos(doc, start));
 20.1413 -
 20.1414 -    var startstart = sel.from, startend = sel.to;
 20.1415 -
 20.1416 -    function doSelect(cur) {
 20.1417 -      if (type == "single") {
 20.1418 -        extendSelection(cm, clipPos(doc, start), cur);
 20.1419 -        return;
 20.1420 -      }
 20.1421 -
 20.1422 -      startstart = clipPos(doc, startstart);
 20.1423 -      startend = clipPos(doc, startend);
 20.1424 -      if (type == "double") {
 20.1425 -        var word = findWordAt(getLine(doc, cur.line).text, cur);
 20.1426 -        if (posLess(cur, startstart)) extendSelection(cm, word.from, startend);
 20.1427 -        else extendSelection(cm, startstart, word.to);
 20.1428 -      } else if (type == "triple") {
 20.1429 -        if (posLess(cur, startstart)) extendSelection(cm, startend, clipPos(doc, {line: cur.line, ch: 0}));
 20.1430 -        else extendSelection(cm, startstart, clipPos(doc, {line: cur.line + 1, ch: 0}));
 20.1431 -      }
 20.1432 -    }
 20.1433 -
 20.1434 -    var editorSize = display.wrapper.getBoundingClientRect();
 20.1435 -    // Used to ensure timeout re-tries don't fire when another extend
 20.1436 -    // happened in the meantime (clearTimeout isn't reliable -- at
 20.1437 -    // least on Chrome, the timeouts still happen even when cleared,
 20.1438 -    // if the clear happens after their scheduled firing time).
 20.1439 -    var counter = 0;
 20.1440 -
 20.1441 -    function extend(e) {
 20.1442 -      var curCount = ++counter;
 20.1443 -      var cur = posFromMouse(cm, e, true);
 20.1444 -      if (!cur) return;
 20.1445 -      if (!posEq(cur, last)) {
 20.1446 -        if (!view.focused) onFocus(cm);
 20.1447 -        last = cur;
 20.1448 -        doSelect(cur);
 20.1449 -        var visible = visibleLines(display, doc);
 20.1450 -        if (cur.line >= visible.to || cur.line < visible.from)
 20.1451 -          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
 20.1452 -      } else {
 20.1453 -        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
 20.1454 -        if (outside) setTimeout(operation(cm, function() {
 20.1455 -          if (counter != curCount) return;
 20.1456 -          display.scroller.scrollTop += outside;
 20.1457 -          extend(e);
 20.1458 -        }), 50);
 20.1459 -      }
 20.1460 -    }
 20.1461 -
 20.1462 -    function done(e) {
 20.1463 -      counter = Infinity;
 20.1464 -      var cur = posFromMouse(cm, e);
 20.1465 -      if (cur) doSelect(cur);
 20.1466 -      e_preventDefault(e);
 20.1467 -      focusInput(cm);
 20.1468 -      off(document, "mousemove", move);
 20.1469 -      off(document, "mouseup", up);
 20.1470 -    }
 20.1471 -
 20.1472 -    var move = operation(cm, function(e) {
 20.1473 -      if (!ie && !e_button(e)) done(e);
 20.1474 -      else extend(e);
 20.1475 -    });
 20.1476 -    var up = operation(cm, done);
 20.1477 -    on(document, "mousemove", move);
 20.1478 -    on(document, "mouseup", up);
 20.1479 -  }
 20.1480 -
 20.1481 -  function onDrop(e) {
 20.1482 -    var cm = this;
 20.1483 -    if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
 20.1484 -    e_preventDefault(e);
 20.1485 -    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
 20.1486 -    if (!pos || isReadOnly(cm)) return;
 20.1487 -    if (files && files.length && window.FileReader && window.File) {
 20.1488 -      var n = files.length, text = Array(n), read = 0;
 20.1489 -      var loadFile = function(file, i) {
 20.1490 -        var reader = new FileReader;
 20.1491 -        reader.onload = function() {
 20.1492 -          text[i] = reader.result;
 20.1493 -          if (++read == n) {
 20.1494 -            pos = clipPos(cm.view.doc, pos);
 20.1495 -            operation(cm, function() {
 20.1496 -              var end = replaceRange(cm, text.join(""), pos, pos, "paste");
 20.1497 -              setSelection(cm, pos, end);
 20.1498 -            })();
 20.1499 -          }
 20.1500 -        };
 20.1501 -        reader.readAsText(file);
 20.1502 -      };
 20.1503 -      for (var i = 0; i < n; ++i) loadFile(files[i], i);
 20.1504 -    } else {
 20.1505 -      // Don't do a replace if the drop happened inside of the selected text.
 20.1506 -      if (cm.view.draggingText && !(posLess(pos, cm.view.sel.from) || posLess(cm.view.sel.to, pos))) {
 20.1507 -        cm.view.draggingText(e);
 20.1508 -        if (ie) setTimeout(bind(focusInput, cm), 50);
 20.1509 -        return;
 20.1510 -      }
 20.1511 -      try {
 20.1512 -        var text = e.dataTransfer.getData("Text");
 20.1513 -        if (text) {
 20.1514 -          var curFrom = cm.view.sel.from, curTo = cm.view.sel.to;
 20.1515 -          setSelection(cm, pos, pos);
 20.1516 -          if (cm.view.draggingText) replaceRange(cm, "", curFrom, curTo, "paste");
 20.1517 -          cm.replaceSelection(text, null, "paste");
 20.1518 -          focusInput(cm);
 20.1519 -          onFocus(cm);
 20.1520 -        }
 20.1521 -      }
 20.1522 -      catch(e){}
 20.1523 -    }
 20.1524 -  }
 20.1525 -
 20.1526 -  function clickInGutter(cm, e) {
 20.1527 -    var display = cm.display;
 20.1528 -    try { var mX = e.clientX, mY = e.clientY; }
 20.1529 -    catch(e) { return false; }
 20.1530 -
 20.1531 -    if (mX >= Math.floor(display.gutters.getBoundingClientRect().right)) return false;
 20.1532 -    e_preventDefault(e);
 20.1533 -    if (!hasHandler(cm, "gutterClick")) return true;
 20.1534 -
 20.1535 -    var lineBox = display.lineDiv.getBoundingClientRect();
 20.1536 -    if (mY > lineBox.bottom) return true;
 20.1537 -    mY -= lineBox.top - display.viewOffset;
 20.1538 -
 20.1539 -    for (var i = 0; i < cm.options.gutters.length; ++i) {
 20.1540 -      var g = display.gutters.childNodes[i];
 20.1541 -      if (g && g.getBoundingClientRect().right >= mX) {
 20.1542 -        var line = lineAtHeight(cm.view.doc, mY);
 20.1543 -        var gutter = cm.options.gutters[i];
 20.1544 -        signalLater(cm, cm, "gutterClick", cm, line, gutter, e);
 20.1545 -        break;
 20.1546 -      }
 20.1547 -    }
 20.1548 -    return true;
 20.1549 -  }
 20.1550 -
 20.1551 -  function onDragStart(cm, e) {
 20.1552 -    var txt = cm.getSelection();
 20.1553 -    e.dataTransfer.setData("Text", txt);
 20.1554 -
 20.1555 -    // Use dummy image instead of default browsers image.
 20.1556 -    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
 20.1557 -    if (e.dataTransfer.setDragImage && !safari)
 20.1558 -      e.dataTransfer.setDragImage(elt('img'), 0, 0);
 20.1559 -  }
 20.1560 -
 20.1561 -  function setScrollTop(cm, val) {
 20.1562 -    if (Math.abs(cm.view.scrollTop - val) < 2) return;
 20.1563 -    cm.view.scrollTop = val;
 20.1564 -    if (!gecko) updateDisplay(cm, [], val);
 20.1565 -    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
 20.1566 -    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
 20.1567 -    if (gecko) updateDisplay(cm, []);
 20.1568 -  }
 20.1569 -  function setScrollLeft(cm, val, isScroller) {
 20.1570 -    if (isScroller ? val == cm.view.scrollLeft : Math.abs(cm.view.scrollLeft - val) < 2) return;
 20.1571 -    cm.view.scrollLeft = val;
 20.1572 -    alignHorizontally(cm);
 20.1573 -    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
 20.1574 -    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
 20.1575 -  }
 20.1576 -
 20.1577 -  // Since the delta values reported on mouse wheel events are
 20.1578 -  // unstandardized between browsers and even browser versions, and
 20.1579 -  // generally horribly unpredictable, this code starts by measuring
 20.1580 -  // the scroll effect that the first few mouse wheel events have,
 20.1581 -  // and, from that, detects the way it can convert deltas to pixel
 20.1582 -  // offsets afterwards.
 20.1583 -  //
 20.1584 -  // The reason we want to know the amount a wheel event will scroll
 20.1585 -  // is that it gives us a chance to update the display before the
 20.1586 -  // actual scrolling happens, reducing flickering.
 20.1587 -
 20.1588 -  var wheelSamples = 0, wheelDX, wheelDY, wheelStartX, wheelStartY, wheelPixelsPerUnit = null;
 20.1589 -  // Fill in a browser-detected starting value on browsers where we
 20.1590 -  // know one. These don't have to be accurate -- the result of them
 20.1591 -  // being wrong would just be a slight flicker on the first wheel
 20.1592 -  // scroll (if it is large enough).
 20.1593 -  if (ie) wheelPixelsPerUnit = -.53;
 20.1594 -  else if (gecko) wheelPixelsPerUnit = 15;
 20.1595 -  else if (chrome) wheelPixelsPerUnit = -.7;
 20.1596 -  else if (safari) wheelPixelsPerUnit = -1/3;
 20.1597 -
 20.1598 -  function onScrollWheel(cm, e) {
 20.1599 -    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
 20.1600 -    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
 20.1601 -    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
 20.1602 -    else if (dy == null) dy = e.wheelDelta;
 20.1603 -
 20.1604 -    // Webkit browsers on OS X abort momentum scrolls when the target
 20.1605 -    // of the scroll event is removed from the scrollable element.
 20.1606 -    // This hack (see related code in patchDisplay) makes sure the
 20.1607 -    // element is kept around.
 20.1608 -    if (dy && mac && webkit) {
 20.1609 -      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
 20.1610 -        if (cur.lineObj) {
 20.1611 -          cm.display.currentWheelTarget = cur;
 20.1612 -          break;
 20.1613 -        }
 20.1614 -      }
 20.1615 -    }
 20.1616 -
 20.1617 -    var scroll = cm.display.scroller;
 20.1618 -    // On some browsers, horizontal scrolling will cause redraws to
 20.1619 -    // happen before the gutter has been realigned, causing it to
 20.1620 -    // wriggle around in a most unseemly way. When we have an
 20.1621 -    // estimated pixels/delta value, we just handle horizontal
 20.1622 -    // scrolling entirely here. It'll be slightly off from native, but
 20.1623 -    // better than glitching out.
 20.1624 -    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
 20.1625 -      if (dy)
 20.1626 -        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
 20.1627 -      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
 20.1628 -      e_preventDefault(e);
 20.1629 -      wheelStartX = null; // Abort measurement, if in progress
 20.1630 -      return;
 20.1631 -    }
 20.1632 -
 20.1633 -    if (dy && wheelPixelsPerUnit != null) {
 20.1634 -      var pixels = dy * wheelPixelsPerUnit;
 20.1635 -      var top = cm.view.scrollTop, bot = top + cm.display.wrapper.clientHeight;
 20.1636 -      if (pixels < 0) top = Math.max(0, top + pixels - 50);
 20.1637 -      else bot = Math.min(cm.view.doc.height, bot + pixels + 50);
 20.1638 -      updateDisplay(cm, [], {top: top, bottom: bot});
 20.1639 -    }
 20.1640 -
 20.1641 -    if (wheelSamples < 20) {
 20.1642 -      if (wheelStartX == null) {
 20.1643 -        wheelStartX = scroll.scrollLeft; wheelStartY = scroll.scrollTop;
 20.1644 -        wheelDX = dx; wheelDY = dy;
 20.1645 -        setTimeout(function() {
 20.1646 -          if (wheelStartX == null) return;
 20.1647 -          var movedX = scroll.scrollLeft - wheelStartX;
 20.1648 -          var movedY = scroll.scrollTop - wheelStartY;
 20.1649 -          var sample = (movedY && wheelDY && movedY / wheelDY) ||
 20.1650 -            (movedX && wheelDX && movedX / wheelDX);
 20.1651 -          wheelStartX = wheelStartY = null;
 20.1652 -          if (!sample) return;
 20.1653 -          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
 20.1654 -          ++wheelSamples;
 20.1655 -        }, 200);
 20.1656 -      } else {
 20.1657 -        wheelDX += dx; wheelDY += dy;
 20.1658 -      }
 20.1659 -    }
 20.1660 -  }
 20.1661 -
 20.1662 -  function doHandleBinding(cm, bound, dropShift) {
 20.1663 -    if (typeof bound == "string") {
 20.1664 -      bound = commands[bound];
 20.1665 -      if (!bound) return false;
 20.1666 -    }
 20.1667 -    // Ensure previous input has been read, so that the handler sees a
 20.1668 -    // consistent view of the document
 20.1669 -    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
 20.1670 -    var view = cm.view, prevShift = view.sel.shift;
 20.1671 -    try {
 20.1672 -      if (isReadOnly(cm)) view.suppressEdits = true;
 20.1673 -      if (dropShift) view.sel.shift = false;
 20.1674 -      bound(cm);
 20.1675 -    } catch(e) {
 20.1676 -      if (e != Pass) throw e;
 20.1677 -      return false;
 20.1678 -    } finally {
 20.1679 -      view.sel.shift = prevShift;
 20.1680 -      view.suppressEdits = false;
 20.1681 -    }
 20.1682 -    return true;
 20.1683 -  }
 20.1684 -
 20.1685 -  function allKeyMaps(cm) {
 20.1686 -    var maps = cm.view.keyMaps.slice(0);
 20.1687 -    maps.push(cm.options.keyMap);
 20.1688 -    if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys);
 20.1689 -    return maps;
 20.1690 -  }
 20.1691 -
 20.1692 -  var maybeTransition;
 20.1693 -  function handleKeyBinding(cm, e) {
 20.1694 -    // Handle auto keymap transitions
 20.1695 -    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
 20.1696 -    clearTimeout(maybeTransition);
 20.1697 -    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
 20.1698 -      if (getKeyMap(cm.options.keyMap) == startMap)
 20.1699 -        cm.options.keyMap = (next.call ? next.call(null, cm) : next);
 20.1700 -    }, 50);
 20.1701 -
 20.1702 -    var name = keyNames[e_prop(e, "keyCode")], handled = false;
 20.1703 -    var flipCtrlCmd = mac && (opera || qtwebkit);
 20.1704 -    if (name == null || e.altGraphKey) return false;
 20.1705 -    if (e_prop(e, "altKey")) name = "Alt-" + name;
 20.1706 -    if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name;
 20.1707 -    if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name;
 20.1708 -
 20.1709 -    var stopped = false;
 20.1710 -    function stop() { stopped = true; }
 20.1711 -    var keymaps = allKeyMaps(cm);
 20.1712 -
 20.1713 -    if (e_prop(e, "shiftKey")) {
 20.1714 -      handled = lookupKey("Shift-" + name, keymaps,
 20.1715 -                          function(b) {return doHandleBinding(cm, b, true);}, stop)
 20.1716 -        || lookupKey(name, keymaps, function(b) {
 20.1717 -          if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b);
 20.1718 -        }, stop);
 20.1719 -    } else {
 20.1720 -      handled = lookupKey(name, keymaps,
 20.1721 -                          function(b) { return doHandleBinding(cm, b); }, stop);
 20.1722 -    }
 20.1723 -    if (stopped) handled = false;
 20.1724 -    if (handled) {
 20.1725 -      e_preventDefault(e);
 20.1726 -      restartBlink(cm);
 20.1727 -      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
 20.1728 -    }
 20.1729 -    return handled;
 20.1730 -  }
 20.1731 -
 20.1732 -  function handleCharBinding(cm, e, ch) {
 20.1733 -    var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
 20.1734 -                            function(b) { return doHandleBinding(cm, b, true); });
 20.1735 -    if (handled) {
 20.1736 -      e_preventDefault(e);
 20.1737 -      restartBlink(cm);
 20.1738 -    }
 20.1739 -    return handled;
 20.1740 -  }
 20.1741 -
 20.1742 -  var lastStoppedKey = null;
 20.1743 -  function onKeyDown(e) {
 20.1744 -    var cm = this;
 20.1745 -    if (!cm.view.focused) onFocus(cm);
 20.1746 -    if (ie && e.keyCode == 27) { e.returnValue = false; }
 20.1747 -    if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
 20.1748 -    var code = e_prop(e, "keyCode");
 20.1749 -    // IE does strange things with escape.
 20.1750 -    cm.view.sel.shift = code == 16 || e_prop(e, "shiftKey");
 20.1751 -    // First give onKeyEvent option a chance to handle this.
 20.1752 -    var handled = handleKeyBinding(cm, e);
 20.1753 -    if (opera) {
 20.1754 -      lastStoppedKey = handled ? code : null;
 20.1755 -      // Opera has no cut event... we try to at least catch the key combo
 20.1756 -      if (!handled && code == 88 && !hasCopyEvent && e_prop(e, mac ? "metaKey" : "ctrlKey"))
 20.1757 -        cm.replaceSelection("");
 20.1758 -    }
 20.1759 -  }
 20.1760 -
 20.1761 -  function onKeyPress(e) {
 20.1762 -    var cm = this;
 20.1763 -    if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
 20.1764 -    var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
 20.1765 -    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
 20.1766 -    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
 20.1767 -    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
 20.1768 -    if (this.options.electricChars && this.view.mode.electricChars &&
 20.1769 -        this.options.smartIndent && !isReadOnly(this) &&
 20.1770 -        this.view.mode.electricChars.indexOf(ch) > -1)
 20.1771 -      setTimeout(operation(cm, function() {indentLine(cm, cm.view.sel.to.line, "smart");}), 75);
 20.1772 -    if (handleCharBinding(cm, e, ch)) return;
 20.1773 -    fastPoll(cm);
 20.1774 -  }
 20.1775 -
 20.1776 -  function onFocus(cm) {
 20.1777 -    if (cm.options.readOnly == "nocursor") return;
 20.1778 -    if (!cm.view.focused) {
 20.1779 -      signal(cm, "focus", cm);
 20.1780 -      cm.view.focused = true;
 20.1781 -      if (cm.display.scroller.className.search(/\bCodeMirror-focused\b/) == -1)
 20.1782 -        cm.display.scroller.className += " CodeMirror-focused";
 20.1783 -      resetInput(cm, true);
 20.1784 -    }
 20.1785 -    slowPoll(cm);
 20.1786 -    restartBlink(cm);
 20.1787 -  }
 20.1788 -  function onBlur(cm) {
 20.1789 -    if (cm.view.focused) {
 20.1790 -      signal(cm, "blur", cm);
 20.1791 -      cm.view.focused = false;
 20.1792 -      cm.display.scroller.className = cm.display.scroller.className.replace(" CodeMirror-focused", "");
 20.1793 -    }
 20.1794 -    clearInterval(cm.display.blinker);
 20.1795 -    setTimeout(function() {if (!cm.view.focused) cm.view.sel.shift = false;}, 150);
 20.1796 -  }
 20.1797 -
 20.1798 -  var detectingSelectAll;
 20.1799 -  function onContextMenu(cm, e) {
 20.1800 -    var display = cm.display, sel = cm.view.sel;
 20.1801 -    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
 20.1802 -    if (!pos || opera) return; // Opera is difficult.
 20.1803 -    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
 20.1804 -      operation(cm, setSelection)(cm, pos, pos);
 20.1805 -
 20.1806 -    var oldCSS = display.input.style.cssText;
 20.1807 -    display.inputDiv.style.position = "absolute";
 20.1808 -    display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
 20.1809 -      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
 20.1810 -      "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
 20.1811 -    focusInput(cm);
 20.1812 -    resetInput(cm, true);
 20.1813 -    // Adds "Select all" to context menu in FF
 20.1814 -    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
 20.1815 -
 20.1816 -    function rehide() {
 20.1817 -      display.inputDiv.style.position = "relative";
 20.1818 -      display.input.style.cssText = oldCSS;
 20.1819 -      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
 20.1820 -      slowPoll(cm);
 20.1821 -
 20.1822 -      // Try to detect the user choosing select-all 
 20.1823 -      if (display.input.selectionStart != null) {
 20.1824 -        clearTimeout(detectingSelectAll);
 20.1825 -        var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
 20.1826 -        display.prevInput = " ";
 20.1827 -        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
 20.1828 -        detectingSelectAll = setTimeout(function poll(){
 20.1829 -          if (display.prevInput == " " && display.input.selectionStart == 0)
 20.1830 -            operation(cm, commands.selectAll)(cm);
 20.1831 -          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
 20.1832 -          else resetInput(cm);
 20.1833 -        }, 200);
 20.1834 -      }
 20.1835 -    }
 20.1836 -
 20.1837 -    if (gecko) {
 20.1838 -      e_stop(e);
 20.1839 -      on(window, "mouseup", function mouseup() {
 20.1840 -        off(window, "mouseup", mouseup);
 20.1841 -        setTimeout(rehide, 20);
 20.1842 -      });
 20.1843 -    } else {
 20.1844 -      setTimeout(rehide, 50);
 20.1845 -    }
 20.1846 -  }
 20.1847 -
 20.1848 -  // UPDATING
 20.1849 -
 20.1850 -  // Replace the range from from to to by the strings in newText.
 20.1851 -  // Afterwards, set the selection to selFrom, selTo.
 20.1852 -  function updateDoc(cm, from, to, newText, selUpdate, origin) {
 20.1853 -    // Possibly split or suppress the update based on the presence
 20.1854 -    // of read-only spans in its range.
 20.1855 -    var split = sawReadOnlySpans &&
 20.1856 -      removeReadOnlyRanges(cm.view.doc, from, to);
 20.1857 -    if (split) {
 20.1858 -      for (var i = split.length - 1; i >= 1; --i)
 20.1859 -        updateDocInner(cm, split[i].from, split[i].to, [""], origin);
 20.1860 -      if (split.length)
 20.1861 -        return updateDocInner(cm, split[0].from, split[0].to, newText, selUpdate, origin);
 20.1862 -    } else {
 20.1863 -      return updateDocInner(cm, from, to, newText, selUpdate, origin);
 20.1864 -    }
 20.1865 -  }
 20.1866 -
 20.1867 -  function updateDocInner(cm, from, to, newText, selUpdate, origin) {
 20.1868 -    if (cm.view.suppressEdits) return;
 20.1869 -
 20.1870 -    var view = cm.view, doc = view.doc, old = [];
 20.1871 -    doc.iter(from.line, to.line + 1, function(line) {
 20.1872 -      old.push(newHL(line.text, line.markedSpans));
 20.1873 -    });
 20.1874 -    var startSelFrom = view.sel.from, startSelTo = view.sel.to;
 20.1875 -    var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText);
 20.1876 -    var retval = updateDocNoUndo(cm, from, to, lines, selUpdate, origin);
 20.1877 -    if (view.history) addChange(cm, from.line, newText.length, old, origin,
 20.1878 -                                startSelFrom, startSelTo, view.sel.from, view.sel.to);
 20.1879 -    return retval;
 20.1880 -  }
 20.1881 -
 20.1882 -  function unredoHelper(cm, type) {
 20.1883 -    var doc = cm.view.doc, hist = cm.view.history;
 20.1884 -    var set = (type == "undo" ? hist.done : hist.undone).pop();
 20.1885 -    if (!set) return;
 20.1886 -    var anti = {events: [], fromBefore: set.fromAfter, toBefore: set.toAfter,
 20.1887 -                fromAfter: set.fromBefore, toAfter: set.toBefore};
 20.1888 -    for (var i = set.events.length - 1; i >= 0; i -= 1) {
 20.1889 -      hist.dirtyCounter += type == "undo" ? -1 : 1;
 20.1890 -      var change = set.events[i];
 20.1891 -      var replaced = [], end = change.start + change.added;
 20.1892 -      doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); });
 20.1893 -      anti.events.push({start: change.start, added: change.old.length, old: replaced});
 20.1894 -      var selPos = i ? null : {from: set.fromBefore, to: set.toBefore};
 20.1895 -      updateDocNoUndo(cm, {line: change.start, ch: 0}, {line: end - 1, ch: getLine(doc, end-1).text.length},
 20.1896 -                      change.old, selPos, type);
 20.1897 -    }
 20.1898 -    (type == "undo" ? hist.undone : hist.done).push(anti);
 20.1899 -  }
 20.1900 -
 20.1901 -  function updateDocNoUndo(cm, from, to, lines, selUpdate, origin) {
 20.1902 -    var view = cm.view, doc = view.doc, display = cm.display;
 20.1903 -    if (view.suppressEdits) return;
 20.1904 -
 20.1905 -    var nlines = to.line - from.line, firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
 20.1906 -    var recomputeMaxLength = false, checkWidthStart = from.line;
 20.1907 -    if (!cm.options.lineWrapping) {
 20.1908 -      checkWidthStart = lineNo(visualLine(doc, firstLine));
 20.1909 -      doc.iter(checkWidthStart, to.line + 1, function(line) {
 20.1910 -        if (lineLength(doc, line) == view.maxLineLength) {
 20.1911 -          recomputeMaxLength = true;
 20.1912 -          return true;
 20.1913 -        }
 20.1914 -      });
 20.1915 -    }
 20.1916 -
 20.1917 -    var lastHL = lst(lines), th = textHeight(display);
 20.1918 -
 20.1919 -    // First adjust the line structure
 20.1920 -    if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") {
 20.1921 -      // This is a whole-line replace. Treated specially to make
 20.1922 -      // sure line objects move the way they are supposed to.
 20.1923 -      var added = [];
 20.1924 -      for (var i = 0, e = lines.length - 1; i < e; ++i)
 20.1925 -        added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
 20.1926 -      updateLine(cm, lastLine, lastLine.text, hlSpans(lastHL));
 20.1927 -      if (nlines) doc.remove(from.line, nlines, cm);
 20.1928 -      if (added.length) doc.insert(from.line, added);
 20.1929 -    } else if (firstLine == lastLine) {
 20.1930 -      if (lines.length == 1) {
 20.1931 -        updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
 20.1932 -                   firstLine.text.slice(to.ch), hlSpans(lines[0]));
 20.1933 -      } else {
 20.1934 -        for (var added = [], i = 1, e = lines.length - 1; i < e; ++i)
 20.1935 -          added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
 20.1936 -        added.push(makeLine(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL), th));
 20.1937 -        updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
 20.1938 -        doc.insert(from.line + 1, added);
 20.1939 -      }
 20.1940 -    } else if (lines.length == 1) {
 20.1941 -      updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) +
 20.1942 -                 lastLine.text.slice(to.ch), hlSpans(lines[0]));
 20.1943 -      doc.remove(from.line + 1, nlines, cm);
 20.1944 -    } else {
 20.1945 -      var added = [];
 20.1946 -      updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0]));
 20.1947 -      updateLine(cm, lastLine, hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL));
 20.1948 -      for (var i = 1, e = lines.length - 1; i < e; ++i)
 20.1949 -        added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th));
 20.1950 -      if (nlines > 1) doc.remove(from.line + 1, nlines - 1, cm);
 20.1951 -      doc.insert(from.line + 1, added);
 20.1952 -    }
 20.1953 -
 20.1954 -    if (cm.options.lineWrapping) {
 20.1955 -      var perLine = Math.max(5, display.scroller.clientWidth / charWidth(display) - 3);
 20.1956 -      doc.iter(from.line, from.line + lines.length, function(line) {
 20.1957 -        if (line.height == 0) return;
 20.1958 -        var guess = (Math.ceil(line.text.length / perLine) || 1) * th;
 20.1959 -        if (guess != line.height) updateLineHeight(line, guess);
 20.1960 -      });
 20.1961 -    } else {
 20.1962 -      doc.iter(checkWidthStart, from.line + lines.length, function(line) {
 20.1963 -        var len = lineLength(doc, line);
 20.1964 -        if (len > view.maxLineLength) {
 20.1965 -          view.maxLine = line;
 20.1966 -          view.maxLineLength = len;
 20.1967 -          view.maxLineChanged = true;
 20.1968 -          recomputeMaxLength = false;
 20.1969 -        }
 20.1970 -      });
 20.1971 -      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
 20.1972 -    }
 20.1973 -
 20.1974 -    // Adjust frontier, schedule worker
 20.1975 -    view.frontier = Math.min(view.frontier, from.line);
 20.1976 -    startWorker(cm, 400);
 20.1977 -
 20.1978 -    var lendiff = lines.length - nlines - 1;
 20.1979 -    // Remember that these lines changed, for updating the display
 20.1980 -    regChange(cm, from.line, to.line + 1, lendiff);
 20.1981 -    if (hasHandler(cm, "change")) {
 20.1982 -      // Normalize lines to contain only strings, since that's what
 20.1983 -      // the change event handler expects
 20.1984 -      for (var i = 0; i < lines.length; ++i)
 20.1985 -        if (typeof lines[i] != "string") lines[i] = lines[i].text;
 20.1986 -      var changeObj = {from: from, to: to, text: lines, origin: origin};
 20.1987 -      if (cm.curOp.textChanged) {
 20.1988 -        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
 20.1989 -        cur.next = changeObj;
 20.1990 -      } else cm.curOp.textChanged = changeObj;
 20.1991 -    }
 20.1992 -
 20.1993 -    // Update the selection
 20.1994 -    var newSelFrom, newSelTo, end = {line: from.line + lines.length - 1,
 20.1995 -                                     ch: hlText(lastHL).length  + (lines.length == 1 ? from.ch : 0)};
 20.1996 -    if (selUpdate && typeof selUpdate != "string") {
 20.1997 -      if (selUpdate.from) { newSelFrom = selUpdate.from; newSelTo = selUpdate.to; }
 20.1998 -      else newSelFrom = newSelTo = selUpdate;
 20.1999 -    } else if (selUpdate == "end") {
 20.2000 -      newSelFrom = newSelTo = end;
 20.2001 -    } else if (selUpdate == "start") {
 20.2002 -      newSelFrom = newSelTo = from;
 20.2003 -    } else if (selUpdate == "around") {
 20.2004 -      newSelFrom = from; newSelTo = end;
 20.2005 -    } else {
 20.2006 -      var adjustPos = function(pos) {
 20.2007 -        if (posLess(pos, from)) return pos;
 20.2008 -        if (!posLess(to, pos)) return end;
 20.2009 -        var line = pos.line + lendiff;
 20.2010 -        var ch = pos.ch;
 20.2011 -        if (pos.line == to.line)
 20.2012 -          ch += hlText(lastHL).length - (to.ch - (to.line == from.line ? from.ch : 0));
 20.2013 -        return {line: line, ch: ch};
 20.2014 -      };
 20.2015 -      newSelFrom = adjustPos(view.sel.from);
 20.2016 -      newSelTo = adjustPos(view.sel.to);
 20.2017 -    }
 20.2018 -    setSelection(cm, newSelFrom, newSelTo, null, true);
 20.2019 -    return end;
 20.2020 -  }
 20.2021 -
 20.2022 -  function replaceRange(cm, code, from, to, origin) {
 20.2023 -    if (!to) to = from;
 20.2024 -    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
 20.2025 -    return updateDoc(cm, from, to, splitLines(code), null, origin);
 20.2026 -  }
 20.2027 -
 20.2028 -  // SELECTION
 20.2029 -
 20.2030 -  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
 20.2031 -  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
 20.2032 -  function copyPos(x) {return {line: x.line, ch: x.ch};}
 20.2033 -
 20.2034 -  function clipLine(doc, n) {return Math.max(0, Math.min(n, doc.size-1));}
 20.2035 -  function clipPos(doc, pos) {
 20.2036 -    if (pos.line < 0) return {line: 0, ch: 0};
 20.2037 -    if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc, doc.size-1).text.length};
 20.2038 -    var ch = pos.ch, linelen = getLine(doc, pos.line).text.length;
 20.2039 -    if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};
 20.2040 -    else if (ch < 0) return {line: pos.line, ch: 0};
 20.2041 -    else return pos;
 20.2042 -  }
 20.2043 -  function isLine(doc, l) {return l >= 0 && l < doc.size;}
 20.2044 -
 20.2045 -  // If shift is held, this will move the selection anchor. Otherwise,
 20.2046 -  // it'll set the whole selection.
 20.2047 -  function extendSelection(cm, pos, other, bias) {
 20.2048 -    var sel = cm.view.sel;
 20.2049 -    if (sel.shift || sel.extend) {
 20.2050 -      var anchor = sel.anchor;
 20.2051 -      if (other) {
 20.2052 -        var posBefore = posLess(pos, anchor);
 20.2053 -        if (posBefore != posLess(other, anchor)) {
 20.2054 -          anchor = pos;
 20.2055 -          pos = other;
 20.2056 -        } else if (posBefore != posLess(pos, other)) {
 20.2057 -          pos = other;
 20.2058 -        }
 20.2059 -      }
 20.2060 -      setSelection(cm, anchor, pos, bias);
 20.2061 -    } else {
 20.2062 -      setSelection(cm, pos, other || pos, bias);
 20.2063 -    }
 20.2064 -    cm.curOp.userSelChange = true;
 20.2065 -  }
 20.2066 -
 20.2067 -  // Update the selection. Last two args are only used by
 20.2068 -  // updateDoc, since they have to be expressed in the line
 20.2069 -  // numbers before the update.
 20.2070 -  function setSelection(cm, anchor, head, bias, checkAtomic) {
 20.2071 -    cm.view.goalColumn = null;
 20.2072 -    var sel = cm.view.sel;
 20.2073 -    // Skip over atomic spans.
 20.2074 -    if (checkAtomic || !posEq(anchor, sel.anchor))
 20.2075 -      anchor = skipAtomic(cm, anchor, bias, checkAtomic != "push");
 20.2076 -    if (checkAtomic || !posEq(head, sel.head))
 20.2077 -      head = skipAtomic(cm, head, bias, checkAtomic != "push");
 20.2078 -
 20.2079 -    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
 20.2080 -
 20.2081 -    sel.anchor = anchor; sel.head = head;
 20.2082 -    var inv = posLess(head, anchor);
 20.2083 -    sel.from = inv ? head : anchor;
 20.2084 -    sel.to = inv ? anchor : head;
 20.2085 -
 20.2086 -    cm.curOp.updateInput = true;
 20.2087 -    cm.curOp.selectionChanged = true;
 20.2088 -  }
 20.2089 -
 20.2090 -  function reCheckSelection(cm) {
 20.2091 -    setSelection(cm, cm.view.sel.from, cm.view.sel.to, null, "push");
 20.2092 -  }
 20.2093 -
 20.2094 -  function skipAtomic(cm, pos, bias, mayClear) {
 20.2095 -    var doc = cm.view.doc, flipped = false, curPos = pos;
 20.2096 -    var dir = bias || 1;
 20.2097 -    cm.view.cantEdit = false;
 20.2098 -    search: for (;;) {
 20.2099 -      var line = getLine(doc, curPos.line), toClear;
 20.2100 -      if (line.markedSpans) {
 20.2101 -        for (var i = 0; i < line.markedSpans.length; ++i) {
 20.2102 -          var sp = line.markedSpans[i], m = sp.marker;
 20.2103 -          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
 20.2104 -              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
 20.2105 -            if (mayClear && m.clearOnEnter) {
 20.2106 -              (toClear || (toClear = [])).push(m);
 20.2107 -              continue;
 20.2108 -            } else if (!m.atomic) continue;
 20.2109 -            var newPos = m.find()[dir < 0 ? "from" : "to"];
 20.2110 -            if (posEq(newPos, curPos)) {
 20.2111 -              newPos.ch += dir;
 20.2112 -              if (newPos.ch < 0) {
 20.2113 -                if (newPos.line) newPos = clipPos(doc, {line: newPos.line - 1});
 20.2114 -                else newPos = null;
 20.2115 -              } else if (newPos.ch > line.text.length) {
 20.2116 -                if (newPos.line < doc.size - 1) newPos = {line: newPos.line + 1, ch: 0};
 20.2117 -                else newPos = null;
 20.2118 -              }
 20.2119 -              if (!newPos) {
 20.2120 -                if (flipped) {
 20.2121 -                  // Driven in a corner -- no valid cursor position found at all
 20.2122 -                  // -- try again *with* clearing, if we didn't already
 20.2123 -                  if (!mayClear) return skipAtomic(cm, pos, bias, true);
 20.2124 -                  // Otherwise, turn off editing until further notice, and return the start of the doc
 20.2125 -                  cm.view.cantEdit = true;
 20.2126 -                  return {line: 0, ch: 0};
 20.2127 -                }
 20.2128 -                flipped = true; newPos = pos; dir = -dir;
 20.2129 -              }
 20.2130 -            }
 20.2131 -            curPos = newPos;
 20.2132 -            continue search;
 20.2133 -          }
 20.2134 -        }
 20.2135 -        if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear();
 20.2136 -      }
 20.2137 -      return curPos;
 20.2138 -    }
 20.2139 -  }
 20.2140 -
 20.2141 -  // SCROLLING
 20.2142 -
 20.2143 -  function scrollCursorIntoView(cm) {
 20.2144 -    var view = cm.view;
 20.2145 -    var coords = scrollPosIntoView(cm, view.sel.head);
 20.2146 -    if (!view.focused) return;
 20.2147 -    var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
 20.2148 -    if (coords.top + box.top < 0) doScroll = true;
 20.2149 -    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
 20.2150 -    if (doScroll != null && !phantom) {
 20.2151 -      var hidden = display.cursor.style.display == "none";
 20.2152 -      if (hidden) {
 20.2153 -        display.cursor.style.display = "";
 20.2154 -        display.cursor.style.left = coords.left + "px";
 20.2155 -        display.cursor.style.top = (coords.top - display.viewOffset) + "px";
 20.2156 -      }
 20.2157 -      display.cursor.scrollIntoView(doScroll);
 20.2158 -      if (hidden) display.cursor.style.display = "none";
 20.2159 -    }
 20.2160 -  }
 20.2161 -
 20.2162 -  function scrollPosIntoView(cm, pos) {
 20.2163 -    for (;;) {
 20.2164 -      var changed = false, coords = cursorCoords(cm, pos);
 20.2165 -      var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
 20.2166 -      var startTop = cm.view.scrollTop, startLeft = cm.view.scrollLeft;
 20.2167 -      if (scrollPos.scrollTop != null) {
 20.2168 -        setScrollTop(cm, scrollPos.scrollTop);
 20.2169 -        if (Math.abs(cm.view.scrollTop - startTop) > 1) changed = true;
 20.2170 -      }
 20.2171 -      if (scrollPos.scrollLeft != null) {
 20.2172 -        setScrollLeft(cm, scrollPos.scrollLeft);
 20.2173 -        if (Math.abs(cm.view.scrollLeft - startLeft) > 1) changed = true;
 20.2174 -      }
 20.2175 -      if (!changed) return coords;
 20.2176 -    }
 20.2177 -  }
 20.2178 -
 20.2179 -  function scrollIntoView(cm, x1, y1, x2, y2) {
 20.2180 -    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
 20.2181 -    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
 20.2182 -    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
 20.2183 -  }
 20.2184 -
 20.2185 -  function calculateScrollPos(cm, x1, y1, x2, y2) {
 20.2186 -    var display = cm.display, pt = paddingTop(display);
 20.2187 -    y1 += pt; y2 += pt;
 20.2188 -    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
 20.2189 -    var docBottom = cm.view.doc.height + 2 * pt;
 20.2190 -    var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
 20.2191 -    if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
 20.2192 -    else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
 20.2193 -
 20.2194 -    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
 20.2195 -    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
 20.2196 -    var gutterw = display.gutters.offsetWidth;
 20.2197 -    var atLeft = x1 < gutterw + 10;
 20.2198 -    if (x1 < screenleft + gutterw || atLeft) {
 20.2199 -      if (atLeft) x1 = 0;
 20.2200 -      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
 20.2201 -    } else if (x2 > screenw + screenleft - 3) {
 20.2202 -      result.scrollLeft = x2 + 10 - screenw;
 20.2203 -    }
 20.2204 -    return result;
 20.2205 -  }
 20.2206 -
 20.2207 -  // API UTILITIES
 20.2208 -
 20.2209 -  function indentLine(cm, n, how, aggressive) {
 20.2210 -    var doc = cm.view.doc;
 20.2211 -    if (!how) how = "add";
 20.2212 -    if (how == "smart") {
 20.2213 -      if (!cm.view.mode.indent) how = "prev";
 20.2214 -      else var state = getStateBefore(cm, n);
 20.2215 -    }
 20.2216 -
 20.2217 -    var tabSize = cm.options.tabSize;
 20.2218 -    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
 20.2219 -    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
 20.2220 -    if (how == "smart") {
 20.2221 -      indentation = cm.view.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
 20.2222 -      if (indentation == Pass) {
 20.2223 -        if (!aggressive) return;
 20.2224 -        how = "prev";
 20.2225 -      }
 20.2226 -    }
 20.2227 -    if (how == "prev") {
 20.2228 -      if (n) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
 20.2229 -      else indentation = 0;
 20.2230 -    }
 20.2231 -    else if (how == "add") indentation = curSpace + cm.options.indentUnit;
 20.2232 -    else if (how == "subtract") indentation = curSpace - cm.options.indentUnit;
 20.2233 -    indentation = Math.max(0, indentation);
 20.2234 -
 20.2235 -    var indentString = "", pos = 0;
 20.2236 -    if (cm.options.indentWithTabs)
 20.2237 -      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
 20.2238 -    if (pos < indentation) indentString += spaceStr(indentation - pos);
 20.2239 -
 20.2240 -    if (indentString != curSpaceString)
 20.2241 -      replaceRange(cm, indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}, "input");
 20.2242 -    line.stateAfter = null;
 20.2243 -  }
 20.2244 -
 20.2245 -  function changeLine(cm, handle, op) {
 20.2246 -    var no = handle, line = handle, doc = cm.view.doc;
 20.2247 -    if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
 20.2248 -    else no = lineNo(handle);
 20.2249 -    if (no == null) return null;
 20.2250 -    if (op(line, no)) regChange(cm, no, no + 1);
 20.2251 -    else return null;
 20.2252 -    return line;
 20.2253 -  }
 20.2254 -
 20.2255 -  function findPosH(cm, dir, unit, visually) {
 20.2256 -    var doc = cm.view.doc, end = cm.view.sel.head, line = end.line, ch = end.ch;
 20.2257 -    var lineObj = getLine(doc, line);
 20.2258 -    function findNextLine() {
 20.2259 -      var l = line + dir;
 20.2260 -      if (l < 0 || l == doc.size) return false;
 20.2261 -      line = l;
 20.2262 -      return lineObj = getLine(doc, l);
 20.2263 -    }
 20.2264 -    function moveOnce(boundToLine) {
 20.2265 -      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
 20.2266 -      if (next == null) {
 20.2267 -        if (!boundToLine && findNextLine()) {
 20.2268 -          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
 20.2269 -          else ch = dir < 0 ? lineObj.text.length : 0;
 20.2270 -        } else return false;
 20.2271 -      } else ch = next;
 20.2272 -      return true;
 20.2273 -    }
 20.2274 -    if (unit == "char") moveOnce();
 20.2275 -    else if (unit == "column") moveOnce(true);
 20.2276 -    else if (unit == "word") {
 20.2277 -      var sawWord = false;
 20.2278 -      for (;;) {
 20.2279 -        if (dir < 0) if (!moveOnce()) break;
 20.2280 -        if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
 20.2281 -        else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
 20.2282 -        if (dir > 0) if (!moveOnce()) break;
 20.2283 -      }
 20.2284 -    }
 20.2285 -    return skipAtomic(cm, {line: line, ch: ch}, dir, true);
 20.2286 -  }
 20.2287 -
 20.2288 -  function findWordAt(line, pos) {
 20.2289 -    var start = pos.ch, end = pos.ch;
 20.2290 -    if (line) {
 20.2291 -      if (pos.after === false || end == line.length) --start; else ++end;
 20.2292 -      var startChar = line.charAt(start);
 20.2293 -      var check = isWordChar(startChar) ? isWordChar :
 20.2294 -        /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
 20.2295 -      function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
 20.2296 -      while (start > 0 && check(line.charAt(start - 1))) --start;
 20.2297 -      while (end < line.length && check(line.charAt(end))) ++end;
 20.2298 -    }
 20.2299 -    return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
 20.2300 -  }
 20.2301 -
 20.2302 -  function selectLine(cm, line) {
 20.2303 -    extendSelection(cm, {line: line, ch: 0}, clipPos(cm.view.doc, {line: line + 1, ch: 0}));
 20.2304 -  }
 20.2305 -
 20.2306 -  // PROTOTYPE
 20.2307 -
 20.2308 -  // The publicly visible API. Note that operation(null, f) means
 20.2309 -  // 'wrap f in an operation, performed on its `this` parameter'
 20.2310 -
 20.2311 -  CodeMirror.prototype = {
 20.2312 -    getValue: function(lineSep) {
 20.2313 -      var text = [], doc = this.view.doc;
 20.2314 -      doc.iter(0, doc.size, function(line) { text.push(line.text); });
 20.2315 -      return text.join(lineSep || "\n");
 20.2316 -    },
 20.2317 -
 20.2318 -    setValue: operation(null, function(code) {
 20.2319 -      var doc = this.view.doc, top = {line: 0, ch: 0}, lastLen = getLine(doc, doc.size-1).text.length;
 20.2320 -      updateDocInner(this, top, {line: doc.size - 1, ch: lastLen}, splitLines(code), top, top, "setValue");
 20.2321 -    }),
 20.2322 -
 20.2323 -    getSelection: function(lineSep) { return this.getRange(this.view.sel.from, this.view.sel.to, lineSep); },
 20.2324 -
 20.2325 -    replaceSelection: operation(null, function(code, collapse, origin) {
 20.2326 -      var sel = this.view.sel;
 20.2327 -      updateDoc(this, sel.from, sel.to, splitLines(code), collapse || "around", origin);
 20.2328 -    }),
 20.2329 -
 20.2330 -    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
 20.2331 -
 20.2332 -    setOption: function(option, value) {
 20.2333 -      var options = this.options, old = options[option];
 20.2334 -      if (options[option] == value && option != "mode") return;
 20.2335 -      options[option] = value;
 20.2336 -      if (optionHandlers.hasOwnProperty(option))
 20.2337 -        operation(this, optionHandlers[option])(this, value, old);
 20.2338 -    },
 20.2339 -
 20.2340 -    getOption: function(option) {return this.options[option];},
 20.2341 -
 20.2342 -    getMode: function() {return this.view.mode;},
 20.2343 -
 20.2344 -    addKeyMap: function(map) {
 20.2345 -      this.view.keyMaps.push(map);
 20.2346 -    },
 20.2347 -
 20.2348 -    removeKeyMap: function(map) {
 20.2349 -      var maps = this.view.keyMaps;
 20.2350 -      for (var i = 0; i < maps.length; ++i)
 20.2351 -        if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
 20.2352 -          maps.splice(i, 1);
 20.2353 -          return true;
 20.2354 -        }
 20.2355 -    },
 20.2356 -
 20.2357 -    undo: operation(null, function() {unredoHelper(this, "undo");}),
 20.2358 -    redo: operation(null, function() {unredoHelper(this, "redo");}),
 20.2359 -
 20.2360 -    indentLine: operation(null, function(n, dir, aggressive) {
 20.2361 -      if (typeof dir != "string") {
 20.2362 -        if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
 20.2363 -        else dir = dir ? "add" : "subtract";
 20.2364 -      }
 20.2365 -      if (isLine(this.view.doc, n)) indentLine(this, n, dir, aggressive);
 20.2366 -    }),
 20.2367 -
 20.2368 -    indentSelection: operation(null, function(how) {
 20.2369 -      var sel = this.view.sel;
 20.2370 -      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
 20.2371 -      var e = sel.to.line - (sel.to.ch ? 0 : 1);
 20.2372 -      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
 20.2373 -    }),
 20.2374 -
 20.2375 -    historySize: function() {
 20.2376 -      var hist = this.view.history;
 20.2377 -      return {undo: hist.done.length, redo: hist.undone.length};
 20.2378 -    },
 20.2379 -
 20.2380 -    clearHistory: function() {this.view.history = makeHistory();},
 20.2381 -
 20.2382 -    markClean: function() {
 20.2383 -      this.view.history.dirtyCounter = 0;
 20.2384 -      this.view.history.lastOp = this.view.history.lastOrigin = null;
 20.2385 -    },
 20.2386 -
 20.2387 -    isClean: function () {return this.view.history.dirtyCounter == 0;},
 20.2388 -      
 20.2389 -    getHistory: function() {
 20.2390 -      var hist = this.view.history;
 20.2391 -      function cp(arr) {
 20.2392 -        for (var i = 0, nw = [], nwelt; i < arr.length; ++i) {
 20.2393 -          var set = arr[i];
 20.2394 -          nw.push({events: nwelt = [], fromBefore: set.fromBefore, toBefore: set.toBefore,
 20.2395 -                   fromAfter: set.fromAfter, toAfter: set.toAfter});
 20.2396 -          for (var j = 0, elt = set.events; j < elt.length; ++j) {
 20.2397 -            var old = [], cur = elt[j];
 20.2398 -            nwelt.push({start: cur.start, added: cur.added, old: old});
 20.2399 -            for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k]));
 20.2400 -          }
 20.2401 -        }
 20.2402 -        return nw;
 20.2403 -      }
 20.2404 -      return {done: cp(hist.done), undone: cp(hist.undone)};
 20.2405 -    },
 20.2406 -
 20.2407 -    setHistory: function(histData) {
 20.2408 -      var hist = this.view.history = makeHistory();
 20.2409 -      hist.done = histData.done;
 20.2410 -      hist.undone = histData.undone;
 20.2411 -    },
 20.2412 -
 20.2413 -    // Fetch the parser token for a given character. Useful for hacks
 20.2414 -    // that want to inspect the mode state (say, for completion).
 20.2415 -    getTokenAt: function(pos) {
 20.2416 -      var doc = this.view.doc;
 20.2417 -      pos = clipPos(doc, pos);
 20.2418 -      var state = getStateBefore(this, pos.line), mode = this.view.mode;
 20.2419 -      var line = getLine(doc, pos.line);
 20.2420 -      var stream = new StringStream(line.text, this.options.tabSize);
 20.2421 -      while (stream.pos < pos.ch && !stream.eol()) {
 20.2422 -        stream.start = stream.pos;
 20.2423 -        var style = mode.token(stream, state);
 20.2424 -      }
 20.2425 -      return {start: stream.start,
 20.2426 -              end: stream.pos,
 20.2427 -              string: stream.current(),
 20.2428 -              className: style || null, // Deprecated, use 'type' instead
 20.2429 -              type: style || null,
 20.2430 -              state: state};
 20.2431 -    },
 20.2432 -
 20.2433 -    getStateAfter: function(line) {
 20.2434 -      var doc = this.view.doc;
 20.2435 -      line = clipLine(doc, line == null ? doc.size - 1: line);
 20.2436 -      return getStateBefore(this, line + 1);
 20.2437 -    },
 20.2438 -
 20.2439 -    cursorCoords: function(start, mode) {
 20.2440 -      var pos, sel = this.view.sel;
 20.2441 -      if (start == null) pos = sel.head;
 20.2442 -      else if (typeof start == "object") pos = clipPos(this.view.doc, start);
 20.2443 -      else pos = start ? sel.from : sel.to;
 20.2444 -      return cursorCoords(this, pos, mode || "page");
 20.2445 -    },
 20.2446 -
 20.2447 -    charCoords: function(pos, mode) {
 20.2448 -      return charCoords(this, clipPos(this.view.doc, pos), mode || "page");
 20.2449 -    },
 20.2450 -
 20.2451 -    coordsChar: function(coords) {
 20.2452 -      var off = this.display.lineSpace.getBoundingClientRect();
 20.2453 -      return coordsChar(this, coords.left - off.left, coords.top - off.top);
 20.2454 -    },
 20.2455 -
 20.2456 -    defaultTextHeight: function() { return textHeight(this.display); },
 20.2457 -
 20.2458 -    markText: operation(null, function(from, to, options) {
 20.2459 -      return markText(this, clipPos(this.view.doc, from), clipPos(this.view.doc, to),
 20.2460 -                      options, "range");
 20.2461 -    }),
 20.2462 -
 20.2463 -    setBookmark: operation(null, function(pos, widget) {
 20.2464 -      pos = clipPos(this.view.doc, pos);
 20.2465 -      return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark");
 20.2466 -    }),
 20.2467 -
 20.2468 -    findMarksAt: function(pos) {
 20.2469 -      var doc = this.view.doc;
 20.2470 -      pos = clipPos(doc, pos);
 20.2471 -      var markers = [], spans = getLine(doc, pos.line).markedSpans;
 20.2472 -      if (spans) for (var i = 0; i < spans.length; ++i) {
 20.2473 -        var span = spans[i];
 20.2474 -        if ((span.from == null || span.from <= pos.ch) &&
 20.2475 -            (span.to == null || span.to >= pos.ch))
 20.2476 -          markers.push(span.marker);
 20.2477 -      }
 20.2478 -      return markers;
 20.2479 -    },
 20.2480 -
 20.2481 -    setGutterMarker: operation(null, function(line, gutterID, value) {
 20.2482 -      return changeLine(this, line, function(line) {
 20.2483 -        var markers = line.gutterMarkers || (line.gutterMarkers = {});
 20.2484 -        markers[gutterID] = value;
 20.2485 -        if (!value && isEmpty(markers)) line.gutterMarkers = null;
 20.2486 -        return true;
 20.2487 -      });
 20.2488 -    }),
 20.2489 -
 20.2490 -    clearGutter: operation(null, function(gutterID) {
 20.2491 -      var i = 0, cm = this, doc = cm.view.doc;
 20.2492 -      doc.iter(0, doc.size, function(line) {
 20.2493 -        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
 20.2494 -          line.gutterMarkers[gutterID] = null;
 20.2495 -          regChange(cm, i, i + 1);
 20.2496 -          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
 20.2497 -        }
 20.2498 -        ++i;
 20.2499 -      });
 20.2500 -    }),
 20.2501 -
 20.2502 -    addLineClass: operation(null, function(handle, where, cls) {
 20.2503 -      return changeLine(this, handle, function(line) {
 20.2504 -        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
 20.2505 -        if (!line[prop]) line[prop] = cls;
 20.2506 -        else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false;
 20.2507 -        else line[prop] += " " + cls;
 20.2508 -        return true;
 20.2509 -      });
 20.2510 -    }),
 20.2511 -
 20.2512 -    removeLineClass: operation(null, function(handle, where, cls) {
 20.2513 -      return changeLine(this, handle, function(line) {
 20.2514 -        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
 20.2515 -        var cur = line[prop];
 20.2516 -        if (!cur) return false;
 20.2517 -        else if (cls == null) line[prop] = null;
 20.2518 -        else {
 20.2519 -          var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
 20.2520 -          if (upd == cur) return false;
 20.2521 -          line[prop] = upd || null;
 20.2522 -        }
 20.2523 -        return true;
 20.2524 -      });
 20.2525 -    }),
 20.2526 -
 20.2527 -    addLineWidget: operation(null, function(handle, node, options) {
 20.2528 -      var widget = options || {};
 20.2529 -      widget.node = node;
 20.2530 -      if (widget.noHScroll) this.display.alignWidgets = true;
 20.2531 -      changeLine(this, handle, function(line) {
 20.2532 -        (line.widgets || (line.widgets = [])).push(widget);
 20.2533 -        widget.line = line;
 20.2534 -        return true;
 20.2535 -      });
 20.2536 -      return widget;
 20.2537 -    }),
 20.2538 -
 20.2539 -    removeLineWidget: operation(null, function(widget) {
 20.2540 -      var ws = widget.line.widgets, no = lineNo(widget.line);
 20.2541 -      if (no == null) return;
 20.2542 -      for (var i = 0; i < ws.length; ++i) if (ws[i] == widget) ws.splice(i--, 1);
 20.2543 -      regChange(this, no, no + 1);
 20.2544 -    }),
 20.2545 -
 20.2546 -    lineInfo: function(line) {
 20.2547 -      if (typeof line == "number") {
 20.2548 -        if (!isLine(this.view.doc, line)) return null;
 20.2549 -        var n = line;
 20.2550 -        line = getLine(this.view.doc, line);
 20.2551 -        if (!line) return null;
 20.2552 -      } else {
 20.2553 -        var n = lineNo(line);
 20.2554 -        if (n == null) return null;
 20.2555 -      }
 20.2556 -      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
 20.2557 -              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
 20.2558 -              widgets: line.widgets};
 20.2559 -    },
 20.2560 -
 20.2561 -    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
 20.2562 -
 20.2563 -    addWidget: function(pos, node, scroll, vert, horiz) {
 20.2564 -      var display = this.display;
 20.2565 -      pos = cursorCoords(this, clipPos(this.view.doc, pos));
 20.2566 -      var top = pos.top, left = pos.left;
 20.2567 -      node.style.position = "absolute";
 20.2568 -      display.sizer.appendChild(node);
 20.2569 -      if (vert == "over") top = pos.top;
 20.2570 -      else if (vert == "near") {
 20.2571 -        var vspace = Math.max(display.wrapper.clientHeight, this.view.doc.height),
 20.2572 -        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
 20.2573 -        if (pos.bottom + node.offsetHeight > vspace && pos.top > node.offsetHeight)
 20.2574 -          top = pos.top - node.offsetHeight;
 20.2575 -        if (left + node.offsetWidth > hspace)
 20.2576 -          left = hspace - node.offsetWidth;
 20.2577 -      }
 20.2578 -      node.style.top = (top + paddingTop(display)) + "px";
 20.2579 -      node.style.left = node.style.right = "";
 20.2580 -      if (horiz == "right") {
 20.2581 -        left = display.sizer.clientWidth - node.offsetWidth;
 20.2582 -        node.style.right = "0px";
 20.2583 -      } else {
 20.2584 -        if (horiz == "left") left = 0;
 20.2585 -        else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
 20.2586 -        node.style.left = left + "px";
 20.2587 -      }
 20.2588 -      if (scroll)
 20.2589 -        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
 20.2590 -    },
 20.2591 -
 20.2592 -    lineCount: function() {return this.view.doc.size;},
 20.2593 -
 20.2594 -    clipPos: function(pos) {return clipPos(this.view.doc, pos);},
 20.2595 -
 20.2596 -    getCursor: function(start) {
 20.2597 -      var sel = this.view.sel, pos;
 20.2598 -      if (start == null || start == "head") pos = sel.head;
 20.2599 -      else if (start == "anchor") pos = sel.anchor;
 20.2600 -      else if (start == "end" || start === false) pos = sel.to;
 20.2601 -      else pos = sel.from;
 20.2602 -      return copyPos(pos);
 20.2603 -    },
 20.2604 -
 20.2605 -    somethingSelected: function() {return !posEq(this.view.sel.from, this.view.sel.to);},
 20.2606 -
 20.2607 -    setCursor: operation(null, function(line, ch, extend) {
 20.2608 -      var pos = clipPos(this.view.doc, typeof line == "number" ? {line: line, ch: ch || 0} : line);
 20.2609 -      if (extend) extendSelection(this, pos);
 20.2610 -      else setSelection(this, pos, pos);
 20.2611 -    }),
 20.2612 -
 20.2613 -    setSelection: operation(null, function(anchor, head) {
 20.2614 -      var doc = this.view.doc;
 20.2615 -      setSelection(this, clipPos(doc, anchor), clipPos(doc, head || anchor));
 20.2616 -    }),
 20.2617 -
 20.2618 -    extendSelection: operation(null, function(from, to) {
 20.2619 -      var doc = this.view.doc;
 20.2620 -      extendSelection(this, clipPos(doc, from), to && clipPos(doc, to));
 20.2621 -    }),
 20.2622 -
 20.2623 -    setExtending: function(val) {this.view.sel.extend = val;},
 20.2624 -
 20.2625 -    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
 20.2626 -
 20.2627 -    getLineHandle: function(line) {
 20.2628 -      var doc = this.view.doc;
 20.2629 -      if (isLine(doc, line)) return getLine(doc, line);
 20.2630 -    },
 20.2631 -
 20.2632 -    getLineNumber: function(line) {return lineNo(line);},
 20.2633 -
 20.2634 -    setLine: operation(null, function(line, text) {
 20.2635 -      if (isLine(this.view.doc, line))
 20.2636 -        replaceRange(this, text, {line: line, ch: 0}, {line: line, ch: getLine(this.view.doc, line).text.length});
 20.2637 -    }),
 20.2638 -
 20.2639 -    removeLine: operation(null, function(line) {
 20.2640 -      if (isLine(this.view.doc, line))
 20.2641 -        replaceRange(this, "", {line: line, ch: 0}, clipPos(this.view.doc, {line: line+1, ch: 0}));
 20.2642 -    }),
 20.2643 -
 20.2644 -    replaceRange: operation(null, function(code, from, to) {
 20.2645 -      var doc = this.view.doc;
 20.2646 -      from = clipPos(doc, from);
 20.2647 -      to = to ? clipPos(doc, to) : from;
 20.2648 -      return replaceRange(this, code, from, to);
 20.2649 -    }),
 20.2650 -
 20.2651 -    getRange: function(from, to, lineSep) {
 20.2652 -      var doc = this.view.doc;
 20.2653 -      from = clipPos(doc, from); to = clipPos(doc, to);
 20.2654 -      var l1 = from.line, l2 = to.line;
 20.2655 -      if (l1 == l2) return getLine(doc, l1).text.slice(from.ch, to.ch);
 20.2656 -      var code = [getLine(doc, l1).text.slice(from.ch)];
 20.2657 -      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
 20.2658 -      code.push(getLine(doc, l2).text.slice(0, to.ch));
 20.2659 -      return code.join(lineSep || "\n");
 20.2660 -    },
 20.2661 -
 20.2662 -    triggerOnKeyDown: operation(null, onKeyDown),
 20.2663 -
 20.2664 -    execCommand: function(cmd) {return commands[cmd](this);},
 20.2665 -
 20.2666 -    // Stuff used by commands, probably not much use to outside code.
 20.2667 -    moveH: operation(null, function(dir, unit) {
 20.2668 -      var sel = this.view.sel, pos = dir < 0 ? sel.from : sel.to;
 20.2669 -      if (sel.shift || sel.extend || posEq(sel.from, sel.to)) pos = findPosH(this, dir, unit, true);
 20.2670 -      extendSelection(this, pos, pos, dir);
 20.2671 -    }),
 20.2672 -
 20.2673 -    deleteH: operation(null, function(dir, unit) {
 20.2674 -      var sel = this.view.sel;
 20.2675 -      if (!posEq(sel.from, sel.to)) replaceRange(this, "", sel.from, sel.to, "delete");
 20.2676 -      else replaceRange(this, "", sel.from, findPosH(this, dir, unit, false), "delete");
 20.2677 -      this.curOp.userSelChange = true;
 20.2678 -    }),
 20.2679 -
 20.2680 -    moveV: operation(null, function(dir, unit) {
 20.2681 -      var view = this.view, doc = view.doc, display = this.display;
 20.2682 -      var cur = view.sel.head, pos = cursorCoords(this, cur, "div");
 20.2683 -      var x = pos.left, y;
 20.2684 -      if (view.goalColumn != null) x = view.goalColumn;
 20.2685 -      if (unit == "page") {
 20.2686 -        var pageSize = Math.min(display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
 20.2687 -        y = pos.top + dir * pageSize;
 20.2688 -      } else if (unit == "line") {
 20.2689 -        y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
 20.2690 -      }
 20.2691 -      do {
 20.2692 -        var target = coordsChar(this, x, y);
 20.2693 -        y += dir * 5;
 20.2694 -      } while (target.outside && (dir < 0 ? y > 0 : y < doc.height));
 20.2695 -
 20.2696 -      if (unit == "page") display.scrollbarV.scrollTop += charCoords(this, target, "div").top - pos.top;
 20.2697 -      extendSelection(this, target, target, dir);
 20.2698 -      view.goalColumn = x;
 20.2699 -    }),
 20.2700 -
 20.2701 -    toggleOverwrite: function() {
 20.2702 -      if (this.view.overwrite = !this.view.overwrite)
 20.2703 -        this.display.cursor.className += " CodeMirror-overwrite";
 20.2704 -      else
 20.2705 -        this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
 20.2706 -    },
 20.2707 -
 20.2708 -    posFromIndex: function(off) {
 20.2709 -      var lineNo = 0, ch, doc = this.view.doc;
 20.2710 -      doc.iter(0, doc.size, function(line) {
 20.2711 -        var sz = line.text.length + 1;
 20.2712 -        if (sz > off) { ch = off; return true; }
 20.2713 -        off -= sz;
 20.2714 -        ++lineNo;
 20.2715 -      });
 20.2716 -      return clipPos(doc, {line: lineNo, ch: ch});
 20.2717 -    },
 20.2718 -    indexFromPos: function (coords) {
 20.2719 -      if (coords.line < 0 || coords.ch < 0) return 0;
 20.2720 -      var index = coords.ch;
 20.2721 -      this.view.doc.iter(0, coords.line, function (line) {
 20.2722 -        index += line.text.length + 1;
 20.2723 -      });
 20.2724 -      return index;
 20.2725 -    },
 20.2726 -
 20.2727 -    scrollTo: function(x, y) {
 20.2728 -      if (x != null) this.display.scrollbarH.scrollLeft = this.display.scroller.scrollLeft = x;
 20.2729 -      if (y != null) this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = y;
 20.2730 -      updateDisplay(this, []);
 20.2731 -    },
 20.2732 -    getScrollInfo: function() {
 20.2733 -      var scroller = this.display.scroller, co = scrollerCutOff;
 20.2734 -      return {left: scroller.scrollLeft, top: scroller.scrollTop,
 20.2735 -              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
 20.2736 -              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
 20.2737 -    },
 20.2738 -
 20.2739 -    scrollIntoView: function(pos) {
 20.2740 -      if (typeof pos == "number") pos = {line: pos, ch: 0};
 20.2741 -      pos = pos ? clipPos(this.view.doc, pos) : this.view.sel.head;
 20.2742 -      scrollPosIntoView(this, pos);
 20.2743 -    },
 20.2744 -
 20.2745 -    setSize: function(width, height) {
 20.2746 -      function interpret(val) {
 20.2747 -        return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
 20.2748 -      }
 20.2749 -      if (width != null) this.display.wrapper.style.width = interpret(width);
 20.2750 -      if (height != null) this.display.wrapper.style.height = interpret(height);
 20.2751 -      this.refresh();
 20.2752 -    },
 20.2753 -
 20.2754 -    on: function(type, f) {on(this, type, f);},
 20.2755 -    off: function(type, f) {off(this, type, f);},
 20.2756 -
 20.2757 -    operation: function(f){return operation(this, f)();},
 20.2758 -
 20.2759 -    refresh: function() {
 20.2760 -      clearCaches(this);
 20.2761 -      if (this.display.scroller.scrollHeight > this.view.scrollTop)
 20.2762 -        this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = this.view.scrollTop;
 20.2763 -      updateDisplay(this, true);
 20.2764 -    },
 20.2765 -
 20.2766 -    getInputField: function(){return this.display.input;},
 20.2767 -    getWrapperElement: function(){return this.display.wrapper;},
 20.2768 -    getScrollerElement: function(){return this.display.scroller;},
 20.2769 -    getGutterElement: function(){return this.display.gutters;}
 20.2770 -  };
 20.2771 -
 20.2772 -  // OPTION DEFAULTS
 20.2773 -
 20.2774 -  var optionHandlers = CodeMirror.optionHandlers = {};
 20.2775 -
 20.2776 -  // The default configuration options.
 20.2777 -  var defaults = CodeMirror.defaults = {};
 20.2778 -
 20.2779 -  function option(name, deflt, handle, notOnInit) {
 20.2780 -    CodeMirror.defaults[name] = deflt;
 20.2781 -    if (handle) optionHandlers[name] =
 20.2782 -      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
 20.2783 -  }
 20.2784 -
 20.2785 -  var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
 20.2786 -
 20.2787 -  // These two are, on init, called from the constructor because they
 20.2788 -  // have to be initialized before the editor can start at all.
 20.2789 -  option("value", "", function(cm, val) {cm.setValue(val);}, true);
 20.2790 -  option("mode", null, loadMode, true);
 20.2791 -
 20.2792 -  option("indentUnit", 2, loadMode, true);
 20.2793 -  option("indentWithTabs", false);
 20.2794 -  option("smartIndent", true);
 20.2795 -  option("tabSize", 4, function(cm) {
 20.2796 -    loadMode(cm);
 20.2797 -    clearCaches(cm);
 20.2798 -    updateDisplay(cm, true);
 20.2799 -  }, true);
 20.2800 -  option("electricChars", true);
 20.2801 -
 20.2802 -  option("theme", "default", function(cm) {
 20.2803 -    themeChanged(cm);
 20.2804 -    guttersChanged(cm);
 20.2805 -  }, true);
 20.2806 -  option("keyMap", "default", keyMapChanged);
 20.2807 -  option("extraKeys", null);
 20.2808 -
 20.2809 -  option("onKeyEvent", null);
 20.2810 -  option("onDragEvent", null);
 20.2811 -
 20.2812 -  option("lineWrapping", false, wrappingChanged, true);
 20.2813 -  option("gutters", [], function(cm) {
 20.2814 -    setGuttersForLineNumbers(cm.options);
 20.2815 -    guttersChanged(cm);
 20.2816 -  }, true);
 20.2817 -  option("lineNumbers", false, function(cm) {
 20.2818 -    setGuttersForLineNumbers(cm.options);
 20.2819 -    guttersChanged(cm);
 20.2820 -  }, true);
 20.2821 -  option("firstLineNumber", 1, guttersChanged, true);
 20.2822 -  option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
 20.2823 -  option("showCursorWhenSelecting", false, updateSelection, true);
 20.2824 -  
 20.2825 -  option("readOnly", false, function(cm, val) {
 20.2826 -    if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
 20.2827 -    else if (!val) resetInput(cm, true);
 20.2828 -  });
 20.2829 -  option("dragDrop", true);
 20.2830 -
 20.2831 -  option("cursorBlinkRate", 530);
 20.2832 -  option("cursorHeight", 1);
 20.2833 -  option("workTime", 100);
 20.2834 -  option("workDelay", 100);
 20.2835 -  option("flattenSpans", true);
 20.2836 -  option("pollInterval", 100);
 20.2837 -  option("undoDepth", 40);
 20.2838 -  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
 20.2839 -
 20.2840 -  option("tabindex", null, function(cm, val) {
 20.2841 -    cm.display.input.tabIndex = val || "";
 20.2842 -  });
 20.2843 -  option("autofocus", null);
 20.2844 -
 20.2845 -  // MODE DEFINITION AND QUERYING
 20.2846 -
 20.2847 -  // Known modes, by name and by MIME
 20.2848 -  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
 20.2849 -
 20.2850 -  CodeMirror.defineMode = function(name, mode) {
 20.2851 -    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
 20.2852 -    if (arguments.length > 2) {
 20.2853 -      mode.dependencies = [];
 20.2854 -      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
 20.2855 -    }
 20.2856 -    modes[name] = mode;
 20.2857 -  };
 20.2858 -
 20.2859 -  CodeMirror.defineMIME = function(mime, spec) {
 20.2860 -    mimeModes[mime] = spec;
 20.2861 -  };
 20.2862 -
 20.2863 -  CodeMirror.resolveMode = function(spec) {
 20.2864 -    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
 20.2865 -      spec = mimeModes[spec];
 20.2866 -    else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
 20.2867 -      return CodeMirror.resolveMode("application/xml");
 20.2868 -    if (typeof spec == "string") return {name: spec};
 20.2869 -    else return spec || {name: "null"};
 20.2870 -  };
 20.2871 -
 20.2872 -  CodeMirror.getMode = function(options, spec) {
 20.2873 -    var spec = CodeMirror.resolveMode(spec);
 20.2874 -    var mfactory = modes[spec.name];
 20.2875 -    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
 20.2876 -    var modeObj = mfactory(options, spec);
 20.2877 -    if (modeExtensions.hasOwnProperty(spec.name)) {
 20.2878 -      var exts = modeExtensions[spec.name];
 20.2879 -      for (var prop in exts) {
 20.2880 -        if (!exts.hasOwnProperty(prop)) continue;
 20.2881 -        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
 20.2882 -        modeObj[prop] = exts[prop];
 20.2883 -      }
 20.2884 -    }
 20.2885 -    modeObj.name = spec.name;
 20.2886 -    return modeObj;
 20.2887 -  };
 20.2888 -
 20.2889 -  CodeMirror.defineMode("null", function() {
 20.2890 -    return {token: function(stream) {stream.skipToEnd();}};
 20.2891 -  });
 20.2892 -  CodeMirror.defineMIME("text/plain", "null");
 20.2893 -
 20.2894 -  var modeExtensions = CodeMirror.modeExtensions = {};
 20.2895 -  CodeMirror.extendMode = function(mode, properties) {
 20.2896 -    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
 20.2897 -    for (var prop in properties) if (properties.hasOwnProperty(prop))
 20.2898 -      exts[prop] = properties[prop];
 20.2899 -  };
 20.2900 -
 20.2901 -  // EXTENSIONS
 20.2902 -
 20.2903 -  CodeMirror.defineExtension = function(name, func) {
 20.2904 -    CodeMirror.prototype[name] = func;
 20.2905 -  };
 20.2906 -
 20.2907 -  CodeMirror.defineOption = option;
 20.2908 -
 20.2909 -  var initHooks = [];
 20.2910 -  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
 20.2911 -
 20.2912 -  // MODE STATE HANDLING
 20.2913 -
 20.2914 -  // Utility functions for working with state. Exported because modes
 20.2915 -  // sometimes need to do this.
 20.2916 -  function copyState(mode, state) {
 20.2917 -    if (state === true) return state;
 20.2918 -    if (mode.copyState) return mode.copyState(state);
 20.2919 -    var nstate = {};
 20.2920 -    for (var n in state) {
 20.2921 -      var val = state[n];
 20.2922 -      if (val instanceof Array) val = val.concat([]);
 20.2923 -      nstate[n] = val;
 20.2924 -    }
 20.2925 -    return nstate;
 20.2926 -  }
 20.2927 -  CodeMirror.copyState = copyState;
 20.2928 -
 20.2929 -  function startState(mode, a1, a2) {
 20.2930 -    return mode.startState ? mode.startState(a1, a2) : true;
 20.2931 -  }
 20.2932 -  CodeMirror.startState = startState;
 20.2933 -
 20.2934 -  CodeMirror.innerMode = function(mode, state) {
 20.2935 -    while (mode.innerMode) {
 20.2936 -      var info = mode.innerMode(state);
 20.2937 -      state = info.state;
 20.2938 -      mode = info.mode;
 20.2939 -    }
 20.2940 -    return info || {mode: mode, state: state};
 20.2941 -  };
 20.2942 -
 20.2943 -  // STANDARD COMMANDS
 20.2944 -
 20.2945 -  var commands = CodeMirror.commands = {
 20.2946 -    selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
 20.2947 -    killLine: function(cm) {
 20.2948 -      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
 20.2949 -      if (!sel && cm.getLine(from.line).length == from.ch)
 20.2950 -        cm.replaceRange("", from, {line: from.line + 1, ch: 0}, "delete");
 20.2951 -      else cm.replaceRange("", from, sel ? to : {line: from.line}, "delete");
 20.2952 -    },
 20.2953 -    deleteLine: function(cm) {
 20.2954 -      var l = cm.getCursor().line;
 20.2955 -      cm.replaceRange("", {line: l, ch: 0}, {line: l}, "delete");
 20.2956 -    },
 20.2957 -    undo: function(cm) {cm.undo();},
 20.2958 -    redo: function(cm) {cm.redo();},
 20.2959 -    goDocStart: function(cm) {cm.extendSelection({line: 0, ch: 0});},
 20.2960 -    goDocEnd: function(cm) {cm.extendSelection({line: cm.lineCount() - 1});},
 20.2961 -    goLineStart: function(cm) {
 20.2962 -      cm.extendSelection(lineStart(cm, cm.getCursor().line));
 20.2963 -    },
 20.2964 -    goLineStartSmart: function(cm) {
 20.2965 -      var cur = cm.getCursor(), start = lineStart(cm, cur.line);
 20.2966 -      var line = cm.getLineHandle(start.line);
 20.2967 -      var order = getOrder(line);
 20.2968 -      if (!order || order[0].level == 0) {
 20.2969 -        var firstNonWS = Math.max(0, line.text.search(/\S/));
 20.2970 -        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
 20.2971 -        cm.extendSelection({line: start.line, ch: inWS ? 0 : firstNonWS});
 20.2972 -      } else cm.extendSelection(start);
 20.2973 -    },
 20.2974 -    goLineEnd: function(cm) {
 20.2975 -      cm.extendSelection(lineEnd(cm, cm.getCursor().line));
 20.2976 -    },
 20.2977 -    goLineUp: function(cm) {cm.moveV(-1, "line");},
 20.2978 -    goLineDown: function(cm) {cm.moveV(1, "line");},
 20.2979 -    goPageUp: function(cm) {cm.moveV(-1, "page");},
 20.2980 -    goPageDown: function(cm) {cm.moveV(1, "page");},
 20.2981 -    goCharLeft: function(cm) {cm.moveH(-1, "char");},
 20.2982 -    goCharRight: function(cm) {cm.moveH(1, "char");},
 20.2983 -    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
 20.2984 -    goColumnRight: function(cm) {cm.moveH(1, "column");},
 20.2985 -    goWordLeft: function(cm) {cm.moveH(-1, "word");},
 20.2986 -    goWordRight: function(cm) {cm.moveH(1, "word");},
 20.2987 -    delCharBefore: function(cm) {cm.deleteH(-1, "char");},
 20.2988 -    delCharAfter: function(cm) {cm.deleteH(1, "char");},
 20.2989 -    delWordBefore: function(cm) {cm.deleteH(-1, "word");},
 20.2990 -    delWordAfter: function(cm) {cm.deleteH(1, "word");},
 20.2991 -    indentAuto: function(cm) {cm.indentSelection("smart");},
 20.2992 -    indentMore: function(cm) {cm.indentSelection("add");},
 20.2993 -    indentLess: function(cm) {cm.indentSelection("subtract");},
 20.2994 -    insertTab: function(cm) {cm.replaceSelection("\t", "end", "input");},
 20.2995 -    defaultTab: function(cm) {
 20.2996 -      if (cm.somethingSelected()) cm.indentSelection("add");
 20.2997 -      else cm.replaceSelection("\t", "end", "input");
 20.2998 -    },
 20.2999 -    transposeChars: function(cm) {
 20.3000 -      var cur = cm.getCursor(), line = cm.getLine(cur.line);
 20.3001 -      if (cur.ch > 0 && cur.ch < line.length - 1)
 20.3002 -        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
 20.3003 -                        {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});
 20.3004 -    },
 20.3005 -    newlineAndIndent: function(cm) {
 20.3006 -      operation(cm, function() {
 20.3007 -        cm.replaceSelection("\n", "end", "input");
 20.3008 -        cm.indentLine(cm.getCursor().line, null, true);
 20.3009 -      })();
 20.3010 -    },
 20.3011 -    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
 20.3012 -  };
 20.3013 -
 20.3014 -  // STANDARD KEYMAPS
 20.3015 -
 20.3016 -  var keyMap = CodeMirror.keyMap = {};
 20.3017 -  keyMap.basic = {
 20.3018 -    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
 20.3019 -    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
 20.3020 -    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
 20.3021 -    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
 20.3022 -  };
 20.3023 -  // Note that the save and find-related commands aren't defined by
 20.3024 -  // default. Unknown commands are simply ignored.
 20.3025 -  keyMap.pcDefault = {
 20.3026 -    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
 20.3027 -    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
 20.3028 -    "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
 20.3029 -    "Ctrl-Backspace": "delWordBefore", "Ctrl-Delete": "delWordAfter", "Ctrl-S": "save", "Ctrl-F": "find",
 20.3030 -    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
 20.3031 -    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
 20.3032 -    fallthrough: "basic"
 20.3033 -  };
 20.3034 -  keyMap.macDefault = {
 20.3035 -    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
 20.3036 -    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
 20.3037 -    "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordBefore",
 20.3038 -    "Ctrl-Alt-Backspace": "delWordAfter", "Alt-Delete": "delWordAfter", "Cmd-S": "save", "Cmd-F": "find",
 20.3039 -    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
 20.3040 -    "Cmd-[": "indentLess", "Cmd-]": "indentMore",
 20.3041 -    fallthrough: ["basic", "emacsy"]
 20.3042 -  };
 20.3043 -  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
 20.3044 -  keyMap.emacsy = {
 20.3045 -    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
 20.3046 -    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
 20.3047 -    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
 20.3048 -    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
 20.3049 -  };
 20.3050 -
 20.3051 -  // KEYMAP DISPATCH
 20.3052 -
 20.3053 -  function getKeyMap(val) {
 20.3054 -    if (typeof val == "string") return keyMap[val];
 20.3055 -    else return val;
 20.3056 -  }
 20.3057 -
 20.3058 -  function lookupKey(name, maps, handle, stop) {
 20.3059 -    function lookup(map) {
 20.3060 -      map = getKeyMap(map);
 20.3061 -      var found = map[name];
 20.3062 -      if (found === false) {
 20.3063 -        if (stop) stop();
 20.3064 -        return true;
 20.3065 -      }
 20.3066 -      if (found != null && handle(found)) return true;
 20.3067 -      if (map.nofallthrough) {
 20.3068 -        if (stop) stop();
 20.3069 -        return true;
 20.3070 -      }
 20.3071 -      var fallthrough = map.fallthrough;
 20.3072 -      if (fallthrough == null) return false;
 20.3073 -      if (Object.prototype.toString.call(fallthrough) != "[object Array]")
 20.3074 -        return lookup(fallthrough);
 20.3075 -      for (var i = 0, e = fallthrough.length; i < e; ++i) {
 20.3076 -        if (lookup(fallthrough[i])) return true;
 20.3077 -      }
 20.3078 -      return false;
 20.3079 -    }
 20.3080 -
 20.3081 -    for (var i = 0; i < maps.length; ++i)
 20.3082 -      if (lookup(maps[i])) return true;
 20.3083 -  }
 20.3084 -  function isModifierKey(event) {
 20.3085 -    var name = keyNames[e_prop(event, "keyCode")];
 20.3086 -    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
 20.3087 -  }
 20.3088 -  CodeMirror.isModifierKey = isModifierKey;
 20.3089 -
 20.3090 -  // FROMTEXTAREA
 20.3091 -
 20.3092 -  CodeMirror.fromTextArea = function(textarea, options) {
 20.3093 -    if (!options) options = {};
 20.3094 -    options.value = textarea.value;
 20.3095 -    if (!options.tabindex && textarea.tabindex)
 20.3096 -      options.tabindex = textarea.tabindex;
 20.3097 -    // Set autofocus to true if this textarea is focused, or if it has
 20.3098 -    // autofocus and no other element is focused.
 20.3099 -    if (options.autofocus == null) {
 20.3100 -      var hasFocus = document.body;
 20.3101 -      // doc.activeElement occasionally throws on IE
 20.3102 -      try { hasFocus = document.activeElement; } catch(e) {}
 20.3103 -      options.autofocus = hasFocus == textarea ||
 20.3104 -        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
 20.3105 -    }
 20.3106 -
 20.3107 -    function save() {textarea.value = cm.getValue();}
 20.3108 -    if (textarea.form) {
 20.3109 -      // Deplorable hack to make the submit method do the right thing.
 20.3110 -      on(textarea.form, "submit", save);
 20.3111 -      var form = textarea.form, realSubmit = form.submit;
 20.3112 -      try {
 20.3113 -        form.submit = function wrappedSubmit() {
 20.3114 -          save();
 20.3115 -          form.submit = realSubmit;
 20.3116 -          form.submit();
 20.3117 -          form.submit = wrappedSubmit;
 20.3118 -        };
 20.3119 -      } catch(e) {}
 20.3120 -    }
 20.3121 -
 20.3122 -    textarea.style.display = "none";
 20.3123 -    var cm = CodeMirror(function(node) {
 20.3124 -      textarea.parentNode.insertBefore(node, textarea.nextSibling);
 20.3125 -    }, options);
 20.3126 -    cm.save = save;
 20.3127 -    cm.getTextArea = function() { return textarea; };
 20.3128 -    cm.toTextArea = function() {
 20.3129 -      save();
 20.3130 -      textarea.parentNode.removeChild(cm.getWrapperElement());
 20.3131 -      textarea.style.display = "";
 20.3132 -      if (textarea.form) {
 20.3133 -        off(textarea.form, "submit", save);
 20.3134 -        if (typeof textarea.form.submit == "function")
 20.3135 -          textarea.form.submit = realSubmit;
 20.3136 -      }
 20.3137 -    };
 20.3138 -    return cm;
 20.3139 -  };
 20.3140 -
 20.3141 -  // STRING STREAM
 20.3142 -
 20.3143 -  // Fed to the mode parsers, provides helper functions to make
 20.3144 -  // parsers more succinct.
 20.3145 -
 20.3146 -  // The character stream used by a mode's parser.
 20.3147 -  function StringStream(string, tabSize) {
 20.3148 -    this.pos = this.start = 0;
 20.3149 -    this.string = string;
 20.3150 -    this.tabSize = tabSize || 8;
 20.3151 -  }
 20.3152 -
 20.3153 -  StringStream.prototype = {
 20.3154 -    eol: function() {return this.pos >= this.string.length;},
 20.3155 -    sol: function() {return this.pos == 0;},
 20.3156 -    peek: function() {return this.string.charAt(this.pos) || undefined;},
 20.3157 -    next: function() {
 20.3158 -      if (this.pos < this.string.length)
 20.3159 -        return this.string.charAt(this.pos++);
 20.3160 -    },
 20.3161 -    eat: function(match) {
 20.3162 -      var ch = this.string.charAt(this.pos);
 20.3163 -      if (typeof match == "string") var ok = ch == match;
 20.3164 -      else var ok = ch && (match.test ? match.test(ch) : match(ch));
 20.3165 -      if (ok) {++this.pos; return ch;}
 20.3166 -    },
 20.3167 -    eatWhile: function(match) {
 20.3168 -      var start = this.pos;
 20.3169 -      while (this.eat(match)){}
 20.3170 -      return this.pos > start;
 20.3171 -    },
 20.3172 -    eatSpace: function() {
 20.3173 -      var start = this.pos;
 20.3174 -      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
 20.3175 -      return this.pos > start;
 20.3176 -    },
 20.3177 -    skipToEnd: function() {this.pos = this.string.length;},
 20.3178 -    skipTo: function(ch) {
 20.3179 -      var found = this.string.indexOf(ch, this.pos);
 20.3180 -      if (found > -1) {this.pos = found; return true;}
 20.3181 -    },
 20.3182 -    backUp: function(n) {this.pos -= n;},
 20.3183 -    column: function() {return countColumn(this.string, this.start, this.tabSize);},
 20.3184 -    indentation: function() {return countColumn(this.string, null, this.tabSize);},
 20.3185 -    match: function(pattern, consume, caseInsensitive) {
 20.3186 -      if (typeof pattern == "string") {
 20.3187 -        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
 20.3188 -        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
 20.3189 -          if (consume !== false) this.pos += pattern.length;
 20.3190 -          return true;
 20.3191 -        }
 20.3192 -      } else {
 20.3193 -        var match = this.string.slice(this.pos).match(pattern);
 20.3194 -        if (match && match.index > 0) return null;
 20.3195 -        if (match && consume !== false) this.pos += match[0].length;
 20.3196 -        return match;
 20.3197 -      }
 20.3198 -    },
 20.3199 -    current: function(){return this.string.slice(this.start, this.pos);}
 20.3200 -  };
 20.3201 -  CodeMirror.StringStream = StringStream;
 20.3202 -
 20.3203 -  // TEXTMARKERS
 20.3204 -
 20.3205 -  function TextMarker(cm, type) {
 20.3206 -    this.lines = [];
 20.3207 -    this.type = type;
 20.3208 -    this.cm = cm;
 20.3209 -  }
 20.3210 -
 20.3211 -  TextMarker.prototype.clear = function() {
 20.3212 -    if (this.explicitlyCleared) return;
 20.3213 -    startOperation(this.cm);
 20.3214 -    var min = null, max = null;
 20.3215 -    for (var i = 0; i < this.lines.length; ++i) {
 20.3216 -      var line = this.lines[i];
 20.3217 -      var span = getMarkedSpanFor(line.markedSpans, this);
 20.3218 -      if (span.to != null) max = lineNo(line);
 20.3219 -      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
 20.3220 -      if (span.from != null)
 20.3221 -        min = lineNo(line);
 20.3222 -      else if (this.collapsed && !lineIsHidden(line))
 20.3223 -        updateLineHeight(line, textHeight(this.cm.display));
 20.3224 -    }
 20.3225 -    if (min != null) regChange(this.cm, min, max + 1);
 20.3226 -    this.lines.length = 0;
 20.3227 -    this.explicitlyCleared = true;
 20.3228 -    if (this.collapsed && this.cm.view.cantEdit) {
 20.3229 -      this.cm.view.cantEdit = false;
 20.3230 -      reCheckSelection(this.cm);
 20.3231 -    }
 20.3232 -    endOperation(this.cm);
 20.3233 -    signalLater(this.cm, this, "clear");
 20.3234 -  };
 20.3235 -
 20.3236 -  TextMarker.prototype.find = function() {
 20.3237 -    var from, to;
 20.3238 -    for (var i = 0; i < this.lines.length; ++i) {
 20.3239 -      var line = this.lines[i];
 20.3240 -      var span = getMarkedSpanFor(line.markedSpans, this);
 20.3241 -      if (span.from != null || span.to != null) {
 20.3242 -        var found = lineNo(line);
 20.3243 -        if (span.from != null) from = {line: found, ch: span.from};
 20.3244 -        if (span.to != null) to = {line: found, ch: span.to};
 20.3245 -      }
 20.3246 -    }
 20.3247 -    if (this.type == "bookmark") return from;
 20.3248 -    return from && {from: from, to: to};
 20.3249 -  };
 20.3250 -
 20.3251 -  function markText(cm, from, to, options, type) {
 20.3252 -    var doc = cm.view.doc;
 20.3253 -    var marker = new TextMarker(cm, type);
 20.3254 -    if (type == "range" && !posLess(from, to)) return marker;
 20.3255 -    if (options) for (var opt in options) if (options.hasOwnProperty(opt))
 20.3256 -      marker[opt] = options[opt];
 20.3257 -    if (marker.replacedWith) {
 20.3258 -      marker.collapsed = true;
 20.3259 -      marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
 20.3260 -    }
 20.3261 -    if (marker.collapsed) sawCollapsedSpans = true;
 20.3262 -
 20.3263 -    var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd;
 20.3264 -    doc.iter(curLine, to.line + 1, function(line) {
 20.3265 -      var span = {from: null, to: null, marker: marker};
 20.3266 -      size += line.text.length;
 20.3267 -      if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
 20.3268 -      if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
 20.3269 -      if (marker.collapsed) {
 20.3270 -        if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
 20.3271 -        if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
 20.3272 -        else updateLineHeight(line, 0);
 20.3273 -      }
 20.3274 -      addMarkedSpan(line, span);
 20.3275 -      if (marker.collapsed && curLine == from.line && lineIsHidden(line))
 20.3276 -        updateLineHeight(line, 0);
 20.3277 -      ++curLine;
 20.3278 -    });
 20.3279 -
 20.3280 -    if (marker.readOnly) {
 20.3281 -      sawReadOnlySpans = true;
 20.3282 -      if (cm.view.history.done.length || cm.view.history.undone.length)
 20.3283 -        cm.clearHistory();
 20.3284 -    }
 20.3285 -    if (marker.collapsed) {
 20.3286 -      if (collapsedAtStart != collapsedAtEnd)
 20.3287 -        throw new Error("Inserting collapsed marker overlapping an existing one");
 20.3288 -      marker.size = size;
 20.3289 -      marker.atomic = true;
 20.3290 -    }
 20.3291 -    if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
 20.3292 -      regChange(cm, from.line, to.line + 1);
 20.3293 -    if (marker.atomic) reCheckSelection(cm);
 20.3294 -    return marker;
 20.3295 -  }
 20.3296 -
 20.3297 -  // TEXTMARKER SPANS
 20.3298 -
 20.3299 -  function getMarkedSpanFor(spans, marker) {
 20.3300 -    if (spans) for (var i = 0; i < spans.length; ++i) {
 20.3301 -      var span = spans[i];
 20.3302 -      if (span.marker == marker) return span;
 20.3303 -    }
 20.3304 -  }
 20.3305 -  function removeMarkedSpan(spans, span) {
 20.3306 -    for (var r, i = 0; i < spans.length; ++i)
 20.3307 -      if (spans[i] != span) (r || (r = [])).push(spans[i]);
 20.3308 -    return r;
 20.3309 -  }
 20.3310 -  function addMarkedSpan(line, span) {
 20.3311 -    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
 20.3312 -    span.marker.lines.push(line);
 20.3313 -  }
 20.3314 -
 20.3315 -  function markedSpansBefore(old, startCh) {
 20.3316 -    if (old) for (var i = 0, nw; i < old.length; ++i) {
 20.3317 -      var span = old[i], marker = span.marker;
 20.3318 -      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
 20.3319 -      if (startsBefore || marker.type == "bookmark" && span.from == startCh) {
 20.3320 -        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
 20.3321 -        (nw || (nw = [])).push({from: span.from,
 20.3322 -                                to: endsAfter ? null : span.to,
 20.3323 -                                marker: marker});
 20.3324 -      }
 20.3325 -    }
 20.3326 -    return nw;
 20.3327 -  }
 20.3328 -
 20.3329 -  function markedSpansAfter(old, startCh, endCh) {
 20.3330 -    if (old) for (var i = 0, nw; i < old.length; ++i) {
 20.3331 -      var span = old[i], marker = span.marker;
 20.3332 -      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
 20.3333 -      if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.from != startCh) {
 20.3334 -        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
 20.3335 -        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
 20.3336 -                                to: span.to == null ? null : span.to - endCh,
 20.3337 -                                marker: marker});
 20.3338 -      }
 20.3339 -    }
 20.3340 -    return nw;
 20.3341 -  }
 20.3342 -
 20.3343 -  function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) {
 20.3344 -    if (!oldFirst && !oldLast) return newText;
 20.3345 -    // Get the spans that 'stick out' on both sides
 20.3346 -    var first = markedSpansBefore(oldFirst, startCh);
 20.3347 -    var last = markedSpansAfter(oldLast, startCh, endCh);
 20.3348 -
 20.3349 -    // Next, merge those two ends
 20.3350 -    var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0);
 20.3351 -    if (first) {
 20.3352 -      // Fix up .to properties of first
 20.3353 -      for (var i = 0; i < first.length; ++i) {
 20.3354 -        var span = first[i];
 20.3355 -        if (span.to == null) {
 20.3356 -          var found = getMarkedSpanFor(last, span.marker);
 20.3357 -          if (!found) span.to = startCh;
 20.3358 -          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
 20.3359 -        }
 20.3360 -      }
 20.3361 -    }
 20.3362 -    if (last) {
 20.3363 -      // Fix up .from in last (or move them into first in case of sameLine)
 20.3364 -      for (var i = 0; i < last.length; ++i) {
 20.3365 -        var span = last[i];
 20.3366 -        if (span.to != null) span.to += offset;
 20.3367 -        if (span.from == null) {
 20.3368 -          var found = getMarkedSpanFor(first, span.marker);
 20.3369 -          if (!found) {
 20.3370 -            span.from = offset;
 20.3371 -            if (sameLine) (first || (first = [])).push(span);
 20.3372 -          }
 20.3373 -        } else {
 20.3374 -          span.from += offset;
 20.3375 -          if (sameLine) (first || (first = [])).push(span);
 20.3376 -        }
 20.3377 -      }
 20.3378 -    }
 20.3379 -
 20.3380 -    var newMarkers = [newHL(newText[0], first)];
 20.3381 -    if (!sameLine) {
 20.3382 -      // Fill gap with whole-line-spans
 20.3383 -      var gap = newText.length - 2, gapMarkers;
 20.3384 -      if (gap > 0 && first)
 20.3385 -        for (var i = 0; i < first.length; ++i)
 20.3386 -          if (first[i].to == null)
 20.3387 -            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
 20.3388 -      for (var i = 0; i < gap; ++i)
 20.3389 -        newMarkers.push(newHL(newText[i+1], gapMarkers));
 20.3390 -      newMarkers.push(newHL(lst(newText), last));
 20.3391 -    }
 20.3392 -    return newMarkers;
 20.3393 -  }
 20.3394 -
 20.3395 -  function removeReadOnlyRanges(doc, from, to) {
 20.3396 -    var markers = null;
 20.3397 -    doc.iter(from.line, to.line + 1, function(line) {
 20.3398 -      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
 20.3399 -        var mark = line.markedSpans[i].marker;
 20.3400 -        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
 20.3401 -          (markers || (markers = [])).push(mark);
 20.3402 -      }
 20.3403 -    });
 20.3404 -    if (!markers) return null;
 20.3405 -    var parts = [{from: from, to: to}];
 20.3406 -    for (var i = 0; i < markers.length; ++i) {
 20.3407 -      var m = markers[i].find();
 20.3408 -      for (var j = 0; j < parts.length; ++j) {
 20.3409 -        var p = parts[j];
 20.3410 -        if (!posLess(m.from, p.to) || posLess(m.to, p.from)) continue;
 20.3411 -        var newParts = [j, 1];
 20.3412 -        if (posLess(p.from, m.from)) newParts.push({from: p.from, to: m.from});
 20.3413 -        if (posLess(m.to, p.to)) newParts.push({from: m.to, to: p.to});
 20.3414 -        parts.splice.apply(parts, newParts);
 20.3415 -        j += newParts.length - 1;
 20.3416 -      }
 20.3417 -    }
 20.3418 -    return parts;
 20.3419 -  }
 20.3420 -
 20.3421 -  function collapsedSpanAt(line, ch) {
 20.3422 -    var sps = sawCollapsedSpans && line.markedSpans, found;
 20.3423 -    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
 20.3424 -      sp = sps[i];
 20.3425 -      if (!sp.marker.collapsed) continue;
 20.3426 -      if ((sp.from == null || sp.from < ch) &&
 20.3427 -          (sp.to == null || sp.to > ch) &&
 20.3428 -          (!found || found.width < sp.marker.width))
 20.3429 -        found = sp.marker;
 20.3430 -    }
 20.3431 -    return found;
 20.3432 -  }
 20.3433 -  function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
 20.3434 -  function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
 20.3435 -
 20.3436 -  function visualLine(doc, line) {
 20.3437 -    var merged;
 20.3438 -    while (merged = collapsedSpanAtStart(line))
 20.3439 -      line = getLine(doc, merged.find().from.line);
 20.3440 -    return line;
 20.3441 -  }
 20.3442 -
 20.3443 -  function lineIsHidden(line) {
 20.3444 -    var sps = sawCollapsedSpans && line.markedSpans;
 20.3445 -    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
 20.3446 -      sp = sps[i];
 20.3447 -      if (!sp.marker.collapsed) continue;
 20.3448 -      if (sp.from == null) return true;
 20.3449 -      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(line, sp))
 20.3450 -        return true;
 20.3451 -    }
 20.3452 -  }
 20.3453 -  window.lineIsHidden = lineIsHidden;
 20.3454 -  function lineIsHiddenInner(line, span) {
 20.3455 -    if (span.to == null || span.marker.inclusiveRight && span.to == line.text.length)
 20.3456 -      return true;
 20.3457 -    for (var sp, i = 0; i < line.markedSpans.length; ++i) {
 20.3458 -      sp = line.markedSpans[i];
 20.3459 -      if (sp.marker.collapsed && sp.from == span.to &&
 20.3460 -          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
 20.3461 -          lineIsHiddenInner(line, sp)) return true;
 20.3462 -    }
 20.3463 -  }
 20.3464 -
 20.3465 -  // hl stands for history-line, a data structure that can be either a
 20.3466 -  // string (line without markers) or a {text, markedSpans} object.
 20.3467 -  function hlText(val) { return typeof val == "string" ? val : val.text; }
 20.3468 -  function hlSpans(val) {
 20.3469 -    if (typeof val == "string") return null;
 20.3470 -    var spans = val.markedSpans, out = null;
 20.3471 -    for (var i = 0; i < spans.length; ++i) {
 20.3472 -      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
 20.3473 -      else if (out) out.push(spans[i]);
 20.3474 -    }
 20.3475 -    return !out ? spans : out.length ? out : null;
 20.3476 -  }
 20.3477 -  function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; }
 20.3478 -
 20.3479 -  function detachMarkedSpans(line) {
 20.3480 -    var spans = line.markedSpans;
 20.3481 -    if (!spans) return;
 20.3482 -    for (var i = 0; i < spans.length; ++i) {
 20.3483 -      var lines = spans[i].marker.lines;
 20.3484 -      var ix = indexOf(lines, line);
 20.3485 -      lines.splice(ix, 1);
 20.3486 -    }
 20.3487 -    line.markedSpans = null;
 20.3488 -  }
 20.3489 -
 20.3490 -  function attachMarkedSpans(line, spans) {
 20.3491 -    if (!spans) return;
 20.3492 -    for (var i = 0; i < spans.length; ++i)
 20.3493 -      spans[i].marker.lines.push(line);
 20.3494 -    line.markedSpans = spans;
 20.3495 -  }
 20.3496 -
 20.3497 -  // LINE DATA STRUCTURE
 20.3498 -
 20.3499 -  // Line objects. These hold state related to a line, including
 20.3500 -  // highlighting info (the styles array).
 20.3501 -  function makeLine(text, markedSpans, height) {
 20.3502 -    var line = {text: text, height: height};
 20.3503 -    attachMarkedSpans(line, markedSpans);
 20.3504 -    if (lineIsHidden(line)) line.height = 0;
 20.3505 -    return line;
 20.3506 -  }
 20.3507 -
 20.3508 -  function updateLine(cm, line, text, markedSpans) {
 20.3509 -    line.text = text;
 20.3510 -    line.stateAfter = line.styles = null;
 20.3511 -    if (line.order != null) line.order = null;
 20.3512 -    detachMarkedSpans(line);
 20.3513 -    attachMarkedSpans(line, markedSpans);
 20.3514 -    if (lineIsHidden(line)) line.height = 0;
 20.3515 -    else if (!line.height) line.height = textHeight(cm.display);
 20.3516 -    signalLater(cm, line, "change");
 20.3517 -  }
 20.3518 -
 20.3519 -  function cleanUpLine(line) {
 20.3520 -    line.parent = null;
 20.3521 -    detachMarkedSpans(line);
 20.3522 -  }
 20.3523 -
 20.3524 -  // Run the given mode's parser over a line, update the styles
 20.3525 -  // array, which contains alternating fragments of text and CSS
 20.3526 -  // classes.
 20.3527 -  function highlightLine(cm, line, state) {
 20.3528 -    var mode = cm.view.mode, flattenSpans = cm.options.flattenSpans;
 20.3529 -    var changed = !line.styles, pos = 0, curText = "", curStyle = null;
 20.3530 -    var stream = new StringStream(line.text, cm.options.tabSize), st = line.styles || (line.styles = []);
 20.3531 -    if (line.text == "" && mode.blankLine) mode.blankLine(state);
 20.3532 -    while (!stream.eol()) {
 20.3533 -      var style = mode.token(stream, state), substr = stream.current();
 20.3534 -      stream.start = stream.pos;
 20.3535 -      if (!flattenSpans || curStyle != style) {
 20.3536 -        if (curText) {
 20.3537 -          changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
 20.3538 -          st[pos++] = curText; st[pos++] = curStyle;
 20.3539 -        }
 20.3540 -        curText = substr; curStyle = style;
 20.3541 -      } else curText = curText + substr;
 20.3542 -      // Give up when line is ridiculously long
 20.3543 -      if (stream.pos > 5000) break;
 20.3544 -    }
 20.3545 -    if (curText) {
 20.3546 -      changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1];
 20.3547 -      st[pos++] = curText; st[pos++] = curStyle;
 20.3548 -    }
 20.3549 -    if (stream.pos > 5000) { st[pos++] = line.text.slice(stream.pos); st[pos++] = null; }
 20.3550 -    if (pos != st.length) { st.length = pos; changed = true; }
 20.3551 -    return changed;
 20.3552 -  }
 20.3553 -
 20.3554 -  // Lightweight form of highlight -- proceed over this line and
 20.3555 -  // update state, but don't save a style array.
 20.3556 -  function processLine(cm, line, state) {
 20.3557 -    var mode = cm.view.mode;
 20.3558 -    var stream = new StringStream(line.text, cm.options.tabSize);
 20.3559 -    if (line.text == "" && mode.blankLine) mode.blankLine(state);
 20.3560 -    while (!stream.eol() && stream.pos <= 5000) {
 20.3561 -      mode.token(stream, state);
 20.3562 -      stream.start = stream.pos;
 20.3563 -    }
 20.3564 -  }
 20.3565 -
 20.3566 -  var styleToClassCache = {};
 20.3567 -  function styleToClass(style) {
 20.3568 -    if (!style) return null;
 20.3569 -    return styleToClassCache[style] ||
 20.3570 -      (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
 20.3571 -  }
 20.3572 -
 20.3573 -  function lineContent(cm, realLine, measure) {
 20.3574 -    var merged, line = realLine, lineBefore, sawBefore, simple = true;
 20.3575 -    while (merged = collapsedSpanAtStart(line)) {
 20.3576 -      simple = false;
 20.3577 -      line = getLine(cm.view.doc, merged.find().from.line);
 20.3578 -      if (!lineBefore) lineBefore = line;
 20.3579 -    }
 20.3580 -
 20.3581 -    var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
 20.3582 -                   measure: null, addedOne: false, cm: cm};
 20.3583 -    if (line.textClass) builder.pre.className = line.textClass;
 20.3584 -
 20.3585 -    do {
 20.3586 -      if (!line.styles)
 20.3587 -        highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
 20.3588 -      builder.measure = line == realLine && measure;
 20.3589 -      builder.pos = 0;
 20.3590 -      builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
 20.3591 -      if (measure && sawBefore && line != realLine && !builder.addedOne) {
 20.3592 -        measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
 20.3593 -        builder.addedOne = true;
 20.3594 -      }
 20.3595 -      var next = insertLineContent(line, builder);
 20.3596 -      sawBefore = line == lineBefore;
 20.3597 -      if (next) {
 20.3598 -        line = getLine(cm.view.doc, next.to.line);
 20.3599 -        simple = false;
 20.3600 -      }
 20.3601 -    } while (next);
 20.3602 -
 20.3603 -    if (measure && !builder.addedOne)
 20.3604 -      measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
 20.3605 -    if (!builder.pre.firstChild && !lineIsHidden(realLine))
 20.3606 -      builder.pre.appendChild(document.createTextNode("\u00a0"));
 20.3607 -
 20.3608 -    return builder.pre;
 20.3609 -  }
 20.3610 -
 20.3611 -  var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
 20.3612 -  function buildToken(builder, text, style, startStyle, endStyle) {
 20.3613 -    if (!text) return;
 20.3614 -    if (!tokenSpecialChars.test(text)) {
 20.3615 -      builder.col += text.length;
 20.3616 -      var content = document.createTextNode(text);
 20.3617 -    } else {
 20.3618 -      var content = document.createDocumentFragment(), pos = 0;
 20.3619 -      while (true) {
 20.3620 -        tokenSpecialChars.lastIndex = pos;
 20.3621 -        var m = tokenSpecialChars.exec(text);
 20.3622 -        var skipped = m ? m.index - pos : text.length - pos;
 20.3623 -        if (skipped) {
 20.3624 -          content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
 20.3625 -          builder.col += skipped;
 20.3626 -        }
 20.3627 -        if (!m) break;
 20.3628 -        pos += skipped + 1;
 20.3629 -        if (m[0] == "\t") {
 20.3630 -          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
 20.3631 -          content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
 20.3632 -          builder.col += tabWidth;
 20.3633 -        } else {
 20.3634 -          var token = elt("span", "\u2022", "cm-invalidchar");
 20.3635 -          token.title = "\\u" + m[0].charCodeAt(0).toString(16);
 20.3636 -          content.appendChild(token);
 20.3637 -          builder.col += 1;
 20.3638 -        }
 20.3639 -      }
 20.3640 -    }
 20.3641 -    if (style || startStyle || endStyle || builder.measure) {
 20.3642 -      var fullStyle = style || "";
 20.3643 -      if (startStyle) fullStyle += startStyle;
 20.3644 -      if (endStyle) fullStyle += endStyle;
 20.3645 -      return builder.pre.appendChild(elt("span", [content], fullStyle));
 20.3646 -    }
 20.3647 -    builder.pre.appendChild(content);
 20.3648 -  }
 20.3649 -
 20.3650 -  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
 20.3651 -    for (var i = 0; i < text.length; ++i) {
 20.3652 -      if (i && i < text.length - 1 &&
 20.3653 -          builder.cm.options.lineWrapping &&
 20.3654 -          spanAffectsWrapping.test(text.slice(i - 1, i + 1)))
 20.3655 -        builder.pre.appendChild(elt("wbr"));
 20.3656 -      builder.measure[builder.pos++] =
 20.3657 -        buildToken(builder, text.charAt(i), style,
 20.3658 -                   i == 0 && startStyle, i == text.length - 1 && endStyle);
 20.3659 -    }
 20.3660 -    if (text.length) builder.addedOne = true;
 20.3661 -  }
 20.3662 -
 20.3663 -  function buildCollapsedSpan(builder, size, widget) {
 20.3664 -    if (widget) {
 20.3665 -      if (!builder.display) widget = widget.cloneNode(true);
 20.3666 -      builder.pre.appendChild(widget);
 20.3667 -      if (builder.measure && size) {
 20.3668 -        builder.measure[builder.pos] = widget;
 20.3669 -        builder.addedOne = true;
 20.3670 -      }
 20.3671 -    }
 20.3672 -    builder.pos += size;
 20.3673 -  }
 20.3674 -
 20.3675 -  // Outputs a number of spans to make up a line, taking highlighting
 20.3676 -  // and marked text into account.
 20.3677 -  function insertLineContent(line, builder) {
 20.3678 -    var st = line.styles, spans = line.markedSpans;
 20.3679 -    if (!spans) {
 20.3680 -      for (var i = 0; i < st.length; i+=2)
 20.3681 -        builder.addToken(builder, st[i], styleToClass(st[i+1]));
 20.3682 -      return;
 20.3683 -    }
 20.3684 -
 20.3685 -    var allText = line.text, len = allText.length;
 20.3686 -    var pos = 0, i = 0, text = "", style;
 20.3687 -    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
 20.3688 -    for (;;) {
 20.3689 -      if (nextChange == pos) { // Update current marker set
 20.3690 -        spanStyle = spanEndStyle = spanStartStyle = "";
 20.3691 -        collapsed = null; nextChange = Infinity;
 20.3692 -        var foundBookmark = null;
 20.3693 -        for (var j = 0; j < spans.length; ++j) {
 20.3694 -          var sp = spans[j], m = sp.marker;
 20.3695 -          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
 20.3696 -            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
 20.3697 -            if (m.className) spanStyle += " " + m.className;
 20.3698 -            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
 20.3699 -            if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
 20.3700 -            if (m.collapsed && (!collapsed || collapsed.marker.width < m.width))
 20.3701 -              collapsed = sp;
 20.3702 -          } else if (sp.from > pos && nextChange > sp.from) {
 20.3703 -            nextChange = sp.from;
 20.3704 -          }
 20.3705 -          if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
 20.3706 -            foundBookmark = m.replacedWith;
 20.3707 -        }
 20.3708 -        if (collapsed && (collapsed.from || 0) == pos) {
 20.3709 -          buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
 20.3710 -                             collapsed.from != null && collapsed.marker.replacedWith);
 20.3711 -          if (collapsed.to == null) return collapsed.marker.find();
 20.3712 -        }
 20.3713 -        if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
 20.3714 -      }
 20.3715 -      if (pos >= len) break;
 20.3716 -
 20.3717 -      var upto = Math.min(len, nextChange);
 20.3718 -      while (true) {
 20.3719 -        if (text) {
 20.3720 -          var end = pos + text.length;
 20.3721 -          if (!collapsed) {
 20.3722 -            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
 20.3723 -            builder.addToken(builder, tokenText, style + spanStyle,
 20.3724 -                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
 20.3725 -          }
 20.3726 -          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
 20.3727 -          pos = end;
 20.3728 -          spanStartStyle = "";
 20.3729 -        }
 20.3730 -        text = st[i++]; style = styleToClass(st[i++]);
 20.3731 -      }
 20.3732 -    }
 20.3733 -  }
 20.3734 -
 20.3735 -  // DOCUMENT DATA STRUCTURE
 20.3736 -
 20.3737 -  function LeafChunk(lines) {
 20.3738 -    this.lines = lines;
 20.3739 -    this.parent = null;
 20.3740 -    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
 20.3741 -      lines[i].parent = this;
 20.3742 -      height += lines[i].height;
 20.3743 -    }
 20.3744 -    this.height = height;
 20.3745 -  }
 20.3746 -
 20.3747 -  LeafChunk.prototype = {
 20.3748 -    chunkSize: function() { return this.lines.length; },
 20.3749 -    remove: function(at, n, cm) {
 20.3750 -      for (var i = at, e = at + n; i < e; ++i) {
 20.3751 -        var line = this.lines[i];
 20.3752 -        this.height -= line.height;
 20.3753 -        cleanUpLine(line);
 20.3754 -        signalLater(cm, line, "delete");
 20.3755 -      }
 20.3756 -      this.lines.splice(at, n);
 20.3757 -    },
 20.3758 -    collapse: function(lines) {
 20.3759 -      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
 20.3760 -    },
 20.3761 -    insertHeight: function(at, lines, height) {
 20.3762 -      this.height += height;
 20.3763 -      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
 20.3764 -      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
 20.3765 -    },
 20.3766 -    iterN: function(at, n, op) {
 20.3767 -      for (var e = at + n; at < e; ++at)
 20.3768 -        if (op(this.lines[at])) return true;
 20.3769 -    }
 20.3770 -  };
 20.3771 -
 20.3772 -  function BranchChunk(children) {
 20.3773 -    this.children = children;
 20.3774 -    var size = 0, height = 0;
 20.3775 -    for (var i = 0, e = children.length; i < e; ++i) {
 20.3776 -      var ch = children[i];
 20.3777 -      size += ch.chunkSize(); height += ch.height;
 20.3778 -      ch.parent = this;
 20.3779 -    }
 20.3780 -    this.size = size;
 20.3781 -    this.height = height;
 20.3782 -    this.parent = null;
 20.3783 -  }
 20.3784 -
 20.3785 -  BranchChunk.prototype = {
 20.3786 -    chunkSize: function() { return this.size; },
 20.3787 -    remove: function(at, n, callbacks) {
 20.3788 -      this.size -= n;
 20.3789 -      for (var i = 0; i < this.children.length; ++i) {
 20.3790 -        var child = this.children[i], sz = child.chunkSize();
 20.3791 -        if (at < sz) {
 20.3792 -          var rm = Math.min(n, sz - at), oldHeight = child.height;
 20.3793 -          child.remove(at, rm, callbacks);
 20.3794 -          this.height -= oldHeight - child.height;
 20.3795 -          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
 20.3796 -          if ((n -= rm) == 0) break;
 20.3797 -          at = 0;
 20.3798 -        } else at -= sz;
 20.3799 -      }
 20.3800 -      if (this.size - n < 25) {
 20.3801 -        var lines = [];
 20.3802 -        this.collapse(lines);
 20.3803 -        this.children = [new LeafChunk(lines)];
 20.3804 -        this.children[0].parent = this;
 20.3805 -      }
 20.3806 -    },
 20.3807 -    collapse: function(lines) {
 20.3808 -      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
 20.3809 -    },
 20.3810 -    insert: function(at, lines) {
 20.3811 -      var height = 0;
 20.3812 -      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
 20.3813 -      this.insertHeight(at, lines, height);
 20.3814 -    },
 20.3815 -    insertHeight: function(at, lines, height) {
 20.3816 -      this.size += lines.length;
 20.3817 -      this.height += height;
 20.3818 -      for (var i = 0, e = this.children.length; i < e; ++i) {
 20.3819 -        var child = this.children[i], sz = child.chunkSize();
 20.3820 -        if (at <= sz) {
 20.3821 -          child.insertHeight(at, lines, height);
 20.3822 -          if (child.lines && child.lines.length > 50) {
 20.3823 -            while (child.lines.length > 50) {
 20.3824 -              var spilled = child.lines.splice(child.lines.length - 25, 25);
 20.3825 -              var newleaf = new LeafChunk(spilled);
 20.3826 -              child.height -= newleaf.height;
 20.3827 -              this.children.splice(i + 1, 0, newleaf);
 20.3828 -              newleaf.parent = this;
 20.3829 -            }
 20.3830 -            this.maybeSpill();
 20.3831 -          }
 20.3832 -          break;
 20.3833 -        }
 20.3834 -        at -= sz;
 20.3835 -      }
 20.3836 -    },
 20.3837 -    maybeSpill: function() {
 20.3838 -      if (this.children.length <= 10) return;
 20.3839 -      var me = this;
 20.3840 -      do {
 20.3841 -        var spilled = me.children.splice(me.children.length - 5, 5);
 20.3842 -        var sibling = new BranchChunk(spilled);
 20.3843 -        if (!me.parent) { // Become the parent node
 20.3844 -          var copy = new BranchChunk(me.children);
 20.3845 -          copy.parent = me;
 20.3846 -          me.children = [copy, sibling];
 20.3847 -          me = copy;
 20.3848 -        } else {
 20.3849 -          me.size -= sibling.size;
 20.3850 -          me.height -= sibling.height;
 20.3851 -          var myIndex = indexOf(me.parent.children, me);
 20.3852 -          me.parent.children.splice(myIndex + 1, 0, sibling);
 20.3853 -        }
 20.3854 -        sibling.parent = me.parent;
 20.3855 -      } while (me.children.length > 10);
 20.3856 -      me.parent.maybeSpill();
 20.3857 -    },
 20.3858 -    iter: function(from, to, op) { this.iterN(from, to - from, op); },
 20.3859 -    iterN: function(at, n, op) {
 20.3860 -      for (var i = 0, e = this.children.length; i < e; ++i) {
 20.3861 -        var child = this.children[i], sz = child.chunkSize();
 20.3862 -        if (at < sz) {
 20.3863 -          var used = Math.min(n, sz - at);
 20.3864 -          if (child.iterN(at, used, op)) return true;
 20.3865 -          if ((n -= used) == 0) break;
 20.3866 -          at = 0;
 20.3867 -        } else at -= sz;
 20.3868 -      }
 20.3869 -    }
 20.3870 -  };
 20.3871 -
 20.3872 -  // LINE UTILITIES
 20.3873 -
 20.3874 -  function getLine(chunk, n) {
 20.3875 -    while (!chunk.lines) {
 20.3876 -      for (var i = 0;; ++i) {
 20.3877 -        var child = chunk.children[i], sz = child.chunkSize();
 20.3878 -        if (n < sz) { chunk = child; break; }
 20.3879 -        n -= sz;
 20.3880 -      }
 20.3881 -    }
 20.3882 -    return chunk.lines[n];
 20.3883 -  }
 20.3884 -
 20.3885 -  function updateLineHeight(line, height) {
 20.3886 -    var diff = height - line.height;
 20.3887 -    for (var n = line; n; n = n.parent) n.height += diff;
 20.3888 -  }
 20.3889 -
 20.3890 -  function lineNo(line) {
 20.3891 -    if (line.parent == null) return null;
 20.3892 -    var cur = line.parent, no = indexOf(cur.lines, line);
 20.3893 -    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
 20.3894 -      for (var i = 0;; ++i) {
 20.3895 -        if (chunk.children[i] == cur) break;
 20.3896 -        no += chunk.children[i].chunkSize();
 20.3897 -      }
 20.3898 -    }
 20.3899 -    return no;
 20.3900 -  }
 20.3901 -
 20.3902 -  function lineAtHeight(chunk, h) {
 20.3903 -    var n = 0;
 20.3904 -    outer: do {
 20.3905 -      for (var i = 0, e = chunk.children.length; i < e; ++i) {
 20.3906 -        var child = chunk.children[i], ch = child.height;
 20.3907 -        if (h < ch) { chunk = child; continue outer; }
 20.3908 -        h -= ch;
 20.3909 -        n += child.chunkSize();
 20.3910 -      }
 20.3911 -      return n;
 20.3912 -    } while (!chunk.lines);
 20.3913 -    for (var i = 0, e = chunk.lines.length; i < e; ++i) {
 20.3914 -      var line = chunk.lines[i], lh = line.height;
 20.3915 -      if (h < lh) break;
 20.3916 -      h -= lh;
 20.3917 -    }
 20.3918 -    return n + i;
 20.3919 -  }
 20.3920 -
 20.3921 -  function heightAtLine(cm, lineObj) {
 20.3922 -    lineObj = visualLine(cm.view.doc, lineObj);
 20.3923 -
 20.3924 -    var h = 0, chunk = lineObj.parent;
 20.3925 -    for (var i = 0; i < chunk.lines.length; ++i) {
 20.3926 -      var line = chunk.lines[i];
 20.3927 -      if (line == lineObj) break;
 20.3928 -      else h += line.height;
 20.3929 -    }
 20.3930 -    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
 20.3931 -      for (var i = 0; i < p.children.length; ++i) {
 20.3932 -        var cur = p.children[i];
 20.3933 -        if (cur == chunk) break;
 20.3934 -        else h += cur.height;
 20.3935 -      }
 20.3936 -    }
 20.3937 -    return h;
 20.3938 -  }
 20.3939 -
 20.3940 -  function getOrder(line) {
 20.3941 -    var order = line.order;
 20.3942 -    if (order == null) order = line.order = bidiOrdering(line.text);
 20.3943 -    return order;
 20.3944 -  }
 20.3945 -
 20.3946 -  // HISTORY
 20.3947 -
 20.3948 -  function makeHistory() {
 20.3949 -    return {
 20.3950 -      // Arrays of history events. Doing something adds an event to
 20.3951 -      // done and clears undo. Undoing moves events from done to
 20.3952 -      // undone, redoing moves them in the other direction.
 20.3953 -      done: [], undone: [],
 20.3954 -      // Used to track when changes can be merged into a single undo
 20.3955 -      // event
 20.3956 -      lastTime: 0, lastOp: null, lastOrigin: null,
 20.3957 -      // Used by the isClean() method
 20.3958 -      dirtyCounter: 0
 20.3959 -    };
 20.3960 -  }
 20.3961 -
 20.3962 -  function addChange(cm, start, added, old, origin, fromBefore, toBefore, fromAfter, toAfter) {
 20.3963 -    var history = cm.view.history;
 20.3964 -    history.undone.length = 0;
 20.3965 -    var time = +new Date, cur = lst(history.done);
 20.3966 -    
 20.3967 -    if (cur &&
 20.3968 -        (history.lastOp == cm.curOp.id ||
 20.3969 -         history.lastOrigin == origin && (origin == "input" || origin == "delete") &&
 20.3970 -         history.lastTime > time - 600)) {
 20.3971 -      // Merge this change into the last event
 20.3972 -      var last = lst(cur.events);
 20.3973 -      if (last.start > start + old.length || last.start + last.added < start) {
 20.3974 -        // Doesn't intersect with last sub-event, add new sub-event
 20.3975 -        cur.events.push({start: start, added: added, old: old});
 20.3976 -      } else {
 20.3977 -        // Patch up the last sub-event
 20.3978 -        var startBefore = Math.max(0, last.start - start),
 20.3979 -        endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
 20.3980 -        for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
 20.3981 -        for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
 20.3982 -        if (startBefore) last.start = start;
 20.3983 -        last.added += added - (old.length - startBefore - endAfter);
 20.3984 -      }
 20.3985 -      cur.fromAfter = fromAfter; cur.toAfter = toAfter;
 20.3986 -    } else {
 20.3987 -      // Can not be merged, start a new event.
 20.3988 -      cur = {events: [{start: start, added: added, old: old}],
 20.3989 -             fromBefore: fromBefore, toBefore: toBefore, fromAfter: fromAfter, toAfter: toAfter};
 20.3990 -      history.done.push(cur);
 20.3991 -      while (history.done.length > cm.options.undoDepth)
 20.3992 -        history.done.shift();
 20.3993 -      if (history.dirtyCounter < 0)
 20.3994 -          // The user has made a change after undoing past the last clean state. 
 20.3995 -          // We can never get back to a clean state now until markClean() is called.
 20.3996 -          history.dirtyCounter = NaN;
 20.3997 -      else
 20.3998 -        history.dirtyCounter++;
 20.3999 -    }
 20.4000 -    history.lastTime = time;
 20.4001 -    history.lastOp = cm.curOp.id;
 20.4002 -    history.lastOrigin = origin;
 20.4003 -  }
 20.4004 -
 20.4005 -  // EVENT OPERATORS
 20.4006 -
 20.4007 -  function stopMethod() {e_stop(this);}
 20.4008 -  // Ensure an event has a stop method.
 20.4009 -  function addStop(event) {
 20.4010 -    if (!event.stop) event.stop = stopMethod;
 20.4011 -    return event;
 20.4012 -  }
 20.4013 -
 20.4014 -  function e_preventDefault(e) {
 20.4015 -    if (e.preventDefault) e.preventDefault();
 20.4016 -    else e.returnValue = false;
 20.4017 -  }
 20.4018 -  function e_stopPropagation(e) {
 20.4019 -    if (e.stopPropagation) e.stopPropagation();
 20.4020 -    else e.cancelBubble = true;
 20.4021 -  }
 20.4022 -  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
 20.4023 -  CodeMirror.e_stop = e_stop;
 20.4024 -  CodeMirror.e_preventDefault = e_preventDefault;
 20.4025 -  CodeMirror.e_stopPropagation = e_stopPropagation;
 20.4026 -
 20.4027 -  function e_target(e) {return e.target || e.srcElement;}
 20.4028 -  function e_button(e) {
 20.4029 -    var b = e.which;
 20.4030 -    if (b == null) {
 20.4031 -      if (e.button & 1) b = 1;
 20.4032 -      else if (e.button & 2) b = 3;
 20.4033 -      else if (e.button & 4) b = 2;
 20.4034 -    }
 20.4035 -    if (mac && e.ctrlKey && b == 1) b = 3;
 20.4036 -    return b;
 20.4037 -  }
 20.4038 -
 20.4039 -  // Allow 3rd-party code to override event properties by adding an override
 20.4040 -  // object to an event object.
 20.4041 -  function e_prop(e, prop) {
 20.4042 -    var overridden = e.override && e.override.hasOwnProperty(prop);
 20.4043 -    return overridden ? e.override[prop] : e[prop];
 20.4044 -  }
 20.4045 -
 20.4046 -  // EVENT HANDLING
 20.4047 -
 20.4048 -  function on(emitter, type, f) {
 20.4049 -    if (emitter.addEventListener)
 20.4050 -      emitter.addEventListener(type, f, false);
 20.4051 -    else if (emitter.attachEvent)
 20.4052 -      emitter.attachEvent("on" + type, f);
 20.4053 -    else {
 20.4054 -      var map = emitter._handlers || (emitter._handlers = {});
 20.4055 -      var arr = map[type] || (map[type] = []);
 20.4056 -      arr.push(f);
 20.4057 -    }
 20.4058 -  }
 20.4059 -
 20.4060 -  function off(emitter, type, f) {
 20.4061 -    if (emitter.removeEventListener)
 20.4062 -      emitter.removeEventListener(type, f, false);
 20.4063 -    else if (emitter.detachEvent)
 20.4064 -      emitter.detachEvent("on" + type, f);
 20.4065 -    else {
 20.4066 -      var arr = emitter._handlers && emitter._handlers[type];
 20.4067 -      if (!arr) return;
 20.4068 -      for (var i = 0; i < arr.length; ++i)
 20.4069 -        if (arr[i] == f) { arr.splice(i, 1); break; }
 20.4070 -    }
 20.4071 -  }
 20.4072 -
 20.4073 -  function signal(emitter, type /*, values...*/) {
 20.4074 -    var arr = emitter._handlers && emitter._handlers[type];
 20.4075 -    if (!arr) return;
 20.4076 -    var args = Array.prototype.slice.call(arguments, 2);
 20.4077 -    for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
 20.4078 -  }
 20.4079 -
 20.4080 -  function signalLater(cm, emitter, type /*, values...*/) {
 20.4081 -    var arr = emitter._handlers && emitter._handlers[type];
 20.4082 -    if (!arr) return;
 20.4083 -    var args = Array.prototype.slice.call(arguments, 3), flist = cm.curOp && cm.curOp.delayedCallbacks;
 20.4084 -    function bnd(f) {return function(){f.apply(null, args);};};
 20.4085 -    for (var i = 0; i < arr.length; ++i)
 20.4086 -      if (flist) flist.push(bnd(arr[i]));
 20.4087 -      else arr[i].apply(null, args);
 20.4088 -  }
 20.4089 -
 20.4090 -  function hasHandler(emitter, type) {
 20.4091 -    var arr = emitter._handlers && emitter._handlers[type];
 20.4092 -    return arr && arr.length > 0;
 20.4093 -  }
 20.4094 -
 20.4095 -  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
 20.4096 -
 20.4097 -  // MISC UTILITIES
 20.4098 -
 20.4099 -  // Number of pixels added to scroller and sizer to hide scrollbar
 20.4100 -  var scrollerCutOff = 30;
 20.4101 -
 20.4102 -  // Returned or thrown by various protocols to signal 'I'm not
 20.4103 -  // handling this'.
 20.4104 -  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
 20.4105 -
 20.4106 -  function Delayed() {this.id = null;}
 20.4107 -  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
 20.4108 -
 20.4109 -  // Counts the column offset in a string, taking tabs into account.
 20.4110 -  // Used mostly to find indentation.
 20.4111 -  function countColumn(string, end, tabSize) {
 20.4112 -    if (end == null) {
 20.4113 -      end = string.search(/[^\s\u00a0]/);
 20.4114 -      if (end == -1) end = string.length;
 20.4115 -    }
 20.4116 -    for (var i = 0, n = 0; i < end; ++i) {
 20.4117 -      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
 20.4118 -      else ++n;
 20.4119 -    }
 20.4120 -    return n;
 20.4121 -  }
 20.4122 -  CodeMirror.countColumn = countColumn;
 20.4123 -
 20.4124 -  var spaceStrs = [""];
 20.4125 -  function spaceStr(n) {
 20.4126 -    while (spaceStrs.length <= n)
 20.4127 -      spaceStrs.push(lst(spaceStrs) + " ");
 20.4128 -    return spaceStrs[n];
 20.4129 -  }
 20.4130 -
 20.4131 -  function lst(arr) { return arr[arr.length-1]; }
 20.4132 -
 20.4133 -  function selectInput(node) {
 20.4134 -    if (ios) { // Mobile Safari apparently has a bug where select() is broken.
 20.4135 -      node.selectionStart = 0;
 20.4136 -      node.selectionEnd = node.value.length;
 20.4137 -    } else node.select();
 20.4138 -  }
 20.4139 -
 20.4140 -  function indexOf(collection, elt) {
 20.4141 -    if (collection.indexOf) return collection.indexOf(elt);
 20.4142 -    for (var i = 0, e = collection.length; i < e; ++i)
 20.4143 -      if (collection[i] == elt) return i;
 20.4144 -    return -1;
 20.4145 -  }
 20.4146 -
 20.4147 -  function emptyArray(size) {
 20.4148 -    for (var a = [], i = 0; i < size; ++i) a.push(undefined);
 20.4149 -    return a;
 20.4150 -  }
 20.4151 -
 20.4152 -  function bind(f) {
 20.4153 -    var args = Array.prototype.slice.call(arguments, 1);
 20.4154 -    return function(){return f.apply(null, args);};
 20.4155 -  }
 20.4156 -
 20.4157 -  var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
 20.4158 -  function isWordChar(ch) {
 20.4159 -    return /\w/.test(ch) || ch > "\x80" &&
 20.4160 -      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
 20.4161 -  }
 20.4162 -
 20.4163 -  function isEmpty(obj) {
 20.4164 -    var c = 0;
 20.4165 -    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) ++c;
 20.4166 -    return !c;
 20.4167 -  }
 20.4168 -
 20.4169 -  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F]/;
 20.4170 -
 20.4171 -  // DOM UTILITIES
 20.4172 -
 20.4173 -  function elt(tag, content, className, style) {
 20.4174 -    var e = document.createElement(tag);
 20.4175 -    if (className) e.className = className;
 20.4176 -    if (style) e.style.cssText = style;
 20.4177 -    if (typeof content == "string") setTextContent(e, content);
 20.4178 -    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
 20.4179 -    return e;
 20.4180 -  }
 20.4181 -
 20.4182 -  function removeChildren(e) {
 20.4183 -    e.innerHTML = "";
 20.4184 -    return e;
 20.4185 -  }
 20.4186 -
 20.4187 -  function removeChildrenAndAdd(parent, e) {
 20.4188 -    return removeChildren(parent).appendChild(e);
 20.4189 -  }
 20.4190 -
 20.4191 -  function setTextContent(e, str) {
 20.4192 -    if (ie_lt9) {
 20.4193 -      e.innerHTML = "";
 20.4194 -      e.appendChild(document.createTextNode(str));
 20.4195 -    } else e.textContent = str;
 20.4196 -  }
 20.4197 -
 20.4198 -  // FEATURE DETECTION
 20.4199 -
 20.4200 -  // Detect drag-and-drop
 20.4201 -  var dragAndDrop = function() {
 20.4202 -    // There is *some* kind of drag-and-drop support in IE6-8, but I
 20.4203 -    // couldn't get it to work yet.
 20.4204 -    if (ie_lt9) return false;
 20.4205 -    var div = elt('div');
 20.4206 -    return "draggable" in div || "dragDrop" in div;
 20.4207 -  }();
 20.4208 -
 20.4209 -  // For a reason I have yet to figure out, some browsers disallow
 20.4210 -  // word wrapping between certain characters *only* if a new inline
 20.4211 -  // element is started between them. This makes it hard to reliably
 20.4212 -  // measure the position of things, since that requires inserting an
 20.4213 -  // extra span. This terribly fragile set of regexps matches the
 20.4214 -  // character combinations that suffer from this phenomenon on the
 20.4215 -  // various browsers.
 20.4216 -  var spanAffectsWrapping = /^$/; // Won't match any two-character string
 20.4217 -  if (gecko) spanAffectsWrapping = /$'/;
 20.4218 -  else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
 20.4219 -  else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
 20.4220 -
 20.4221 -  var knownScrollbarWidth;
 20.4222 -  function scrollbarWidth(measure) {
 20.4223 -    if (knownScrollbarWidth != null) return knownScrollbarWidth;
 20.4224 -    var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
 20.4225 -    removeChildrenAndAdd(measure, test);
 20.4226 -    if (test.offsetWidth)
 20.4227 -      knownScrollbarWidth = test.offsetHeight - test.clientHeight;
 20.4228 -    return knownScrollbarWidth || 0;
 20.4229 -  }
 20.4230 -
 20.4231 -  var zwspSupported;
 20.4232 -  function zeroWidthElement(measure) {
 20.4233 -    if (zwspSupported == null) {
 20.4234 -      var test = elt("span", "\u200b");
 20.4235 -      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
 20.4236 -      if (measure.firstChild.offsetHeight != 0)
 20.4237 -        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
 20.4238 -    }
 20.4239 -    if (zwspSupported) return elt("span", "\u200b");
 20.4240 -    else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
 20.4241 -  }
 20.4242 -
 20.4243 -  // See if "".split is the broken IE version, if so, provide an
 20.4244 -  // alternative way to split lines.
 20.4245 -  var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
 20.4246 -    var pos = 0, result = [], l = string.length;
 20.4247 -    while (pos <= l) {
 20.4248 -      var nl = string.indexOf("\n", pos);
 20.4249 -      if (nl == -1) nl = string.length;
 20.4250 -      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
 20.4251 -      var rt = line.indexOf("\r");
 20.4252 -      if (rt != -1) {
 20.4253 -        result.push(line.slice(0, rt));
 20.4254 -        pos += rt + 1;
 20.4255 -      } else {
 20.4256 -        result.push(line);
 20.4257 -        pos = nl + 1;
 20.4258 -      }
 20.4259 -    }
 20.4260 -    return result;
 20.4261 -  } : function(string){return string.split(/\r\n?|\n/);};
 20.4262 -  CodeMirror.splitLines = splitLines;
 20.4263 -
 20.4264 -  var hasSelection = window.getSelection ? function(te) {
 20.4265 -    try { return te.selectionStart != te.selectionEnd; }
 20.4266 -    catch(e) { return false; }
 20.4267 -  } : function(te) {
 20.4268 -    try {var range = te.ownerDocument.selection.createRange();}
 20.4269 -    catch(e) {}
 20.4270 -    if (!range || range.parentElement() != te) return false;
 20.4271 -    return range.compareEndPoints("StartToEnd", range) != 0;
 20.4272 -  };
 20.4273 -
 20.4274 -  var hasCopyEvent = (function() {
 20.4275 -    var e = elt("div");
 20.4276 -    if ("oncopy" in e) return true;
 20.4277 -    e.setAttribute("oncopy", "return;");
 20.4278 -    return typeof e.oncopy == 'function';
 20.4279 -  })();
 20.4280 -
 20.4281 -  // KEY NAMING
 20.4282 -
 20.4283 -  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
 20.4284 -                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
 20.4285 -                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
 20.4286 -                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
 20.4287 -                  186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
 20.4288 -                  221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
 20.4289 -                  63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
 20.4290 -  CodeMirror.keyNames = keyNames;
 20.4291 -  (function() {
 20.4292 -    // Number keys
 20.4293 -    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
 20.4294 -    // Alphabetic keys
 20.4295 -    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
 20.4296 -    // Function keys
 20.4297 -    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
 20.4298 -  })();
 20.4299 -
 20.4300 -  // BIDI HELPERS
 20.4301 -
 20.4302 -  function iterateBidiSections(order, from, to, f) {
 20.4303 -    if (!order) return f(from, to, "ltr");
 20.4304 -    for (var i = 0; i < order.length; ++i) {
 20.4305 -      var part = order[i];
 20.4306 -      if (part.from < to && part.to > from)
 20.4307 -        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
 20.4308 -    }
 20.4309 -  }
 20.4310 -
 20.4311 -  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
 20.4312 -  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
 20.4313 -
 20.4314 -  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
 20.4315 -  function lineRight(line) {
 20.4316 -    var order = getOrder(line);
 20.4317 -    if (!order) return line.text.length;
 20.4318 -    return bidiRight(lst(order));
 20.4319 -  }
 20.4320 -
 20.4321 -  function lineStart(cm, lineN) {
 20.4322 -    var line = getLine(cm.view.doc, lineN);
 20.4323 -    var visual = visualLine(cm.view.doc, line);
 20.4324 -    if (visual != line) lineN = lineNo(visual);
 20.4325 -    var order = getOrder(visual);
 20.4326 -    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
 20.4327 -    return {line: lineN, ch: ch};
 20.4328 -  }
 20.4329 -  function lineEnd(cm, lineNo) {
 20.4330 -    var merged, line;
 20.4331 -    while (merged = collapsedSpanAtEnd(line = getLine(cm.view.doc, lineNo)))
 20.4332 -      lineNo = merged.find().to.line;
 20.4333 -    var order = getOrder(line);
 20.4334 -    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
 20.4335 -    return {line: lineNo, ch: ch};
 20.4336 -  }
 20.4337 -
 20.4338 -  // This is somewhat involved. It is needed in order to move
 20.4339 -  // 'visually' through bi-directional text -- i.e., pressing left
 20.4340 -  // should make the cursor go left, even when in RTL text. The
 20.4341 -  // tricky part is the 'jumps', where RTL and LTR text touch each
 20.4342 -  // other. This often requires the cursor offset to move more than
 20.4343 -  // one unit, in order to visually move one unit.
 20.4344 -  function moveVisually(line, start, dir, byUnit) {
 20.4345 -    var bidi = getOrder(line);
 20.4346 -    if (!bidi) return moveLogically(line, start, dir, byUnit);
 20.4347 -    var moveOneUnit = byUnit ? function(pos, dir) {
 20.4348 -      do pos += dir;
 20.4349 -      while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
 20.4350 -      return pos;
 20.4351 -    } : function(pos, dir) { return pos + dir; };
 20.4352 -    var linedir = bidi[0].level;
 20.4353 -    for (var i = 0; i < bidi.length; ++i) {
 20.4354 -      var part = bidi[i], sticky = part.level % 2 == linedir;
 20.4355 -      if ((part.from < start && part.to > start) ||
 20.4356 -          (sticky && (part.from == start || part.to == start))) break;
 20.4357 -    }
 20.4358 -    var target = moveOneUnit(start, part.level % 2 ? -dir : dir);
 20.4359 -
 20.4360 -    while (target != null) {
 20.4361 -      if (part.level % 2 == linedir) {
 20.4362 -        if (target < part.from || target > part.to) {
 20.4363 -          part = bidi[i += dir];
 20.4364 -          target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1));
 20.4365 -        } else break;
 20.4366 -      } else {
 20.4367 -        if (target == bidiLeft(part)) {
 20.4368 -          part = bidi[--i];
 20.4369 -          target = part && bidiRight(part);
 20.4370 -        } else if (target == bidiRight(part)) {
 20.4371 -          part = bidi[++i];
 20.4372 -          target = part && bidiLeft(part);
 20.4373 -        } else break;
 20.4374 -      }
 20.4375 -    }
 20.4376 -
 20.4377 -    return target < 0 || target > line.text.length ? null : target;
 20.4378 -  }
 20.4379 -
 20.4380 -  function moveLogically(line, start, dir, byUnit) {
 20.4381 -    var target = start + dir;
 20.4382 -    if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
 20.4383 -    return target < 0 || target > line.text.length ? null : target;
 20.4384 -  }
 20.4385 -
 20.4386 -  // Bidirectional ordering algorithm
 20.4387 -  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
 20.4388 -  // that this (partially) implements.
 20.4389 -
 20.4390 -  // One-char codes used for character types:
 20.4391 -  // L (L):   Left-to-Right
 20.4392 -  // R (R):   Right-to-Left
 20.4393 -  // r (AL):  Right-to-Left Arabic
 20.4394 -  // 1 (EN):  European Number
 20.4395 -  // + (ES):  European Number Separator
 20.4396 -  // % (ET):  European Number Terminator
 20.4397 -  // n (AN):  Arabic Number
 20.4398 -  // , (CS):  Common Number Separator
 20.4399 -  // m (NSM): Non-Spacing Mark
 20.4400 -  // b (BN):  Boundary Neutral
 20.4401 -  // s (B):   Paragraph Separator
 20.4402 -  // t (S):   Segment Separator
 20.4403 -  // w (WS):  Whitespace
 20.4404 -  // N (ON):  Other Neutrals
 20.4405 -
 20.4406 -  // Returns null if characters are ordered as they appear
 20.4407 -  // (left-to-right), or an array of sections ({from, to, level}
 20.4408 -  // objects) in the order in which they occur visually.
 20.4409 -  var bidiOrdering = (function() {
 20.4410 -    // Character types for codepoints 0 to 0xff
 20.4411 -    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
 20.4412 -    // Character types for codepoints 0x600 to 0x6ff
 20.4413 -    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
 20.4414 -    function charType(code) {
 20.4415 -      if (code <= 0xff) return lowTypes.charAt(code);
 20.4416 -      else if (0x590 <= code && code <= 0x5f4) return "R";
 20.4417 -      else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
 20.4418 -      else if (0x700 <= code && code <= 0x8ac) return "r";
 20.4419 -      else return "L";
 20.4420 -    }
 20.4421 -
 20.4422 -    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
 20.4423 -    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
 20.4424 -
 20.4425 -    return function charOrdering(str) {
 20.4426 -      if (!bidiRE.test(str)) return false;
 20.4427 -      var len = str.length, types = [], startType = null;
 20.4428 -      for (var i = 0, type; i < len; ++i) {
 20.4429 -        types.push(type = charType(str.charCodeAt(i)));
 20.4430 -        if (startType == null) {
 20.4431 -          if (type == "L") startType = "L";
 20.4432 -          else if (type == "R" || type == "r") startType = "R";
 20.4433 -        }
 20.4434 -      }
 20.4435 -      if (startType == null) startType = "L";
 20.4436 -
 20.4437 -      // W1. Examine each non-spacing mark (NSM) in the level run, and
 20.4438 -      // change the type of the NSM to the type of the previous
 20.4439 -      // character. If the NSM is at the start of the level run, it will
 20.4440 -      // get the type of sor.
 20.4441 -      for (var i = 0, prev = startType; i < len; ++i) {
 20.4442 -        var type = types[i];
 20.4443 -        if (type == "m") types[i] = prev;
 20.4444 -        else prev = type;
 20.4445 -      }
 20.4446 -
 20.4447 -      // W2. Search backwards from each instance of a European number
 20.4448 -      // until the first strong type (R, L, AL, or sor) is found. If an
 20.4449 -      // AL is found, change the type of the European number to Arabic
 20.4450 -      // number.
 20.4451 -      // W3. Change all ALs to R.
 20.4452 -      for (var i = 0, cur = startType; i < len; ++i) {
 20.4453 -        var type = types[i];
 20.4454 -        if (type == "1" && cur == "r") types[i] = "n";
 20.4455 -        else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
 20.4456 -      }
 20.4457 -
 20.4458 -      // W4. A single European separator between two European numbers
 20.4459 -      // changes to a European number. A single common separator between
 20.4460 -      // two numbers of the same type changes to that type.
 20.4461 -      for (var i = 1, prev = types[0]; i < len - 1; ++i) {
 20.4462 -        var type = types[i];
 20.4463 -        if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
 20.4464 -        else if (type == "," && prev == types[i+1] &&
 20.4465 -                 (prev == "1" || prev == "n")) types[i] = prev;
 20.4466 -        prev = type;
 20.4467 -      }
 20.4468 -
 20.4469 -      // W5. A sequence of European terminators adjacent to European
 20.4470 -      // numbers changes to all European numbers.
 20.4471 -      // W6. Otherwise, separators and terminators change to Other
 20.4472 -      // Neutral.
 20.4473 -      for (var i = 0; i < len; ++i) {
 20.4474 -        var type = types[i];
 20.4475 -        if (type == ",") types[i] = "N";
 20.4476 -        else if (type == "%") {
 20.4477 -          for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
 20.4478 -          var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
 20.4479 -          for (var j = i; j < end; ++j) types[j] = replace;
 20.4480 -          i = end - 1;
 20.4481 -        }
 20.4482 -      }
 20.4483 -
 20.4484 -      // W7. Search backwards from each instance of a European number
 20.4485 -      // until the first strong type (R, L, or sor) is found. If an L is
 20.4486 -      // found, then change the type of the European number to L.
 20.4487 -      for (var i = 0, cur = startType; i < len; ++i) {
 20.4488 -        var type = types[i];
 20.4489 -        if (cur == "L" && type == "1") types[i] = "L";
 20.4490 -        else if (isStrong.test(type)) cur = type;
 20.4491 -      }
 20.4492 -
 20.4493 -      // N1. A sequence of neutrals takes the direction of the
 20.4494 -      // surrounding strong text if the text on both sides has the same
 20.4495 -      // direction. European and Arabic numbers act as if they were R in
 20.4496 -      // terms of their influence on neutrals. Start-of-level-run (sor)
 20.4497 -      // and end-of-level-run (eor) are used at level run boundaries.
 20.4498 -      // N2. Any remaining neutrals take the embedding direction.
 20.4499 -      for (var i = 0; i < len; ++i) {
 20.4500 -        if (isNeutral.test(types[i])) {
 20.4501 -          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
 20.4502 -          var before = (i ? types[i-1] : startType) == "L";
 20.4503 -          var after = (end < len - 1 ? types[end] : startType) == "L";
 20.4504 -          var replace = before || after ? "L" : "R";
 20.4505 -          for (var j = i; j < end; ++j) types[j] = replace;
 20.4506 -          i = end - 1;
 20.4507 -        }
 20.4508 -      }
 20.4509 -
 20.4510 -      // Here we depart from the documented algorithm, in order to avoid
 20.4511 -      // building up an actual levels array. Since there are only three
 20.4512 -      // levels (0, 1, 2) in an implementation that doesn't take
 20.4513 -      // explicit embedding into account, we can build up the order on
 20.4514 -      // the fly, without following the level-based algorithm.
 20.4515 -      var order = [], m;
 20.4516 -      for (var i = 0; i < len;) {
 20.4517 -        if (countsAsLeft.test(types[i])) {
 20.4518 -          var start = i;
 20.4519 -          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
 20.4520 -          order.push({from: start, to: i, level: 0});
 20.4521 -        } else {
 20.4522 -          var pos = i, at = order.length;
 20.4523 -          for (++i; i < len && types[i] != "L"; ++i) {}
 20.4524 -          for (var j = pos; j < i;) {
 20.4525 -            if (countsAsNum.test(types[j])) {
 20.4526 -              if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
 20.4527 -              var nstart = j;
 20.4528 -              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
 20.4529 -              order.splice(at, 0, {from: nstart, to: j, level: 2});
 20.4530 -              pos = j;
 20.4531 -            } else ++j;
 20.4532 -          }
 20.4533 -          if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
 20.4534 -        }
 20.4535 -      }
 20.4536 -      if (order[0].level == 1 && (m = str.match(/^\s+/))) {
 20.4537 -        order[0].from = m[0].length;
 20.4538 -        order.unshift({from: 0, to: m[0].length, level: 0});
 20.4539 -      }
 20.4540 -      if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
 20.4541 -        lst(order).to -= m[0].length;
 20.4542 -        order.push({from: len - m[0].length, to: len, level: 0});
 20.4543 -      }
 20.4544 -      if (order[0].level != lst(order).level)
 20.4545 -        order.push({from: len, to: len, level: order[0].level});
 20.4546 -
 20.4547 -      return order;
 20.4548 -    };
 20.4549 -  })();
 20.4550 -
 20.4551 -  // THE END
 20.4552 -
 20.4553 -  CodeMirror.version = "3.0";
 20.4554 -
 20.4555 -  return CodeMirror;
 20.4556 -})();
    21.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js	Tue Apr 29 15:25:58 2014 +0200
    21.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.3 @@ -1,300 +0,0 @@
    21.4 -CodeMirror.defineMode("clike", function(config, parserConfig) {
    21.5 -  var indentUnit = config.indentUnit,
    21.6 -      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
    21.7 -      keywords = parserConfig.keywords || {},
    21.8 -      builtin = parserConfig.builtin || {},
    21.9 -      blockKeywords = parserConfig.blockKeywords || {},
   21.10 -      atoms = parserConfig.atoms || {},
   21.11 -      hooks = parserConfig.hooks || {},
   21.12 -      multiLineStrings = parserConfig.multiLineStrings;
   21.13 -  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
   21.14 -
   21.15 -  var curPunc;
   21.16 -
   21.17 -  function tokenBase(stream, state) {
   21.18 -    var ch = stream.next();
   21.19 -    if (hooks[ch]) {
   21.20 -      var result = hooks[ch](stream, state);
   21.21 -      if (result !== false) return result;
   21.22 -    }
   21.23 -    if (ch == '"' || ch == "'") {
   21.24 -      state.tokenize = tokenString(ch);
   21.25 -      return state.tokenize(stream, state);
   21.26 -    }
   21.27 -    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
   21.28 -      curPunc = ch;
   21.29 -      return null;
   21.30 -    }
   21.31 -    if (/\d/.test(ch)) {
   21.32 -      stream.eatWhile(/[\w\.]/);
   21.33 -      return "number";
   21.34 -    }
   21.35 -    if (ch == "/") {
   21.36 -      if (stream.eat("*")) {
   21.37 -        state.tokenize = tokenComment;
   21.38 -        return tokenComment(stream, state);
   21.39 -      }
   21.40 -      if (stream.eat("/")) {
   21.41 -        stream.skipToEnd();
   21.42 -        return "comment";
   21.43 -      }
   21.44 -    }
   21.45 -    if (isOperatorChar.test(ch)) {
   21.46 -      stream.eatWhile(isOperatorChar);
   21.47 -      return "operator";
   21.48 -    }
   21.49 -    stream.eatWhile(/[\w\$_]/);
   21.50 -    var cur = stream.current();
   21.51 -    if (keywords.propertyIsEnumerable(cur)) {
   21.52 -      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
   21.53 -      return "keyword";
   21.54 -    }
   21.55 -    if (builtin.propertyIsEnumerable(cur)) {
   21.56 -      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
   21.57 -      return "builtin";
   21.58 -    }
   21.59 -    if (atoms.propertyIsEnumerable(cur)) return "atom";
   21.60 -    return "variable";
   21.61 -  }
   21.62 -
   21.63 -  function tokenString(quote) {
   21.64 -    return function(stream, state) {
   21.65 -      var escaped = false, next, end = false;
   21.66 -      while ((next = stream.next()) != null) {
   21.67 -        if (next == quote && !escaped) {end = true; break;}
   21.68 -        escaped = !escaped && next == "\\";
   21.69 -      }
   21.70 -      if (end || !(escaped || multiLineStrings))
   21.71 -        state.tokenize = null;
   21.72 -      return "string";
   21.73 -    };
   21.74 -  }
   21.75 -
   21.76 -  function tokenComment(stream, state) {
   21.77 -    var maybeEnd = false, ch;
   21.78 -    while (ch = stream.next()) {
   21.79 -      if (ch == "/" && maybeEnd) {
   21.80 -        state.tokenize = null;
   21.81 -        break;
   21.82 -      }
   21.83 -      maybeEnd = (ch == "*");
   21.84 -    }
   21.85 -    return "comment";
   21.86 -  }
   21.87 -
   21.88 -  function Context(indented, column, type, align, prev) {
   21.89 -    this.indented = indented;
   21.90 -    this.column = column;
   21.91 -    this.type = type;
   21.92 -    this.align = align;
   21.93 -    this.prev = prev;
   21.94 -  }
   21.95 -  function pushContext(state, col, type) {
   21.96 -    var indent = state.indented;
   21.97 -    if (state.context && state.context.type == "statement")
   21.98 -      indent = state.context.indented;
   21.99 -    return state.context = new Context(indent, col, type, null, state.context);
  21.100 -  }
  21.101 -  function popContext(state) {
  21.102 -    var t = state.context.type;
  21.103 -    if (t == ")" || t == "]" || t == "}")
  21.104 -      state.indented = state.context.indented;
  21.105 -    return state.context = state.context.prev;
  21.106 -  }
  21.107 -
  21.108 -  // Interface
  21.109 -
  21.110 -  return {
  21.111 -    startState: function(basecolumn) {
  21.112 -      return {
  21.113 -        tokenize: null,
  21.114 -        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
  21.115 -        indented: 0,
  21.116 -        startOfLine: true
  21.117 -      };
  21.118 -    },
  21.119 -
  21.120 -    token: function(stream, state) {
  21.121 -      var ctx = state.context;
  21.122 -      if (stream.sol()) {
  21.123 -        if (ctx.align == null) ctx.align = false;
  21.124 -        state.indented = stream.indentation();
  21.125 -        state.startOfLine = true;
  21.126 -      }
  21.127 -      if (stream.eatSpace()) return null;
  21.128 -      curPunc = null;
  21.129 -      var style = (state.tokenize || tokenBase)(stream, state);
  21.130 -      if (style == "comment" || style == "meta") return style;
  21.131 -      if (ctx.align == null) ctx.align = true;
  21.132 -
  21.133 -      if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
  21.134 -      else if (curPunc == "{") pushContext(state, stream.column(), "}");
  21.135 -      else if (curPunc == "[") pushContext(state, stream.column(), "]");
  21.136 -      else if (curPunc == "(") pushContext(state, stream.column(), ")");
  21.137 -      else if (curPunc == "}") {
  21.138 -        while (ctx.type == "statement") ctx = popContext(state);
  21.139 -        if (ctx.type == "}") ctx = popContext(state);
  21.140 -        while (ctx.type == "statement") ctx = popContext(state);
  21.141 -      }
  21.142 -      else if (curPunc == ctx.type) popContext(state);
  21.143 -      else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
  21.144 -        pushContext(state, stream.column(), "statement");
  21.145 -      state.startOfLine = false;
  21.146 -      return style;
  21.147 -    },
  21.148 -
  21.149 -    indent: function(state, textAfter) {
  21.150 -      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
  21.151 -      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
  21.152 -      if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
  21.153 -      var closing = firstChar == ctx.type;
  21.154 -      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
  21.155 -      else if (ctx.align) return ctx.column + (closing ? 0 : 1);
  21.156 -      else return ctx.indented + (closing ? 0 : indentUnit);
  21.157 -    },
  21.158 -
  21.159 -    electricChars: "{}"
  21.160 -  };
  21.161 -});
  21.162 -
  21.163 -(function() {
  21.164 -  function words(str) {
  21.165 -    var obj = {}, words = str.split(" ");
  21.166 -    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
  21.167 -    return obj;
  21.168 -  }
  21.169 -  var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
  21.170 -    "double static else struct entry switch extern typedef float union for unsigned " +
  21.171 -    "goto while enum void const signed volatile";
  21.172 -
  21.173 -  function cppHook(stream, state) {
  21.174 -    if (!state.startOfLine) return false;
  21.175 -    for (;;) {
  21.176 -      if (stream.skipTo("\\")) {
  21.177 -        stream.next();
  21.178 -        if (stream.eol()) {
  21.179 -          state.tokenize = cppHook;
  21.180 -          break;
  21.181 -        }
  21.182 -      } else {
  21.183 -        stream.skipToEnd();
  21.184 -        state.tokenize = null;
  21.185 -        break;
  21.186 -      }
  21.187 -    }
  21.188 -    return "meta";
  21.189 -  }
  21.190 -
  21.191 -  // C#-style strings where "" escapes a quote.
  21.192 -  function tokenAtString(stream, state) {
  21.193 -    var next;
  21.194 -    while ((next = stream.next()) != null) {
  21.195 -      if (next == '"' && !stream.eat('"')) {
  21.196 -        state.tokenize = null;
  21.197 -        break;
  21.198 -      }
  21.199 -    }
  21.200 -    return "string";
  21.201 -  }
  21.202 -
  21.203 -  function mimes(ms, mode) {
  21.204 -    for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
  21.205 -  }
  21.206 -
  21.207 -  mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
  21.208 -    name: "clike",
  21.209 -    keywords: words(cKeywords),
  21.210 -    blockKeywords: words("case do else for if switch while struct"),
  21.211 -    atoms: words("null"),
  21.212 -    hooks: {"#": cppHook}
  21.213 -  });
  21.214 -  mimes(["text/x-c++src", "text/x-c++hdr"], {
  21.215 -    name: "clike",
  21.216 -    keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
  21.217 -                    "static_cast typeid catch operator template typename class friend private " +
  21.218 -                    "this using const_cast inline public throw virtual delete mutable protected " +
  21.219 -                    "wchar_t"),
  21.220 -    blockKeywords: words("catch class do else finally for if struct switch try while"),
  21.221 -    atoms: words("true false null"),
  21.222 -    hooks: {"#": cppHook}
  21.223 -  });
  21.224 -  CodeMirror.defineMIME("text/x-java", {
  21.225 -    name: "clike",
  21.226 -    keywords: words("abstract assert boolean break byte case catch char class const continue default " + 
  21.227 -                    "do double else enum extends final finally float for goto if implements import " +
  21.228 -                    "instanceof int interface long native new package private protected public " +
  21.229 -                    "return short static strictfp super switch synchronized this throw throws transient " +
  21.230 -                    "try void volatile while"),
  21.231 -    blockKeywords: words("catch class do else finally for if switch try while"),
  21.232 -    atoms: words("true false null"),
  21.233 -    hooks: {
  21.234 -      "@": function(stream) {
  21.235 -        stream.eatWhile(/[\w\$_]/);
  21.236 -        return "meta";
  21.237 -      }
  21.238 -    }
  21.239 -  });
  21.240 -  CodeMirror.defineMIME("text/x-csharp", {
  21.241 -    name: "clike",
  21.242 -    keywords: words("abstract as base break case catch checked class const continue" + 
  21.243 -                    " default delegate do else enum event explicit extern finally fixed for" + 
  21.244 -                    " foreach goto if implicit in interface internal is lock namespace new" + 
  21.245 -                    " operator out override params private protected public readonly ref return sealed" + 
  21.246 -                    " sizeof stackalloc static struct switch this throw try typeof unchecked" + 
  21.247 -                    " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + 
  21.248 -                    " global group into join let orderby partial remove select set value var yield"),
  21.249 -    blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
  21.250 -    builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
  21.251 -                    " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
  21.252 -                    " UInt64 bool byte char decimal double short int long object"  +
  21.253 -                    " sbyte float string ushort uint ulong"),
  21.254 -    atoms: words("true false null"),
  21.255 -    hooks: {
  21.256 -      "@": function(stream, state) {
  21.257 -        if (stream.eat('"')) {
  21.258 -          state.tokenize = tokenAtString;
  21.259 -          return tokenAtString(stream, state);
  21.260 -        }
  21.261 -        stream.eatWhile(/[\w\$_]/);
  21.262 -        return "meta";
  21.263 -      }
  21.264 -    }
  21.265 -  });
  21.266 -  CodeMirror.defineMIME("text/x-scala", {
  21.267 -    name: "clike",
  21.268 -    keywords: words(
  21.269 -      
  21.270 -      /* scala */
  21.271 -      "abstract case catch class def do else extends false final finally for forSome if " +
  21.272 -      "implicit import lazy match new null object override package private protected return " +
  21.273 -      "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
  21.274 -      "<% >: # @ " +
  21.275 -                    
  21.276 -      /* package scala */
  21.277 -      "assert assume require print println printf readLine readBoolean readByte readShort " +
  21.278 -      "readChar readInt readLong readFloat readDouble " +
  21.279 -      
  21.280 -      "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
  21.281 -      "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
  21.282 -      "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
  21.283 -      "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
  21.284 -      "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
  21.285 -      
  21.286 -      /* package java.lang */            
  21.287 -      "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
  21.288 -      "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
  21.289 -      "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
  21.290 -      "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
  21.291 -      
  21.292 -      
  21.293 -    ),
  21.294 -    blockKeywords: words("catch class do else finally for forSome if match switch try while"),
  21.295 -    atoms: words("true false null"),
  21.296 -    hooks: {
  21.297 -      "@": function(stream) {
  21.298 -        stream.eatWhile(/[\w\$_]/);
  21.299 -        return "meta";
  21.300 -      }
  21.301 -    }
  21.302 -  });
  21.303 -}());
    22.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js	Tue Apr 29 15:25:58 2014 +0200
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,324 +0,0 @@
    22.4 -CodeMirror.defineMode("xml", function(config, parserConfig) {
    22.5 -  var indentUnit = config.indentUnit;
    22.6 -  var Kludges = parserConfig.htmlMode ? {
    22.7 -    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
    22.8 -                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
    22.9 -                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
   22.10 -                      'track': true, 'wbr': true},
   22.11 -    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
   22.12 -                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
   22.13 -                       'th': true, 'tr': true},
   22.14 -    contextGrabbers: {
   22.15 -      'dd': {'dd': true, 'dt': true},
   22.16 -      'dt': {'dd': true, 'dt': true},
   22.17 -      'li': {'li': true},
   22.18 -      'option': {'option': true, 'optgroup': true},
   22.19 -      'optgroup': {'optgroup': true},
   22.20 -      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
   22.21 -            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
   22.22 -            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
   22.23 -            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
   22.24 -            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
   22.25 -      'rp': {'rp': true, 'rt': true},
   22.26 -      'rt': {'rp': true, 'rt': true},
   22.27 -      'tbody': {'tbody': true, 'tfoot': true},
   22.28 -      'td': {'td': true, 'th': true},
   22.29 -      'tfoot': {'tbody': true},
   22.30 -      'th': {'td': true, 'th': true},
   22.31 -      'thead': {'tbody': true, 'tfoot': true},
   22.32 -      'tr': {'tr': true}
   22.33 -    },
   22.34 -    doNotIndent: {"pre": true},
   22.35 -    allowUnquoted: true,
   22.36 -    allowMissing: true
   22.37 -  } : {
   22.38 -    autoSelfClosers: {},
   22.39 -    implicitlyClosed: {},
   22.40 -    contextGrabbers: {},
   22.41 -    doNotIndent: {},
   22.42 -    allowUnquoted: false,
   22.43 -    allowMissing: false
   22.44 -  };
   22.45 -  var alignCDATA = parserConfig.alignCDATA;
   22.46 -
   22.47 -  // Return variables for tokenizers
   22.48 -  var tagName, type;
   22.49 -
   22.50 -  function inText(stream, state) {
   22.51 -    function chain(parser) {
   22.52 -      state.tokenize = parser;
   22.53 -      return parser(stream, state);
   22.54 -    }
   22.55 -
   22.56 -    var ch = stream.next();
   22.57 -    if (ch == "<") {
   22.58 -      if (stream.eat("!")) {
   22.59 -        if (stream.eat("[")) {
   22.60 -          if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
   22.61 -          else return null;
   22.62 -        }
   22.63 -        else if (stream.match("--")) return chain(inBlock("comment", "-->"));
   22.64 -        else if (stream.match("DOCTYPE", true, true)) {
   22.65 -          stream.eatWhile(/[\w\._\-]/);
   22.66 -          return chain(doctype(1));
   22.67 -        }
   22.68 -        else return null;
   22.69 -      }
   22.70 -      else if (stream.eat("?")) {
   22.71 -        stream.eatWhile(/[\w\._\-]/);
   22.72 -        state.tokenize = inBlock("meta", "?>");
   22.73 -        return "meta";
   22.74 -      }
   22.75 -      else {
   22.76 -        var isClose = stream.eat("/");
   22.77 -        tagName = "";
   22.78 -        var c;
   22.79 -        while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
   22.80 -        if (!tagName) return "error";
   22.81 -        type = isClose ? "closeTag" : "openTag";
   22.82 -        state.tokenize = inTag;
   22.83 -        return "tag";
   22.84 -      }
   22.85 -    }
   22.86 -    else if (ch == "&") {
   22.87 -      var ok;
   22.88 -      if (stream.eat("#")) {
   22.89 -        if (stream.eat("x")) {
   22.90 -          ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");          
   22.91 -        } else {
   22.92 -          ok = stream.eatWhile(/[\d]/) && stream.eat(";");
   22.93 -        }
   22.94 -      } else {
   22.95 -        ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
   22.96 -      }
   22.97 -      return ok ? "atom" : "error";
   22.98 -    }
   22.99 -    else {
  22.100 -      stream.eatWhile(/[^&<]/);
  22.101 -      return null;
  22.102 -    }
  22.103 -  }
  22.104 -
  22.105 -  function inTag(stream, state) {
  22.106 -    var ch = stream.next();
  22.107 -    if (ch == ">" || (ch == "/" && stream.eat(">"))) {
  22.108 -      state.tokenize = inText;
  22.109 -      type = ch == ">" ? "endTag" : "selfcloseTag";
  22.110 -      return "tag";
  22.111 -    }
  22.112 -    else if (ch == "=") {
  22.113 -      type = "equals";
  22.114 -      return null;
  22.115 -    }
  22.116 -    else if (/[\'\"]/.test(ch)) {
  22.117 -      state.tokenize = inAttribute(ch);
  22.118 -      return state.tokenize(stream, state);
  22.119 -    }
  22.120 -    else {
  22.121 -      stream.eatWhile(/[^\s\u00a0=<>\"\']/);
  22.122 -      return "word";
  22.123 -    }
  22.124 -  }
  22.125 -
  22.126 -  function inAttribute(quote) {
  22.127 -    return function(stream, state) {
  22.128 -      while (!stream.eol()) {
  22.129 -        if (stream.next() == quote) {
  22.130 -          state.tokenize = inTag;
  22.131 -          break;
  22.132 -        }
  22.133 -      }
  22.134 -      return "string";
  22.135 -    };
  22.136 -  }
  22.137 -
  22.138 -  function inBlock(style, terminator) {
  22.139 -    return function(stream, state) {
  22.140 -      while (!stream.eol()) {
  22.141 -        if (stream.match(terminator)) {
  22.142 -          state.tokenize = inText;
  22.143 -          break;
  22.144 -        }
  22.145 -        stream.next();
  22.146 -      }
  22.147 -      return style;
  22.148 -    };
  22.149 -  }
  22.150 -  function doctype(depth) {
  22.151 -    return function(stream, state) {
  22.152 -      var ch;
  22.153 -      while ((ch = stream.next()) != null) {
  22.154 -        if (ch == "<") {
  22.155 -          state.tokenize = doctype(depth + 1);
  22.156 -          return state.tokenize(stream, state);
  22.157 -        } else if (ch == ">") {
  22.158 -          if (depth == 1) {
  22.159 -            state.tokenize = inText;
  22.160 -            break;
  22.161 -          } else {
  22.162 -            state.tokenize = doctype(depth - 1);
  22.163 -            return state.tokenize(stream, state);
  22.164 -          }
  22.165 -        }
  22.166 -      }
  22.167 -      return "meta";
  22.168 -    };
  22.169 -  }
  22.170 -
  22.171 -  var curState, setStyle;
  22.172 -  function pass() {
  22.173 -    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
  22.174 -  }
  22.175 -  function cont() {
  22.176 -    pass.apply(null, arguments);
  22.177 -    return true;
  22.178 -  }
  22.179 -
  22.180 -  function pushContext(tagName, startOfLine) {
  22.181 -    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
  22.182 -    curState.context = {
  22.183 -      prev: curState.context,
  22.184 -      tagName: tagName,
  22.185 -      indent: curState.indented,
  22.186 -      startOfLine: startOfLine,
  22.187 -      noIndent: noIndent
  22.188 -    };
  22.189 -  }
  22.190 -  function popContext() {
  22.191 -    if (curState.context) curState.context = curState.context.prev;
  22.192 -  }
  22.193 -
  22.194 -  function element(type) {
  22.195 -    if (type == "openTag") {
  22.196 -      curState.tagName = tagName;
  22.197 -      return cont(attributes, endtag(curState.startOfLine));
  22.198 -    } else if (type == "closeTag") {
  22.199 -      var err = false;
  22.200 -      if (curState.context) {
  22.201 -        if (curState.context.tagName != tagName) {
  22.202 -          if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
  22.203 -            popContext();
  22.204 -          }
  22.205 -          err = !curState.context || curState.context.tagName != tagName;
  22.206 -        }
  22.207 -      } else {
  22.208 -        err = true;
  22.209 -      }
  22.210 -      if (err) setStyle = "error";
  22.211 -      return cont(endclosetag(err));
  22.212 -    }
  22.213 -    return cont();
  22.214 -  }
  22.215 -  function endtag(startOfLine) {
  22.216 -    return function(type) {
  22.217 -      var tagName = curState.tagName;
  22.218 -      curState.tagName = null;
  22.219 -      if (type == "selfcloseTag" ||
  22.220 -          (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
  22.221 -        maybePopContext(tagName.toLowerCase());
  22.222 -        return cont();
  22.223 -      }
  22.224 -      if (type == "endTag") {
  22.225 -        maybePopContext(tagName.toLowerCase());
  22.226 -        pushContext(tagName, startOfLine);
  22.227 -        return cont();
  22.228 -      }
  22.229 -      return cont();
  22.230 -    };
  22.231 -  }
  22.232 -  function endclosetag(err) {
  22.233 -    return function(type) {
  22.234 -      if (err) setStyle = "error";
  22.235 -      if (type == "endTag") { popContext(); return cont(); }
  22.236 -      setStyle = "error";
  22.237 -      return cont(arguments.callee);
  22.238 -    };
  22.239 -  }
  22.240 -  function maybePopContext(nextTagName) {
  22.241 -    var parentTagName;
  22.242 -    while (true) {
  22.243 -      if (!curState.context) {
  22.244 -        return;
  22.245 -      }
  22.246 -      parentTagName = curState.context.tagName.toLowerCase();
  22.247 -      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
  22.248 -          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
  22.249 -        return;
  22.250 -      }
  22.251 -      popContext();
  22.252 -    }
  22.253 -  }
  22.254 -
  22.255 -  function attributes(type) {
  22.256 -    if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
  22.257 -    if (type == "endTag" || type == "selfcloseTag") return pass();
  22.258 -    setStyle = "error";
  22.259 -    return cont(attributes);
  22.260 -  }
  22.261 -  function attribute(type) {
  22.262 -    if (type == "equals") return cont(attvalue, attributes);
  22.263 -    if (!Kludges.allowMissing) setStyle = "error";
  22.264 -    else if (type == "word") setStyle = "attribute";
  22.265 -    return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
  22.266 -  }
  22.267 -  function attvalue(type) {
  22.268 -    if (type == "string") return cont(attvaluemaybe);
  22.269 -    if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
  22.270 -    setStyle = "error";
  22.271 -    return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
  22.272 -  }
  22.273 -  function attvaluemaybe(type) {
  22.274 -    if (type == "string") return cont(attvaluemaybe);
  22.275 -    else return pass();
  22.276 -  }
  22.277 -
  22.278 -  return {
  22.279 -    startState: function() {
  22.280 -      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
  22.281 -    },
  22.282 -
  22.283 -    token: function(stream, state) {
  22.284 -      if (stream.sol()) {
  22.285 -        state.startOfLine = true;
  22.286 -        state.indented = stream.indentation();
  22.287 -      }
  22.288 -      if (stream.eatSpace()) return null;
  22.289 -
  22.290 -      setStyle = type = tagName = null;
  22.291 -      var style = state.tokenize(stream, state);
  22.292 -      state.type = type;
  22.293 -      if ((style || type) && style != "comment") {
  22.294 -        curState = state;
  22.295 -        while (true) {
  22.296 -          var comb = state.cc.pop() || element;
  22.297 -          if (comb(type || style)) break;
  22.298 -        }
  22.299 -      }
  22.300 -      state.startOfLine = false;
  22.301 -      return setStyle || style;
  22.302 -    },
  22.303 -
  22.304 -    indent: function(state, textAfter, fullLine) {
  22.305 -      var context = state.context;
  22.306 -      if ((state.tokenize != inTag && state.tokenize != inText) ||
  22.307 -          context && context.noIndent)
  22.308 -        return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
  22.309 -      if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
  22.310 -      if (context && /^<\//.test(textAfter))
  22.311 -        context = context.prev;
  22.312 -      while (context && !context.startOfLine)
  22.313 -        context = context.prev;
  22.314 -      if (context) return context.indent + indentUnit;
  22.315 -      else return 0;
  22.316 -    },
  22.317 -
  22.318 -    electricChars: "/",
  22.319 -
  22.320 -    configuration: parserConfig.htmlMode ? "html" : "xml"
  22.321 -  };
  22.322 -});
  22.323 -
  22.324 -CodeMirror.defineMIME("text/xml", "xml");
  22.325 -CodeMirror.defineMIME("application/xml", "xml");
  22.326 -if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
  22.327 -  CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
    23.1 --- a/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/theme/elegant.css	Tue Apr 29 15:25:58 2014 +0200
    23.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.3 @@ -1,10 +0,0 @@
    23.4 -.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
    23.5 -.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
    23.6 -.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
    23.7 -.cm-s-elegant span.cm-variable {color: black;}
    23.8 -.cm-s-elegant span.cm-variable-2 {color: #b11;}
    23.9 -.cm-s-elegant span.cm-qualifier {color: #555;}
   23.10 -.cm-s-elegant span.cm-keyword {color: #730;}
   23.11 -.cm-s-elegant span.cm-builtin {color: #30a;}
   23.12 -.cm-s-elegant span.cm-error {background-color: #fdd;}
   23.13 -.cm-s-elegant span.cm-link {color: #762;}
    24.1 --- a/dew/src/test/java/org/apidesign/bck2brwsr/dew/CompileTest.java	Tue Apr 29 15:25:58 2014 +0200
    24.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.3 @@ -1,45 +0,0 @@
    24.4 -/**
    24.5 - * Back 2 Browser Bytecode Translator
    24.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    24.7 - *
    24.8 - * This program is free software: you can redistribute it and/or modify
    24.9 - * it under the terms of the GNU General Public License as published by
   24.10 - * the Free Software Foundation, version 2 of the License.
   24.11 - *
   24.12 - * This program is distributed in the hope that it will be useful,
   24.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.15 - * GNU General Public License for more details.
   24.16 - *
   24.17 - * You should have received a copy of the GNU General Public License
   24.18 - * along with this program. Look for COPYING file in the top folder.
   24.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   24.20 - */
   24.21 -package org.apidesign.bck2brwsr.dew;
   24.22 -
   24.23 -import java.io.IOException;
   24.24 -import static org.testng.Assert.*;
   24.25 -import org.testng.annotations.Test;
   24.26 -
   24.27 -/**
   24.28 - *
   24.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   24.30 - */
   24.31 -public class CompileTest  {
   24.32 -    @Test public void testCompile() throws IOException {
   24.33 -        String html = "<html><body>"
   24.34 -                + " <button id='btn'>Hello!</button>"
   24.35 -                + "</body></html>";
   24.36 -        String java = "package x.y.z;"
   24.37 -                + "import org.apidesign.bck2brwsr.htmlpage.api.*;"
   24.38 -                + "import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;"
   24.39 -            + "@Page(xhtml=\"index.html\", className=\"Index\")"
   24.40 -            + "class X { "
   24.41 -            + "   @On(event=CLICK, id=\"btn\") static void clcs() {}"
   24.42 -            + "}";
   24.43 -        Compile result = Compile.create(html, java);
   24.44 -
   24.45 -        assertNotNull(result.get("x/y/z/X.class"), "Class X is compiled: " + result);
   24.46 -        assertNotNull(result.get("x/y/z/Index.class"), "Class Index is compiled: " + result);
   24.47 -    }
   24.48 -}
    25.1 --- a/ide/editor/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,185 +0,0 @@
    25.4 -<?xml version="1.0" encoding="UTF-8"?>
    25.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">
    25.6 -    <modelVersion>4.0.0</modelVersion>
    25.7 -    <parent>
    25.8 -        <artifactId>ide</artifactId>
    25.9 -        <groupId>org.apidesign.bck2brwsr</groupId>
   25.10 -        <version>0.8-SNAPSHOT</version>
   25.11 -    </parent>
   25.12 -
   25.13 -    <groupId>org.apidesign.bck2brwsr.ide</groupId>
   25.14 -    <artifactId>editor</artifactId>
   25.15 -    <version>0.8-SNAPSHOT</version>
   25.16 -    <packaging>nbm</packaging>
   25.17 -
   25.18 -    <name>Editor Support for Bck2Brwsr</name>
   25.19 -
   25.20 -    <properties>
   25.21 -        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   25.22 -        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
   25.23 -    </properties>
   25.24 -
   25.25 -    <repositories>
   25.26 -        <!--
   25.27 -        Repository hosting NetBeans modules, especially APIs.
   25.28 -        Versions are based on IDE releases, e.g.: RELEASE691
   25.29 -        To create your own repository, use: nbm:populate-repository
   25.30 -        -->
   25.31 -        <repository>
   25.32 -            <id>netbeans</id>
   25.33 -            <name>NetBeans</name>
   25.34 -            <url>http://bits.netbeans.org/maven2/</url>
   25.35 -            <snapshots>
   25.36 -                <enabled>false</enabled>
   25.37 -            </snapshots>
   25.38 -        </repository>
   25.39 -    </repositories>
   25.40 -
   25.41 -    <dependencies>
   25.42 -        <dependency>
   25.43 -            <groupId>org.netbeans.api</groupId>
   25.44 -            <artifactId>org-netbeans-api-annotations-common</artifactId>
   25.45 -        </dependency>
   25.46 -        <dependency>
   25.47 -            <groupId>org.netbeans.api</groupId>
   25.48 -            <artifactId>org-netbeans-modules-java-source</artifactId>
   25.49 -        </dependency>
   25.50 -        <dependency>
   25.51 -            <groupId>org.netbeans.api</groupId>
   25.52 -            <artifactId>org-netbeans-libs-javacapi</artifactId>
   25.53 -        </dependency>
   25.54 -        <dependency>
   25.55 -            <groupId>org.netbeans.api</groupId>
   25.56 -            <artifactId>org-netbeans-spi-java-hints</artifactId>
   25.57 -        </dependency>
   25.58 -        <dependency>
   25.59 -            <groupId>org.netbeans.api</groupId>
   25.60 -            <artifactId>org-netbeans-modules-parsing-api</artifactId>
   25.61 -        </dependency>
   25.62 -        <dependency>
   25.63 -            <groupId>org.netbeans.api</groupId>
   25.64 -            <artifactId>org-netbeans-spi-editor-hints</artifactId>
   25.65 -        </dependency>
   25.66 -        <dependency>
   25.67 -            <groupId>org.netbeans.api</groupId>
   25.68 -            <artifactId>org-openide-util</artifactId>
   25.69 -        </dependency>
   25.70 -        <dependency>
   25.71 -            <groupId>org.netbeans.api</groupId>
   25.72 -            <artifactId>org-netbeans-modules-java-lexer</artifactId>
   25.73 -        </dependency>
   25.74 -        <dependency>
   25.75 -            <groupId>org.netbeans.api</groupId>
   25.76 -            <artifactId>org-netbeans-modules-lexer</artifactId>
   25.77 -        </dependency>
   25.78 -        <dependency>
   25.79 -            <groupId>org.apidesign.bck2brwsr</groupId>
   25.80 -            <artifactId>core</artifactId>
   25.81 -            <version>0.8-SNAPSHOT</version>
   25.82 -            <type>jar</type>
   25.83 -            <scope>test</scope>
   25.84 -        </dependency>
   25.85 -        <dependency>
   25.86 -            <groupId>org.netbeans.api</groupId>
   25.87 -            <artifactId>org-netbeans-modules-java-hints-test</artifactId>
   25.88 -            <scope>test</scope>
   25.89 -        </dependency>
   25.90 -        <dependency>
   25.91 -            <groupId>org.netbeans.api</groupId>
   25.92 -            <artifactId>org-netbeans-libs-junit4</artifactId>
   25.93 -            <scope>test</scope>
   25.94 -        </dependency>
   25.95 -        <dependency>
   25.96 -            <groupId>org.netbeans.modules</groupId>
   25.97 -            <artifactId>org-netbeans-lib-nbjavac</artifactId>
   25.98 -            <scope>test</scope>
   25.99 -        </dependency>
  25.100 -        <dependency>
  25.101 -            <groupId>org.testng</groupId>
  25.102 -            <artifactId>testng</artifactId>
  25.103 -            <scope>test</scope>
  25.104 -        </dependency>
  25.105 -    </dependencies>
  25.106 -
  25.107 -    <build>
  25.108 -        <plugins>
  25.109 -            <plugin>
  25.110 -                <groupId>org.codehaus.mojo</groupId>
  25.111 -                <artifactId>nbm-maven-plugin</artifactId>
  25.112 -                <version>3.8</version>
  25.113 -                <extensions>true</extensions>
  25.114 -            </plugin>
  25.115 -
  25.116 -            <plugin>
  25.117 -                <!-- NetBeans 6.9+ requires JDK 6 -->
  25.118 -                <groupId>org.apache.maven.plugins</groupId>
  25.119 -                <artifactId>maven-compiler-plugin</artifactId>
  25.120 -                <version>2.5.1</version>
  25.121 -                <configuration>
  25.122 -                    <source>1.6</source>
  25.123 -                    <target>1.6</target>
  25.124 -                    <compilerArguments>
  25.125 -                        <endorseddirs>${endorsed.dir}</endorseddirs>
  25.126 -                    </compilerArguments>
  25.127 -                </configuration>
  25.128 -            </plugin>
  25.129 -
  25.130 -            <plugin>
  25.131 -                <groupId>org.apache.maven.plugins</groupId>
  25.132 -                <artifactId>maven-jar-plugin</artifactId>
  25.133 -                <version>2.4</version>
  25.134 -                <configuration>
  25.135 -                    <!-- to have the jar plugin pickup the nbm generated manifest -->
  25.136 -                    <useDefaultManifestFile>true</useDefaultManifestFile>
  25.137 -                </configuration>
  25.138 -            </plugin>
  25.139 -
  25.140 -            <plugin>
  25.141 -                <groupId>org.apache.maven.plugins</groupId>
  25.142 -                <artifactId>maven-dependency-plugin</artifactId>
  25.143 -                <executions>
  25.144 -                    <execution>
  25.145 -                        <id>endorsed</id>
  25.146 -                        <phase>validate</phase>
  25.147 -                        <goals>
  25.148 -                            <goal>copy</goal>
  25.149 -                        </goals>
  25.150 -                    </execution>
  25.151 -                </executions>
  25.152 -                <configuration>
  25.153 -                    <outputDirectory>${endorsed.dir}</outputDirectory>
  25.154 -                    <silent>true</silent>
  25.155 -                    <artifactItems>
  25.156 -                        <artifactItem>
  25.157 -                            <groupId>org.netbeans.api</groupId>
  25.158 -                            <artifactId>org-netbeans-libs-javacapi</artifactId>
  25.159 -                            <version>${netbeans.version}</version>
  25.160 -                        </artifactItem>
  25.161 -                        <artifactItem>
  25.162 -                            <groupId>org.netbeans.external</groupId>
  25.163 -                            <artifactId>nb-javac-api</artifactId>
  25.164 -                            <version>${netbeans.version}</version>
  25.165 -                        </artifactItem>
  25.166 -                        <artifactItem>
  25.167 -                            <groupId>org.netbeans.modules</groupId>
  25.168 -                            <artifactId>org-netbeans-libs-javacimpl</artifactId>
  25.169 -                            <version>${netbeans.version}</version>
  25.170 -                        </artifactItem>
  25.171 -                        <artifactItem>
  25.172 -                            <groupId>org.netbeans.external</groupId>
  25.173 -                            <artifactId>nb-javac-impl</artifactId>
  25.174 -                            <version>${netbeans.version}</version>
  25.175 -                        </artifactItem>
  25.176 -                    </artifactItems>
  25.177 -                </configuration>
  25.178 -            </plugin>
  25.179 -            <plugin>
  25.180 -                <groupId>org.apache.maven.plugins</groupId>
  25.181 -                <artifactId>maven-surefire-plugin</artifactId>
  25.182 -                <configuration>
  25.183 -                    <argLine>-Djava.endorsed.dirs=${endorsed.dir}</argLine>
  25.184 -                </configuration>
  25.185 -            </plugin>
  25.186 -        </plugins>
  25.187 -    </build>
  25.188 -</project>
    26.1 --- a/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JNIHelper.java	Tue Apr 29 15:25:58 2014 +0200
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,80 +0,0 @@
    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.ide.editor;
   26.22 -
   26.23 -import java.lang.reflect.Method;
   26.24 -import java.util.HashMap;
   26.25 -import java.util.Map;
   26.26 -
   26.27 -/**
   26.28 - * JNI Helper.
   26.29 - * To facilitate lookup of methods by name and signature, instead of manually parsing signatures,
   26.30 - * constructs the map of all methods and uses Class.getName() to generate almost-correct signatures.
   26.31 - */
   26.32 -class JNIHelper {
   26.33 -
   26.34 -    static Method method(String clazz, String method, String signature) {
   26.35 -        final Map<String, Method> methods = methodMap(JNIHelper.clazz(clazz));
   26.36 -        return methods.get(methodKey(method, signature));
   26.37 -    }
   26.38 -
   26.39 -    static Class<?> clazz(String clazz) {
   26.40 -        try {
   26.41 -            return Class.forName(clazz);
   26.42 -        } catch (ClassNotFoundException e) {
   26.43 -            throw new IllegalArgumentException(e);
   26.44 -        }
   26.45 -    }
   26.46 -
   26.47 -    static Map<String, Method> methodMap(final Class<?> clazz) {
   26.48 -        final Map<String, Method> map = new HashMap<String, Method>();
   26.49 -        final Method[] methods = clazz.getDeclaredMethods();
   26.50 -        for (int i = 0; i < methods.length; i++) {
   26.51 -            final Method method = methods[i];
   26.52 -            map.put(methodKey(method.getName(), signature(method)), method);
   26.53 -        }
   26.54 -        return map;
   26.55 -    }
   26.56 -
   26.57 -    static String methodKey(String method, String signature) {
   26.58 -        return method + '@' + signature;
   26.59 -    }
   26.60 -
   26.61 -    static String signature(final Method method) {
   26.62 -        final Class<?>[] parameterTypes = method.getParameterTypes();
   26.63 -        final StringBuilder b = new StringBuilder();
   26.64 -        for (int j = 0; j < parameterTypes.length; j++) {
   26.65 -            b.append(signature(parameterTypes[j]));
   26.66 -        }
   26.67 -        return b.toString();
   26.68 -    }
   26.69 -
   26.70 -    static String signature(final Class<?> clazz) {
   26.71 -        if (clazz == boolean.class) return "Z";
   26.72 -        else if (clazz == byte.class) return "B";
   26.73 -        else if (clazz == char.class) return "C";
   26.74 -        else if (clazz == double.class) return "D";
   26.75 -        else if (clazz == float.class) return "F";
   26.76 -        else if (clazz == int.class) return "I";
   26.77 -        else if (clazz == long.class) return "J";
   26.78 -        else if (clazz == short.class) return "S";
   26.79 -        else if (clazz == void.class) return "V";
   26.80 -        else if (clazz.isArray()) return clazz.getName().replace('.','/');
   26.81 -        else return "L" + clazz.getName().replace('.','/') + ";";
   26.82 -    }
   26.83 -}
    27.1 --- a/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSEmbeddingProvider.java	Tue Apr 29 15:25:58 2014 +0200
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,188 +0,0 @@
    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.ide.editor;
   27.22 -
   27.23 -import com.sun.source.tree.AnnotationTree;
   27.24 -import com.sun.source.tree.AssignmentTree;
   27.25 -import com.sun.source.tree.CompilationUnitTree;
   27.26 -import com.sun.source.tree.ExpressionTree;
   27.27 -import com.sun.source.tree.LiteralTree;
   27.28 -import com.sun.source.tree.MethodTree;
   27.29 -import com.sun.source.util.SourcePositions;
   27.30 -import com.sun.source.util.TreePath;
   27.31 -import com.sun.source.util.TreePathScanner;
   27.32 -import com.sun.source.util.Trees;
   27.33 -import java.io.IOException;
   27.34 -import java.util.ArrayList;
   27.35 -import java.util.Collection;
   27.36 -import java.util.Collections;
   27.37 -import java.util.List;
   27.38 -import java.util.concurrent.atomic.AtomicBoolean;
   27.39 -import javax.lang.model.element.TypeElement;
   27.40 -import javax.swing.text.Document;
   27.41 -import org.netbeans.api.editor.mimelookup.MimeRegistration;
   27.42 -import org.netbeans.api.java.source.CompilationInfo;
   27.43 -import org.netbeans.api.java.source.JavaParserResultTask;
   27.44 -import org.netbeans.api.java.source.JavaSource;
   27.45 -import org.netbeans.api.lexer.Language;
   27.46 -import org.netbeans.api.lexer.TokenHierarchy;
   27.47 -import org.netbeans.api.lexer.TokenSequence;
   27.48 -import org.netbeans.modules.parsing.api.Snapshot;
   27.49 -import org.netbeans.modules.parsing.spi.Parser;
   27.50 -import org.netbeans.modules.parsing.spi.Scheduler;
   27.51 -import org.netbeans.modules.parsing.spi.SchedulerEvent;
   27.52 -import org.netbeans.modules.parsing.spi.SchedulerTask;
   27.53 -import org.netbeans.modules.parsing.spi.TaskFactory;
   27.54 -import org.openide.util.Exceptions;
   27.55 -
   27.56 -/**
   27.57 - *
   27.58 - * @author Tomas Zezula
   27.59 - */
   27.60 -public final class JSEmbeddingProvider extends JavaParserResultTask<Parser.Result> {
   27.61 -
   27.62 -    private static final int PRIORITY = 1000;
   27.63 -    private static final String JS_ANNOTATION = "org.apidesign.bck2brwsr.core.JavaScriptBody";  //NOI18N
   27.64 -    private static final String BODY = "body";                            //NOI18N
   27.65 -    private static final String JAVA_MIME_TYPE = "text/x-java";           //NOI18N
   27.66 -    private static final String JAVASCRIPT_MIME_TYPE = "text/javascript"; //NOI18N
   27.67 -    private final AtomicBoolean canceled = new AtomicBoolean();
   27.68 -
   27.69 -    private JSEmbeddingProvider() {
   27.70 -        super(JavaSource.Phase.ELEMENTS_RESOLVED);
   27.71 -    }
   27.72 -
   27.73 -    @Override
   27.74 -    public int getPriority() {
   27.75 -        return PRIORITY;
   27.76 -    }
   27.77 -
   27.78 -    @Override
   27.79 -    public void cancel() {
   27.80 -        canceled.set(true);
   27.81 -    }
   27.82 -
   27.83 -    @Override
   27.84 -    public Class<? extends Scheduler> getSchedulerClass() {
   27.85 -        return Scheduler.EDITOR_SENSITIVE_TASK_SCHEDULER;
   27.86 -    }
   27.87 -
   27.88 -    @Override
   27.89 -    public void run(Parser.Result t, SchedulerEvent se) {
   27.90 -        canceled.set(false);
   27.91 -        final CompilationInfo ci = CompilationInfo.get(t);
   27.92 -        final CompilationUnitTree cu = ci.getCompilationUnit();
   27.93 -        final Trees trees = ci.getTrees();
   27.94 -        final SourcePositions sp = trees.getSourcePositions();
   27.95 -        final Finder f = new Finder(trees);
   27.96 -        final List<LiteralTree> result = new ArrayList<LiteralTree>();
   27.97 -        f.scan(cu, result);
   27.98 -        if (!result.isEmpty()) {
   27.99 -            try {
  27.100 -                final TokenHierarchy<Document> tk = TokenHierarchy.get(ci.getDocument());
  27.101 -                final Language<?> java = Language.find(JAVA_MIME_TYPE);
  27.102 -                final Language<?> javaScript = Language.find(JAVASCRIPT_MIME_TYPE);
  27.103 -                if (java != null && javaScript != null) {
  27.104 -                    final TokenSequence<?> seq = tk.tokenSequence(java);
  27.105 -                    if (seq != null) {
  27.106 -                        for (LiteralTree lt : result) {
  27.107 -                            final int start = (int) sp.getStartPosition(cu, lt);
  27.108 -                            final int end = (int) sp.getEndPosition(cu, lt);
  27.109 -                            seq.move(start);
  27.110 -                            while (seq.moveNext() && seq.offset() < end) {
  27.111 -                                seq.createEmbedding(javaScript, 1, 1, true);
  27.112 -                            }
  27.113 -                        }
  27.114 -                    }
  27.115 -                }
  27.116 -            } catch (IOException ioe) {
  27.117 -                Exceptions.printStackTrace(ioe);
  27.118 -            }
  27.119 -        }
  27.120 -    }
  27.121 -
  27.122 -
  27.123 -
  27.124 -
  27.125 -    private static final class Finder extends TreePathScanner<Void, List<? super LiteralTree>> {
  27.126 -
  27.127 -        private final Trees trees;
  27.128 -        private CompilationUnitTree cu;
  27.129 -        private boolean inEmbedding;
  27.130 -
  27.131 -        Finder(final Trees trees) {
  27.132 -            this.trees = trees;
  27.133 -        }
  27.134 -
  27.135 -        @Override
  27.136 -        public Void visitCompilationUnit(
  27.137 -                final CompilationUnitTree unit,
  27.138 -                final List p) {
  27.139 -            this.cu = unit;
  27.140 -            return super.visitCompilationUnit(unit, p);
  27.141 -        }
  27.142 -
  27.143 -
  27.144 -
  27.145 -        @Override
  27.146 -        public Void visitMethod(
  27.147 -                final MethodTree m,
  27.148 -                final List<? super LiteralTree> p) {
  27.149 -            for (AnnotationTree a : m.getModifiers().getAnnotations()) {
  27.150 -                final TypeElement ae = (TypeElement) trees.getElement(TreePath.getPath(cu, a.getAnnotationType()));
  27.151 -                if (ae != null && JS_ANNOTATION.contentEquals(ae.getQualifiedName())) {
  27.152 -                    final List<? extends ExpressionTree> args =  a.getArguments();
  27.153 -                    for (ExpressionTree kvp : args) {
  27.154 -                        if (kvp instanceof AssignmentTree) {
  27.155 -                            final AssignmentTree assignemt = (AssignmentTree) kvp;
  27.156 -                            if (BODY.equals(assignemt.getVariable().toString())) {
  27.157 -                                inEmbedding = true;
  27.158 -                                try {
  27.159 -                                    scan(assignemt.getExpression(), p);
  27.160 -                                } finally {
  27.161 -                                    inEmbedding = false;
  27.162 -                                }
  27.163 -                            }
  27.164 -                        }
  27.165 -                    }
  27.166 -                }
  27.167 -            }
  27.168 -            return null;
  27.169 -        }
  27.170 -
  27.171 -        @Override
  27.172 -        public Void visitLiteral(LiteralTree node, List<? super LiteralTree> p) {
  27.173 -            if (inEmbedding) {
  27.174 -                p.add(node);
  27.175 -            }
  27.176 -            return super.visitLiteral(node, p);
  27.177 -        }
  27.178 -
  27.179 -    }
  27.180 -
  27.181 -    @MimeRegistration(
  27.182 -            service = TaskFactory.class,
  27.183 -            mimeType = JAVA_MIME_TYPE)
  27.184 -    public static final class Factory extends TaskFactory {
  27.185 -        @Override
  27.186 -        public Collection<? extends SchedulerTask> create(Snapshot snpsht) {
  27.187 -            return Collections.singleton(new JSEmbeddingProvider());
  27.188 -        }
  27.189 -    }
  27.190 -
  27.191 -}
    28.1 --- a/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBody.java	Tue Apr 29 15:25:58 2014 +0200
    28.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3 @@ -1,149 +0,0 @@
    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.ide.editor;
   28.22 -
   28.23 -import com.sun.source.tree.AnnotationTree;
   28.24 -import com.sun.source.tree.ExpressionTree;
   28.25 -import com.sun.source.tree.LiteralTree;
   28.26 -import com.sun.source.tree.MethodTree;
   28.27 -import com.sun.source.tree.Tree.Kind;
   28.28 -import com.sun.source.tree.VariableTree;
   28.29 -import com.sun.source.util.TreePath;
   28.30 -import java.util.ArrayList;
   28.31 -import java.util.Arrays;
   28.32 -import java.util.Collections;
   28.33 -import java.util.List;
   28.34 -import org.netbeans.api.java.lexer.JavaTokenId;
   28.35 -import static org.netbeans.api.java.lexer.JavaTokenId.BLOCK_COMMENT;
   28.36 -import static org.netbeans.api.java.lexer.JavaTokenId.JAVADOC_COMMENT;
   28.37 -import static org.netbeans.api.java.lexer.JavaTokenId.LINE_COMMENT;
   28.38 -import static org.netbeans.api.java.lexer.JavaTokenId.WHITESPACE;
   28.39 -import org.netbeans.api.java.source.CompilationInfo;
   28.40 -import org.netbeans.api.java.source.TreeMaker;
   28.41 -import org.netbeans.api.lexer.Token;
   28.42 -import org.netbeans.api.lexer.TokenSequence;
   28.43 -import org.netbeans.spi.editor.hints.ErrorDescription;
   28.44 -import org.netbeans.spi.editor.hints.Fix;
   28.45 -import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
   28.46 -import org.netbeans.spi.java.hints.Hint;
   28.47 -import org.netbeans.spi.java.hints.HintContext;
   28.48 -import org.netbeans.spi.java.hints.JavaFix;
   28.49 -import org.netbeans.spi.java.hints.TriggerTreeKind;
   28.50 -import org.openide.util.NbBundle.Messages;
   28.51 -
   28.52 -@Hint(displayName = "#DN_JSNI2JavaScriptBody", description = "#DESC_JSNI2JavaScriptBody", category = "general")
   28.53 -@Messages({
   28.54 -    "DN_JSNI2JavaScriptBody=JSNI to @JavaScriptBody",
   28.55 -    "DESC_JSNI2JavaScriptBody=JSNI to @JavaScriptBody"
   28.56 -})
   28.57 -public class JSNI2JavaScriptBody {
   28.58 -
   28.59 -    @TriggerTreeKind(Kind.METHOD)
   28.60 -    @Messages("ERR_JSNI2JavaScriptBody=Can convert JSNI to @JavaScriptBody")
   28.61 -    public static ErrorDescription computeWarning(final HintContext ctx) {
   28.62 -        Token<JavaTokenId> token = findBlockToken(ctx.getInfo(), ctx.getPath(), ctx);
   28.63 -
   28.64 -        if (token == null) {
   28.65 -            return null;
   28.66 -        }
   28.67 -
   28.68 -        Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath()).toEditorFix();
   28.69 -        return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), Bundle.ERR_JSNI2JavaScriptBody(), fix);
   28.70 -    }
   28.71 -
   28.72 -    private static Token<JavaTokenId> findBlockToken(CompilationInfo info, TreePath path, HintContext ctx) {
   28.73 -        int end = (int) info.getTrees().getSourcePositions().getEndPosition(path.getCompilationUnit(), path.getLeaf());
   28.74 -        TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence(JavaTokenId.language());
   28.75 -
   28.76 -        if (ts == null) return null;
   28.77 -
   28.78 -        ts.move(end);
   28.79 -
   28.80 -        if ((ctx != null && ctx.isCanceled()) || !ts.movePrevious() || ts.token().id() != JavaTokenId.SEMICOLON) return null;
   28.81 -
   28.82 -        OUTER: while (ts.movePrevious()) {
   28.83 -            if (ctx != null && ctx.isCanceled()) return null;
   28.84 -
   28.85 -            switch (ts.token().id()) {
   28.86 -                case WHITESPACE: break;
   28.87 -                case LINE_COMMENT: break;
   28.88 -                case JAVADOC_COMMENT: break;
   28.89 -                case BLOCK_COMMENT:
   28.90 -                    final CharSequence tok = ts.token().text();
   28.91 -                    final int l = tok.length(); 
   28.92 -                    if (l > 4 
   28.93 -                        && tok.subSequence(0, 4).toString().equals("/*-{") // NOI18N
   28.94 -                        && tok.subSequence(l - 4, l).toString().equals("}-*/") // NOI18N
   28.95 -                    ) {
   28.96 -                        return ts.offsetToken();
   28.97 -                    }
   28.98 -                    break;
   28.99 -                default:
  28.100 -                    break OUTER;
  28.101 -            }
  28.102 -        }
  28.103 -
  28.104 -        return null;
  28.105 -    }
  28.106 -
  28.107 -    private static final class FixImpl extends JavaFix {
  28.108 -
  28.109 -        public FixImpl(CompilationInfo info, TreePath tp) {
  28.110 -            super(info, tp);
  28.111 -        }
  28.112 -
  28.113 -        @Override
  28.114 -        @Messages("FIX_JSNI2JavaScriptBody=Convert JSNI to @JavaScriptBody")
  28.115 -        protected String getText() {
  28.116 -            return Bundle.FIX_JSNI2JavaScriptBody();
  28.117 -        }
  28.118 -
  28.119 -        @Override
  28.120 -        protected void performRewrite(TransformationContext ctx) {
  28.121 -            Token<JavaTokenId> jsniComment = findBlockToken(ctx.getWorkingCopy(), ctx.getPath(), null);
  28.122 -
  28.123 -            if (jsniComment == null) {
  28.124 -                //XXX: warn?
  28.125 -                return ;
  28.126 -            }
  28.127 -            
  28.128 -            JsniCommentTokenizer tok = new JsniCommentTokenizer();
  28.129 -            ManglingSink ms = new ManglingSink();
  28.130 -            final CharSequence cmnt = jsniComment.text();
  28.131 -            tok.process(cmnt.subSequence(4, cmnt.length() - 4), ms);
  28.132 -
  28.133 -            TreeMaker make = ctx.getWorkingCopy().getTreeMaker();
  28.134 -            MethodTree mt = (MethodTree) ctx.getPath().getLeaf();
  28.135 -            List<LiteralTree> params = new ArrayList<LiteralTree>();
  28.136 -
  28.137 -            for (VariableTree p : mt.getParameters()) {
  28.138 -                params.add(make.Literal(p.getName().toString()));
  28.139 -            }
  28.140 -
  28.141 -            AnnotationTree jsBody = make.Annotation(make.QualIdent("org.apidesign.bck2brwsr.core.JavaScriptBody"),
  28.142 -                Arrays.<ExpressionTree>asList(
  28.143 -                    make.Assignment(make.Identifier("args"), make.NewArray(null, Collections.<ExpressionTree>emptyList(), params)),
  28.144 -                    make.Assignment(make.Identifier("body"), make.Literal(ms.out.toString()))
  28.145 -                )
  28.146 -            );
  28.147 -
  28.148 -
  28.149 -            ctx.getWorkingCopy().rewrite(mt.getModifiers(), make.addModifiersAnnotation(mt.getModifiers(), jsBody));
  28.150 -        }
  28.151 -    }
  28.152 -}
    29.1 --- a/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizer.java	Tue Apr 29 15:25:58 2014 +0200
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,70 +0,0 @@
    29.4 -/**
    29.5 - * Back 2 Browser Bytecode Translator
    29.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    29.7 - *
    29.8 - * This program is free software: you can redistribute it and/or modify
    29.9 - * it under the terms of the GNU General Public License as published by
   29.10 - * the Free Software Foundation, version 2 of the License.
   29.11 - *
   29.12 - * This program is distributed in the hope that it will be useful,
   29.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.15 - * GNU General Public License for more details.
   29.16 - *
   29.17 - * You should have received a copy of the GNU General Public License
   29.18 - * along with this program. Look for COPYING file in the top folder.
   29.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   29.20 - */
   29.21 -package org.apidesign.bck2brwsr.ide.editor;
   29.22 -
   29.23 -import java.util.regex.Matcher;
   29.24 -import java.util.regex.Pattern;
   29.25 -
   29.26 -final class JsniCommentTokenizer {
   29.27 -
   29.28 -    /**
   29.29 -     * Tokenize the contents of JSNI comment into the provided {@linkplain Sink}.
   29.30 -     * @param in the contents of JSNI comment
   29.31 -     * @param out the sink that consumes parsed tokens
   29.32 -     */
   29.33 -    public void process(final CharSequence in, final Sink out) {
   29.34 -        final Matcher member = Pattern.compile("@([^:]+)::([a-zA-Z_$][a-zA-Z\\d_$]*)").matcher(in);
   29.35 -        final Matcher signature = Pattern.compile("\\(([^\\)]*)\\)").matcher(in);
   29.36 -
   29.37 -        int i = 0;
   29.38 -        while (true) {
   29.39 -            if (member.find(i)) {
   29.40 -                final int memberStart = member.start();
   29.41 -                final int memberEnd = member.end();
   29.42 -                if (memberStart > i) out.javascript(in.subSequence(i, memberStart).toString());
   29.43 -
   29.44 -                final String clazz = member.group(1);
   29.45 -                final String name = member.group(2);
   29.46 -
   29.47 -                if (in.charAt(memberEnd) == '(') {
   29.48 -                    if (!signature.find(memberEnd)) {
   29.49 -                        throw new IllegalStateException("Expected method signature");
   29.50 -                    }
   29.51 -                    assert signature.start() == memberEnd;
   29.52 -                    out.method(clazz, name, signature.group(1));
   29.53 -                    i = signature.end();
   29.54 -                } else {
   29.55 -                    out.field(clazz, name);
   29.56 -                    i = memberEnd;
   29.57 -                }
   29.58 -            } else {
   29.59 -                out.javascript(in.subSequence(i, in.length()).toString());
   29.60 -                break;
   29.61 -            }
   29.62 -        }
   29.63 -    }
   29.64 -
   29.65 -
   29.66 -    static interface Sink {
   29.67 -        void javascript(String s);
   29.68 -
   29.69 -        void method(String clazz, String method, String signature);
   29.70 -
   29.71 -        void field(String clazz, String field);
   29.72 -    }
   29.73 -}
    30.1 --- a/ide/editor/src/main/java/org/apidesign/bck2brwsr/ide/editor/ManglingSink.java	Tue Apr 29 15:25:58 2014 +0200
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,71 +0,0 @@
    30.4 -/**
    30.5 - * Back 2 Browser Bytecode Translator
    30.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    30.7 - *
    30.8 - * This program is free software: you can redistribute it and/or modify
    30.9 - * it under the terms of the GNU General Public License as published by
   30.10 - * the Free Software Foundation, version 2 of the License.
   30.11 - *
   30.12 - * This program is distributed in the hope that it will be useful,
   30.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.15 - * GNU General Public License for more details.
   30.16 - *
   30.17 - * You should have received a copy of the GNU General Public License
   30.18 - * along with this program. Look for COPYING file in the top folder.
   30.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   30.20 - */
   30.21 -package org.apidesign.bck2brwsr.ide.editor;
   30.22 -
   30.23 -/**
   30.24 - * An implementation of {@linkplain JsniCommentTokenizer.Sink} that generates B2B
   30.25 - */
   30.26 -class ManglingSink implements JsniCommentTokenizer.Sink {
   30.27 -
   30.28 -    final StringBuilder out = new StringBuilder();
   30.29 -
   30.30 -    public void javascript(String s) {
   30.31 -        out.append(s);
   30.32 -    }
   30.33 -
   30.34 -    public void method(String clazz, String method, String signature) {
   30.35 -        out.append(mangle(clazz, method, signature));
   30.36 -    }
   30.37 -
   30.38 -    public void field(String clazz, String field) {
   30.39 -//        out.append(field);
   30.40 -        out.append('_').append(field).append('(').append(')');
   30.41 -    }
   30.42 -
   30.43 -
   30.44 -    @Override
   30.45 -    public String toString() {
   30.46 -        return out.toString();
   30.47 -    }
   30.48 -
   30.49 -
   30.50 -    static String mangle(String clazz, String method, String signature) {
   30.51 -        final StringBuilder builder = new StringBuilder();
   30.52 -        builder.append(method);
   30.53 -        builder.append("__");
   30.54 -        builder.append(mangle(JNIHelper.signature(JNIHelper.method(clazz, method, signature).getReturnType())));
   30.55 -        builder.append(mangle(signature));
   30.56 -        return builder.toString();
   30.57 -    }
   30.58 -
   30.59 -
   30.60 -    static String mangle(String txt) {
   30.61 -        final StringBuilder sb = new StringBuilder();
   30.62 -        for (int i = 0; i < txt.length(); i++) {
   30.63 -            final char ch = txt.charAt(i);
   30.64 -            switch (ch) {
   30.65 -                case '/': sb.append('_'); break;
   30.66 -                case '_': sb.append("_1"); break;
   30.67 -                case ';': sb.append("_2"); break;
   30.68 -                case '[': sb.append("_3"); break;
   30.69 -                default: sb.append(ch); break;
   30.70 -            }
   30.71 -        }
   30.72 -        return sb.toString();
   30.73 -    }
   30.74 -}
    31.1 --- a/ide/editor/src/main/nbm/manifest.mf	Tue Apr 29 15:25:58 2014 +0200
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,2 +0,0 @@
    31.4 -Manifest-Version: 1.0
    31.5 -OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/test/hints/Bundle.properties
    32.1 --- a/ide/editor/src/main/resources/org/netbeans/modules/jackpot30/test/hints/Bundle.properties	Tue Apr 29 15:25:58 2014 +0200
    32.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3 @@ -1,21 +0,0 @@
    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 -
   32.22 -OpenIDE-Module-Name=Bck2Brwsr Editor Support
   32.23 -OpenIDE-Module-Short-Description=Provides hints, coloring, etc. for the bck2brwsr.apidesign.org project
   32.24 -OpenIDE-Module-Display-Category=Java
    33.1 --- a/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/DejsniReaderTest.java	Tue Apr 29 15:25:58 2014 +0200
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,84 +0,0 @@
    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.ide.editor;
   33.22 -
   33.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   33.24 -import org.netbeans.modules.java.hints.test.api.HintTest;
   33.25 -import org.openide.filesystems.FileUtil;
   33.26 -import org.testng.annotations.Test;
   33.27 -
   33.28 -public class DejsniReaderTest {
   33.29 -
   33.30 -    @Test
   33.31 -    public void test1() throws Exception {
   33.32 -        String s = "class Test {\n" +
   33.33 -                "    /** javadoc */\n" +
   33.34 -                "    public native void test() /*-{\n" +
   33.35 -                "        // body\n" +
   33.36 -                "    }-*/;\n" +
   33.37 -                "}\n";
   33.38 -
   33.39 -        String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n"
   33.40 -              + "class Test {\n" +
   33.41 -                "\n" +
   33.42 -                "    /** javadoc */\n" +
   33.43 -                "    @JavaScriptBody(args = {}, body = \"\\n        // body\\n  \")\n" +
   33.44 -                "    public native void test();\n" +
   33.45 -                "}\n";
   33.46 -        
   33.47 -          HintTest.create()
   33.48 -                .input(s)
   33.49 -                .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
   33.50 -                .run(JSNI2JavaScriptBody.class)
   33.51 -                .findWarning("2:23-2:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
   33.52 -                .applyFix()
   33.53 -                .assertCompilable()
   33.54 -                .assertOutput(expected);
   33.55 -    }
   33.56 -
   33.57 -
   33.58 -    @Test
   33.59 -    public void test2() throws Exception {
   33.60 -        String s = "class Test {\n" +
   33.61 -                "    /** javadoc */\n" +
   33.62 -                "    @SuppressWarnings(\"unused\")\n" +
   33.63 -                "    // comment\n" +
   33.64 -                "    public native void test() /*-{\n" +
   33.65 -                "        // body\n" +
   33.66 -                "    }-*/;\n" +
   33.67 -                "}\n";
   33.68 -
   33.69 -        String expected = " import org.apidesign.bck2brwsr.core.JavaScriptBody;\n"
   33.70 -              + "class Test {\n" +
   33.71 -                "\n" +
   33.72 -                "    /** javadoc */\n" +
   33.73 -                "    @SuppressWarnings(\"unused\")\n" +
   33.74 -                "    // comment\n" +
   33.75 -                "    @JavaScriptBody(args = {}, body = \"\\n        // body\\n  \")\n" +
   33.76 -                "    public native void test();\n" +
   33.77 -                "}\n";
   33.78 -          HintTest.create()
   33.79 -                .input(s)
   33.80 -                .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
   33.81 -                .run(JSNI2JavaScriptBody.class)
   33.82 -                .findWarning("4:23-4:27:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
   33.83 -                .applyFix()
   33.84 -                .assertCompilable()
   33.85 -                .assertOutput(expected);
   33.86 -    }
   33.87 -}
   33.88 \ No newline at end of file
    34.1 --- a/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JSNI2JavaScriptBodyTest.java	Tue Apr 29 15:25:58 2014 +0200
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,46 +0,0 @@
    34.4 -/**
    34.5 - * Back 2 Browser Bytecode Translator
    34.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    34.7 - *
    34.8 - * This program is free software: you can redistribute it and/or modify
    34.9 - * it under the terms of the GNU General Public License as published by
   34.10 - * the Free Software Foundation, version 2 of the License.
   34.11 - *
   34.12 - * This program is distributed in the hope that it will be useful,
   34.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.15 - * GNU General Public License for more details.
   34.16 - *
   34.17 - * You should have received a copy of the GNU General Public License
   34.18 - * along with this program. Look for COPYING file in the top folder.
   34.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   34.20 - */
   34.21 -package org.apidesign.bck2brwsr.ide.editor;
   34.22 -
   34.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   34.24 -import org.netbeans.modules.java.hints.test.api.HintTest;
   34.25 -import org.openide.filesystems.FileUtil;
   34.26 -import org.testng.annotations.Test;
   34.27 -
   34.28 -public class JSNI2JavaScriptBodyTest {
   34.29 -
   34.30 -    @Test
   34.31 -    public void testFixWorking() throws Exception {
   34.32 -        HintTest.create()
   34.33 -                .input("package test;\n" +
   34.34 -                       "public class Test {\n" +
   34.35 -                       "    public native void run(int a) /*-{ this.a = a; }-*/;\n" +
   34.36 -                       "}\n")
   34.37 -                .classpath(FileUtil.getArchiveRoot(JavaScriptBody.class.getProtectionDomain().getCodeSource().getLocation()))
   34.38 -                .run(JSNI2JavaScriptBody.class)
   34.39 -                .findWarning("2:23-2:26:verifier:" + Bundle.ERR_JSNI2JavaScriptBody())
   34.40 -                .applyFix()
   34.41 -                .assertCompilable()
   34.42 -                .assertOutput("package test;\n" +
   34.43 -                              "import org.apidesign.bck2brwsr.core.JavaScriptBody;\n" +
   34.44 -                              "public class Test {\n" +
   34.45 -                              "    @JavaScriptBody(args = {\"a\"}, body = \" this.a = a; \")\n" +
   34.46 -                              "    public native void run(int a);\n" +
   34.47 -                              "}\n");
   34.48 -    }
   34.49 -}
    35.1 --- a/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/JsniCommentTokenizerTest.java	Tue Apr 29 15:25:58 2014 +0200
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,154 +0,0 @@
    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.ide.editor;
   35.22 -
   35.23 -import java.io.IOException;
   35.24 -import java.util.ArrayList;
   35.25 -import java.util.List;
   35.26 -import org.testng.Assert;
   35.27 -import org.testng.annotations.Test;
   35.28 -
   35.29 -public class JsniCommentTokenizerTest {
   35.30 -
   35.31 -    private static class MockSink implements JsniCommentTokenizer.Sink {
   35.32 -        final List<String> out = new ArrayList<String>();
   35.33 -
   35.34 -        public void javascript(String s) {
   35.35 -            out.add("J " + s);
   35.36 -        }
   35.37 -
   35.38 -        public void method(String clazz, String method, String signature) {
   35.39 -            out.add("M " + clazz + "|" + method + "|" + signature);
   35.40 -        }
   35.41 -
   35.42 -        public void field(String clazz, String field) {
   35.43 -            out.add("F " + clazz + "|" + field);
   35.44 -        }
   35.45 -    }
   35.46 -
   35.47 -
   35.48 -    @Test
   35.49 -    public void testProcess_nop() throws IOException {
   35.50 -        final String in = "foo bar";
   35.51 -        final List<String> expected = new ArrayList<String>();
   35.52 -        expected.add("J foo bar");
   35.53 -
   35.54 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
   35.55 -        final MockSink out = new MockSink();
   35.56 -        jsniCommentTokenizer.process(in, out);
   35.57 -
   35.58 -        Assert.assertEquals(expected, out.out);
   35.59 -    }
   35.60 -
   35.61 -    @Test
   35.62 -    public void testProcess_read_static_field() throws IOException {
   35.63 -        final String in = " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";";
   35.64 -        final List<String> expected = new ArrayList<String>();
   35.65 -        expected.add("J  ");
   35.66 -        expected.add("F com.google.gwt.examples.JSNIExample|myStaticField");
   35.67 -        expected.add("J  = val + \" and stuff\";");
   35.68 -
   35.69 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
   35.70 -        final MockSink out = new MockSink();
   35.71 -        jsniCommentTokenizer.process(in, out);
   35.72 -
   35.73 -        Assert.assertEquals(expected, out.out);
   35.74 -    }
   35.75 -
   35.76 -    @Test
   35.77 -    public void testProcess_write_instance_field() throws IOException {
   35.78 -        final String in = " x.@com.google.gwt.examples.JSNIExample::myInstanceField = val + \" and stuff\";";
   35.79 -        final List<String> expected = new ArrayList<String>();
   35.80 -        expected.add("J  x.");
   35.81 -        expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField");
   35.82 -        expected.add("J  = val + \" and stuff\";");
   35.83 -
   35.84 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
   35.85 -        final MockSink out = new MockSink();
   35.86 -        jsniCommentTokenizer.process(in, out);
   35.87 -
   35.88 -        Assert.assertEquals(expected, out.out);
   35.89 -    }
   35.90 -
   35.91 -    @Test
   35.92 -    public void testProcess_read_instance_field() throws IOException {
   35.93 -        final String in = " var val = this.@com.google.gwt.examples.JSNIExample::myInstanceField;";
   35.94 -        final List<String> expected = new ArrayList<String>();
   35.95 -        expected.add("J  var val = this.");
   35.96 -        expected.add("F com.google.gwt.examples.JSNIExample|myInstanceField");
   35.97 -        expected.add("J ;");
   35.98 -
   35.99 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
  35.100 -        final MockSink out = new MockSink();
  35.101 -        jsniCommentTokenizer.process(in, out);
  35.102 -
  35.103 -        Assert.assertEquals(expected, out.out);
  35.104 -    }
  35.105 -
  35.106 -
  35.107 -    @Test
  35.108 -    public void testProcess_static_method() throws IOException {
  35.109 -        final String in = " @com.google.gwt.examples.JSNIExample::staticFoo(Ljava/lang/String;)(s);";
  35.110 -        final List<String> expected = new ArrayList<String>();
  35.111 -        expected.add("J  ");
  35.112 -        expected.add("M com.google.gwt.examples.JSNIExample|staticFoo|Ljava/lang/String;");
  35.113 -        expected.add("J (s);");
  35.114 -
  35.115 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
  35.116 -        final MockSink out = new MockSink();
  35.117 -        jsniCommentTokenizer.process(in, out);
  35.118 -
  35.119 -        Assert.assertEquals(expected, out.out);
  35.120 -    }
  35.121 -
  35.122 -
  35.123 -    @Test
  35.124 -    public void testProcess_instance_method() throws IOException {
  35.125 -        final String in = " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);";
  35.126 -        final List<String> expected = new ArrayList<String>();
  35.127 -        expected.add("J  x.");
  35.128 -        expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;");
  35.129 -        expected.add("J (s);");
  35.130 -
  35.131 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
  35.132 -        final MockSink out = new MockSink();
  35.133 -        jsniCommentTokenizer.process(in, out);
  35.134 -
  35.135 -        Assert.assertEquals(expected, out.out);
  35.136 -    }
  35.137 -
  35.138 -
  35.139 -    @Test
  35.140 -    public void testProcess_multiline() throws IOException {
  35.141 -        final String in =
  35.142 -            " x.@com.google.gwt.examples.JSNIExample::instanceFoo(Ljava/lang/String;)(s);" +
  35.143 -            " @com.google.gwt.examples.JSNIExample::myStaticField = val + \" and stuff\";";
  35.144 -        final List<String> expected = new ArrayList<String>();
  35.145 -        expected.add("J  x.");
  35.146 -        expected.add("M com.google.gwt.examples.JSNIExample|instanceFoo|Ljava/lang/String;");
  35.147 -        expected.add("J (s); ");
  35.148 -        expected.add("F com.google.gwt.examples.JSNIExample|myStaticField");
  35.149 -        expected.add("J  = val + \" and stuff\";");
  35.150 -
  35.151 -        final JsniCommentTokenizer jsniCommentTokenizer = new JsniCommentTokenizer();
  35.152 -        final MockSink out = new MockSink();
  35.153 -        jsniCommentTokenizer.process(in, out);
  35.154 -
  35.155 -        Assert.assertEquals(expected, out.out);
  35.156 -    }
  35.157 -}
    36.1 --- a/ide/editor/src/test/java/org/apidesign/bck2brwsr/ide/editor/ManglingSinkTest.java	Tue Apr 29 15:25:58 2014 +0200
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,58 +0,0 @@
    36.4 -/**
    36.5 - * Back 2 Browser Bytecode Translator
    36.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    36.7 - *
    36.8 - * This program is free software: you can redistribute it and/or modify
    36.9 - * it under the terms of the GNU General Public License as published by
   36.10 - * the Free Software Foundation, version 2 of the License.
   36.11 - *
   36.12 - * This program is distributed in the hope that it will be useful,
   36.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.15 - * GNU General Public License for more details.
   36.16 - *
   36.17 - * You should have received a copy of the GNU General Public License
   36.18 - * along with this program. Look for COPYING file in the top folder.
   36.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   36.20 - */
   36.21 -package org.apidesign.bck2brwsr.ide.editor;
   36.22 -
   36.23 -import org.testng.Assert;
   36.24 -import org.testng.annotations.Test;
   36.25 -
   36.26 -
   36.27 -public class ManglingSinkTest {
   36.28 -
   36.29 -    @Test
   36.30 -    public void testMangle_1() {
   36.31 -        Assert.assertEquals(
   36.32 -                "binarySearch__I_3BIIB",
   36.33 -                ManglingSink.mangle("java.util.Arrays", "binarySearch", "[BIIB")
   36.34 -        );
   36.35 -    }
   36.36 -
   36.37 -    @Test
   36.38 -    public void testMangle_2() {
   36.39 -        Assert.assertEquals(
   36.40 -                "sort__V_3I",
   36.41 -                ManglingSink.mangle("java.util.Arrays", "sort", "[I")
   36.42 -        );
   36.43 -    }
   36.44 -
   36.45 -    @Test
   36.46 -    public void testMangle_3() {
   36.47 -        Assert.assertEquals(
   36.48 -                "binarySearch__I_3Ljava_lang_Object_2IILjava_lang_Object_2",
   36.49 -                ManglingSink.mangle("java.util.Arrays", "binarySearch", "[Ljava/lang/Object;IILjava/lang/Object;")
   36.50 -        );
   36.51 -    }
   36.52 -
   36.53 -
   36.54 -    @Test
   36.55 -    public void testField() {
   36.56 -        final ManglingSink manglingSink = new ManglingSink();
   36.57 -        manglingSink.field(null, "value");
   36.58 -
   36.59 -        Assert.assertEquals("_value()", manglingSink.toString());
   36.60 -    }
   36.61 -}
    37.1 --- a/ide/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,29 +0,0 @@
    37.4 -<?xml version="1.0" encoding="UTF-8"?>
    37.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">
    37.6 -  <modelVersion>4.0.0</modelVersion>
    37.7 -  <parent>
    37.8 -    <artifactId>bck2brwsr</artifactId>
    37.9 -    <groupId>org.apidesign</groupId>
   37.10 -    <version>0.8-SNAPSHOT</version>
   37.11 -  </parent>
   37.12 -  <groupId>org.apidesign.bck2brwsr</groupId>
   37.13 -  <artifactId>ide</artifactId>
   37.14 -  <version>0.8-SNAPSHOT</version>
   37.15 -  <packaging>pom</packaging>
   37.16 -  <name>IDE Support</name>
   37.17 -  <modules>
   37.18 -    <module>editor</module>
   37.19 -  </modules>
   37.20 -  <build>
   37.21 -      <plugins>
   37.22 -          <plugin>
   37.23 -              <groupId>org.apache.maven.plugins</groupId>
   37.24 -              <artifactId>maven-deploy-plugin</artifactId>
   37.25 -              <version>2.7</version>
   37.26 -              <configuration>
   37.27 -                  <skip>true</skip>
   37.28 -              </configuration>
   37.29 -          </plugin>      
   37.30 -      </plugins>
   37.31 -  </build>
   37.32 -</project>
    38.1 --- a/javaquery/api/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    38.2 +++ b/javaquery/api/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    38.3 @@ -4,11 +4,11 @@
    38.4    <parent>
    38.5      <groupId>org.apidesign.bck2brwsr</groupId>
    38.6      <artifactId>javaquery</artifactId>
    38.7 -    <version>0.8-SNAPSHOT</version>
    38.8 +    <version>0.9-SNAPSHOT</version>
    38.9    </parent>
   38.10    <groupId>org.apidesign.bck2brwsr</groupId>
   38.11    <artifactId>javaquery.api</artifactId>
   38.12 -  <version>0.8-SNAPSHOT</version>
   38.13 +  <version>0.9-SNAPSHOT</version>
   38.14    <name>JavaQuery API</name>
   38.15    <url>http://maven.apache.org</url>
   38.16      <build>
    39.1 --- a/javaquery/demo-calculator-dynamic/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    39.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    39.3 @@ -4,7 +4,7 @@
    39.4  
    39.5    <groupId>org.apidesign.bck2brwsr</groupId>
    39.6    <artifactId>demo.calculator</artifactId>
    39.7 -  <version>0.8-SNAPSHOT</version>
    39.8 +  <version>0.9-SNAPSHOT</version>
    39.9    <packaging>jar</packaging>
   39.10  
   39.11    <name>JavaQuery Demo - Calculator</name>
    40.1 --- a/javaquery/demo-calculator/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    40.2 +++ b/javaquery/demo-calculator/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    40.3 @@ -4,7 +4,7 @@
    40.4  
    40.5    <groupId>org.apidesign.bck2brwsr</groupId>
    40.6    <artifactId>demo.static.calculator</artifactId>
    40.7 -  <version>0.8-SNAPSHOT</version>
    40.8 +  <version>0.9-SNAPSHOT</version>
    40.9    <packaging>jar</packaging>
   40.10  
   40.11    <name>JavaQuery Demo - Calculator - Static Compilation</name>
    41.1 --- a/javaquery/demo-twitter/bck2brwsr-assembly.xml	Tue Apr 29 15:25:58 2014 +0200
    41.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.3 @@ -1,62 +0,0 @@
    41.4 -<?xml version="1.0"?>
    41.5 -<!--
    41.6 -
    41.7 -    Back 2 Browser Bytecode Translator
    41.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    41.9 -
   41.10 -    This program is free software: you can redistribute it and/or modify
   41.11 -    it under the terms of the GNU General Public License as published by
   41.12 -    the Free Software Foundation, version 2 of the License.
   41.13 -
   41.14 -    This program is distributed in the hope that it will be useful,
   41.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.17 -    GNU General Public License for more details.
   41.18 -
   41.19 -    You should have received a copy of the GNU General Public License
   41.20 -    along with this program. Look for COPYING file in the top folder.
   41.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
   41.22 -
   41.23 --->
   41.24 -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   41.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">
   41.26 -  
   41.27 -  <id>bck2brwsr</id>
   41.28 -  <formats>
   41.29 -      <format>zip</format>
   41.30 -  </formats>
   41.31 -  <baseDirectory>public_html</baseDirectory>
   41.32 -  <dependencySets>
   41.33 -    <dependencySet>
   41.34 -        <useProjectArtifact>false</useProjectArtifact>
   41.35 -        <scope>runtime</scope>
   41.36 -        <outputDirectory>lib</outputDirectory>
   41.37 -        <includes>
   41.38 -            <include>*:jar</include>
   41.39 -            <include>*:rt</include>
   41.40 -        </includes>
   41.41 -    </dependencySet>
   41.42 -  </dependencySets> 
   41.43 -  <fileSets>
   41.44 -      <fileSet>
   41.45 -          <directory>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/</directory>
   41.46 -          <includes>
   41.47 -              <include>**/*</include>
   41.48 -          </includes>
   41.49 -          <excludes>
   41.50 -              <exclude>**/*.class</exclude>
   41.51 -          </excludes>
   41.52 -          <outputDirectory>/</outputDirectory>
   41.53 -      </fileSet>
   41.54 -  </fileSets>
   41.55 -  <files>
   41.56 -    <file>
   41.57 -      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   41.58 -      <outputDirectory>/</outputDirectory>
   41.59 -    </file>
   41.60 -    <file>
   41.61 -      <source>${project.build.directory}/bck2brwsr.js</source>
   41.62 -      <outputDirectory>/</outputDirectory>
   41.63 -    </file>
   41.64 -  </files>
   41.65 -</assembly>
   41.66 \ No newline at end of file
    42.1 --- a/javaquery/demo-twitter/nb-configuration.xml	Tue Apr 29 15:25:58 2014 +0200
    42.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.3 @@ -1,37 +0,0 @@
    42.4 -<?xml version="1.0" encoding="UTF-8"?>
    42.5 -<!--
    42.6 -
    42.7 -    Back 2 Browser Bytecode Translator
    42.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    42.9 -
   42.10 -    This program is free software: you can redistribute it and/or modify
   42.11 -    it under the terms of the GNU General Public License as published by
   42.12 -    the Free Software Foundation, version 2 of the License.
   42.13 -
   42.14 -    This program is distributed in the hope that it will be useful,
   42.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.17 -    GNU General Public License for more details.
   42.18 -
   42.19 -    You should have received a copy of the GNU General Public License
   42.20 -    along with this program. Look for COPYING file in the top folder.
   42.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
   42.22 -
   42.23 --->
   42.24 -<project-shared-configuration>
   42.25 -    <!--
   42.26 -This file contains additional configuration written by modules in the NetBeans IDE.
   42.27 -The configuration is intended to be shared among all the users of project and
   42.28 -therefore it is assumed to be part of version control checkout.
   42.29 -Without this configuration present, some functionality in the IDE may be limited or fail altogether.
   42.30 --->
   42.31 -    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
   42.32 -        <!--
   42.33 -Properties that influence various parts of the IDE, especially code formatting and the like. 
   42.34 -You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
   42.35 -That way multiple projects can share the same settings (useful for formatting rules for example).
   42.36 -Any value defined here will override the pom.xml file value but is only applicable to the current project.
   42.37 --->
   42.38 -        <netbeans.compile.on.save>none</netbeans.compile.on.save>
   42.39 -    </properties>
   42.40 -</project-shared-configuration>
    43.1 --- a/javaquery/demo-twitter/nbactions.xml	Tue Apr 29 15:25:58 2014 +0200
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,29 +0,0 @@
    43.4 -<?xml version="1.0" encoding="UTF-8"?>
    43.5 -<!--
    43.6 -
    43.7 -    Back 2 Browser Bytecode Translator
    43.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    43.9 -
   43.10 -    This program is free software: you can redistribute it and/or modify
   43.11 -    it under the terms of the GNU General Public License as published by
   43.12 -    the Free Software Foundation, version 2 of the License.
   43.13 -
   43.14 -    This program is distributed in the hope that it will be useful,
   43.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.17 -    GNU General Public License for more details.
   43.18 -
   43.19 -    You should have received a copy of the GNU General Public License
   43.20 -    along with this program. Look for COPYING file in the top folder.
   43.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
   43.22 -
   43.23 --->
   43.24 -<actions>
   43.25 -    <action>
   43.26 -        <actionName>run</actionName>
   43.27 -        <goals>
   43.28 -            <goal>process-classes</goal>
   43.29 -            <goal>bck2brwsr:brwsr</goal>
   43.30 -        </goals>
   43.31 -    </action>
   43.32 -</actions>
    44.1 --- a/javaquery/demo-twitter/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    44.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3 @@ -1,151 +0,0 @@
    44.4 -<?xml version="1.0" encoding="UTF-8"?>
    44.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">
    44.6 -  <modelVersion>4.0.0</modelVersion>
    44.7 -  <parent>
    44.8 -    <artifactId>javaquery</artifactId>
    44.9 -    <groupId>org.apidesign.bck2brwsr</groupId>
   44.10 -    <version>0.8-SNAPSHOT</version>
   44.11 -  </parent>
   44.12 -
   44.13 -  <groupId>org.apidesign.bck2brwsr</groupId>
   44.14 -  <artifactId>demo-twitter</artifactId>
   44.15 -  <version>0.8-SNAPSHOT</version>
   44.16 -  <packaging>jar</packaging>
   44.17 -
   44.18 -  <name>Bck2Brwsr's Twttr</name>
   44.19 -  <description>
   44.20 -      Rewrite of knockoutjs example to use model written in Java and
   44.21 -      execute using Bck2Brwsr virtual machine.
   44.22 -  </description>
   44.23 -
   44.24 -  <repositories>
   44.25 -      <repository>
   44.26 -          <id>java.net</id>
   44.27 -          <name>Java.net</name>
   44.28 -          <url>https://maven.java.net/content/repositories/releases/</url>
   44.29 -          <snapshots>
   44.30 -          </snapshots>
   44.31 -      </repository>
   44.32 -      <repository>
   44.33 -          <id>netbeans</id>
   44.34 -          <name>NetBeans</name>
   44.35 -          <url>http://bits.netbeans.org/maven2/</url>
   44.36 -      </repository>
   44.37 -  </repositories>
   44.38 -  <pluginRepositories>
   44.39 -      <pluginRepository>
   44.40 -          <id>java.net</id>
   44.41 -          <name>Java.net</name>
   44.42 -          <url>https://maven.java.net/content/repositories/releases/</url>
   44.43 -          <snapshots>
   44.44 -          </snapshots>
   44.45 -      </pluginRepository>
   44.46 -  </pluginRepositories>
   44.47 -
   44.48 -  <properties>
   44.49 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   44.50 -    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
   44.51 -  </properties>
   44.52 -  <build>
   44.53 -      <plugins>
   44.54 -            <plugin>
   44.55 -                <groupId>org.apidesign.bck2brwsr</groupId>
   44.56 -                <artifactId>bck2brwsr-maven-plugin</artifactId>
   44.57 -                <version>${project.version}</version>
   44.58 -                <executions>
   44.59 -                    <execution>
   44.60 -                        <goals>
   44.61 -                            <goal>brwsr</goal>
   44.62 -                            <goal>j2js</goal>
   44.63 -                        </goals>
   44.64 -                    </execution>
   44.65 -                </executions>
   44.66 -                <configuration>
   44.67 -                    <startpage>org/apidesign/bck2brwsr/demo/twitter/index.html</startpage>
   44.68 -                    <javascript>${project.build.directory}/bck2brwsr.js</javascript>
   44.69 -                    <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
   44.70 -                </configuration>
   44.71 -            </plugin>
   44.72 -         <plugin>
   44.73 -            <groupId>org.apache.maven.plugins</groupId>
   44.74 -            <artifactId>maven-compiler-plugin</artifactId>
   44.75 -            <version>2.3.2</version>
   44.76 -            <configuration>
   44.77 -               <source>1.7</source>
   44.78 -               <target>1.7</target>
   44.79 -            </configuration>
   44.80 -         </plugin>
   44.81 -         <plugin>
   44.82 -             <groupId>org.apache.maven.plugins</groupId>
   44.83 -             <artifactId>maven-jar-plugin</artifactId>
   44.84 -             <version>2.4</version>
   44.85 -             <configuration>
   44.86 -                 <archive>
   44.87 -                     <manifest>
   44.88 -                         <addClasspath>true</addClasspath>
   44.89 -                         <classpathPrefix>lib/</classpathPrefix>
   44.90 -                     </manifest>
   44.91 -                 </archive>
   44.92 -             </configuration>
   44.93 -         </plugin>
   44.94 -         <plugin>
   44.95 -           <groupId>org.apache.maven.plugins</groupId>
   44.96 -           <artifactId>maven-deploy-plugin</artifactId>
   44.97 -           <version>2.7</version>
   44.98 -           <configuration>
   44.99 -             <skip>true</skip>
  44.100 -           </configuration>
  44.101 -         </plugin>      
  44.102 -         <plugin>
  44.103 -             <artifactId>maven-assembly-plugin</artifactId>
  44.104 -             <version>2.4</version>
  44.105 -             <executions>
  44.106 -                 <execution>
  44.107 -                     <id>distro-assembly</id>
  44.108 -                     <phase>package</phase>
  44.109 -                     <goals>
  44.110 -                         <goal>single</goal>
  44.111 -                     </goals>
  44.112 -                     <configuration>
  44.113 -                         <descriptors>
  44.114 -                             <descriptor>bck2brwsr-assembly.xml</descriptor>
  44.115 -                         </descriptors>
  44.116 -                     </configuration>
  44.117 -                 </execution>
  44.118 -             </executions>                
  44.119 -         </plugin>      
  44.120 -      </plugins>
  44.121 -  </build>
  44.122 -
  44.123 -  <dependencies>
  44.124 -    <dependency>
  44.125 -      <groupId>org.apidesign.bck2brwsr</groupId>
  44.126 -      <artifactId>emul</artifactId>
  44.127 -      <version>${project.version}</version>
  44.128 -      <classifier>rt</classifier>
  44.129 -    </dependency>
  44.130 -    <dependency>
  44.131 -      <groupId>org.apidesign.bck2brwsr</groupId>
  44.132 -      <artifactId>javaquery.api</artifactId>
  44.133 -      <version>${project.version}</version>
  44.134 -    </dependency>
  44.135 -    <dependency>
  44.136 -      <groupId>org.testng</groupId>
  44.137 -      <artifactId>testng</artifactId>
  44.138 -      <version>6.5.2</version>
  44.139 -      <scope>test</scope>
  44.140 -    </dependency>
  44.141 -    <dependency>
  44.142 -      <groupId>org.apidesign.bck2brwsr</groupId>
  44.143 -      <artifactId>vmtest</artifactId>
  44.144 -      <version>${project.version}</version>
  44.145 -      <scope>test</scope>
  44.146 -    </dependency>
  44.147 -    <dependency>
  44.148 -      <groupId>org.apidesign.bck2brwsr</groupId>
  44.149 -      <artifactId>launcher.http</artifactId>
  44.150 -      <version>${project.version}</version>
  44.151 -      <scope>runtime</scope>
  44.152 -    </dependency>
  44.153 -  </dependencies>
  44.154 -</project>
    45.1 --- a/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java	Tue Apr 29 15:25:58 2014 +0200
    45.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.3 @@ -1,194 +0,0 @@
    45.4 -/**
    45.5 - * Back 2 Browser Bytecode Translator
    45.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    45.7 - *
    45.8 - * This program is free software: you can redistribute it and/or modify
    45.9 - * it under the terms of the GNU General Public License as published by
   45.10 - * the Free Software Foundation, version 2 of the License.
   45.11 - *
   45.12 - * This program is distributed in the hope that it will be useful,
   45.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   45.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   45.15 - * GNU General Public License for more details.
   45.16 - *
   45.17 - * You should have received a copy of the GNU General Public License
   45.18 - * along with this program. Look for COPYING file in the top folder.
   45.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   45.20 - */
   45.21 -package org.apidesign.bck2brwsr.demo.twitter;
   45.22 -
   45.23 -import java.util.Arrays;
   45.24 -import java.util.List;
   45.25 -import org.apidesign.bck2brwsr.htmlpage.api.*;
   45.26 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
   45.27 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
   45.28 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   45.29 -
   45.30 -/** Controller class for access to Twitter.
   45.31 - * 
   45.32 - * @author Jaroslav Tulach
   45.33 - */
   45.34 -@Page(xhtml="index.html", className="TwitterModel", properties={
   45.35 -    @Property(name="savedLists", type=Tweeters.class, array = true),
   45.36 -    @Property(name="activeTweetersName", type=String.class),
   45.37 -    @Property(name="activeTweeters", type=String.class, array = true),
   45.38 -    @Property(name="userNameToAdd", type=String.class),
   45.39 -    @Property(name="currentTweets", type=Tweet.class, array = true)
   45.40 -})
   45.41 -public class TwitterClient {
   45.42 -    @Model(className = "Tweeters", properties = {
   45.43 -        @Property(name="name", type = String.class),
   45.44 -        @Property(name="userNames", type = String.class, array = true)
   45.45 -    })
   45.46 -    static class Twttrs {
   45.47 -    }
   45.48 -    @Model(className = "Tweet", properties = {
   45.49 -        @Property(name = "from_user", type = String.class),
   45.50 -        @Property(name = "from_user_id", type = int.class),
   45.51 -        @Property(name = "profile_image_url", type = String.class),
   45.52 -        @Property(name = "text", type = String.class),
   45.53 -        @Property(name = "created_at", type = String.class),
   45.54 -    })
   45.55 -    static final class Twt {
   45.56 -        @ComputedProperty static String html(String text) {
   45.57 -            StringBuilder sb = new StringBuilder(320);
   45.58 -            for (int pos = 0;;) {
   45.59 -                int http = text.indexOf("http", pos);
   45.60 -                if (http == -1) {
   45.61 -                    sb.append(text.substring(pos));
   45.62 -                    return sb.toString();
   45.63 -                }
   45.64 -                int spc = text.indexOf(' ', http);
   45.65 -                if (spc == -1) {
   45.66 -                    spc = text.length();
   45.67 -                }
   45.68 -                sb.append(text.substring(pos, http));
   45.69 -                String url = text.substring(http, spc);
   45.70 -                sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
   45.71 -                pos = spc;
   45.72 -            }
   45.73 -        }
   45.74 -        
   45.75 -        @ComputedProperty static String userUrl(String from_user) {
   45.76 -            return "http://twitter.com/" + from_user;
   45.77 -        }
   45.78 -    }
   45.79 -    @Model(className = "TwitterQuery", properties = {
   45.80 -        @Property(array = true, name = "results", type = Twt.class)
   45.81 -    })
   45.82 -    public static final class TwttrQr {
   45.83 -    }
   45.84 -    
   45.85 -    @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
   45.86 -    static void queryTweets(TwitterModel page, TwitterQuery q) {
   45.87 -        page.getCurrentTweets().clear();
   45.88 -        page.getCurrentTweets().addAll(q.getResults());
   45.89 -    }
   45.90 -    
   45.91 -    @OnPropertyChange("activeTweetersName")
   45.92 -    static void changeTweetersList(TwitterModel model) {
   45.93 -        Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());        
   45.94 -        model.getActiveTweeters().clear();
   45.95 -        model.getActiveTweeters().addAll(people.getUserNames());
   45.96 -    }
   45.97 -    
   45.98 -    @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
   45.99 -    static void refreshTweets(TwitterModel model) {
  45.100 -        StringBuilder sb = new StringBuilder();
  45.101 -        sb.append("rpp=25&q=");
  45.102 -        String sep = "";
  45.103 -        for (String p : model.getActiveTweeters()) {
  45.104 -            sb.append(sep);
  45.105 -            sb.append("from:");
  45.106 -            sb.append(p);
  45.107 -            sep = " OR ";
  45.108 -        }
  45.109 -        model.queryTweets("http://search.twitter.com", sb.toString());
  45.110 -    }
  45.111 -    
  45.112 -    static {
  45.113 -        final TwitterModel model = new TwitterModel();
  45.114 -        final List<Tweeters> svdLst = model.getSavedLists();
  45.115 -        svdLst.add(newTweeters("API Design", "JaroslavTulach"));
  45.116 -        svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
  45.117 -        svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
  45.118 -        svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
  45.119 -        svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
  45.120 -
  45.121 -        model.setActiveTweetersName("NetBeans");
  45.122 -
  45.123 -        model.applyBindings();
  45.124 -    }
  45.125 -    
  45.126 -    @ComputedProperty
  45.127 -    static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
  45.128 -        Tweeters tw = findByName(savedLists, activeTweetersName);
  45.129 -        if (activeTweeters == null) {
  45.130 -            return false;
  45.131 -        }
  45.132 -        return !tw.getUserNames().equals(activeTweeters);
  45.133 -    }
  45.134 -    
  45.135 -    @ComputedProperty
  45.136 -    static int activeTweetersCount(List<String> activeTweeters) {
  45.137 -        return activeTweeters.size();
  45.138 -    }
  45.139 -    
  45.140 -    @ComputedProperty
  45.141 -    static boolean userNameToAddIsValid(
  45.142 -        String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
  45.143 -    ) {
  45.144 -        return userNameToAdd != null && 
  45.145 -            userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
  45.146 -            !activeTweeters.contains(userNameToAdd);
  45.147 -    }
  45.148 -    
  45.149 -    @OnFunction
  45.150 -    static void deleteList(TwitterModel model) {
  45.151 -        final List<Tweeters> sl = model.getSavedLists();
  45.152 -        sl.remove(findByName(sl, model.getActiveTweetersName()));
  45.153 -        if (sl.isEmpty()) {
  45.154 -            final Tweeters t = new Tweeters();
  45.155 -            t.setName("New");
  45.156 -            sl.add(t);
  45.157 -        }
  45.158 -        model.setActiveTweetersName(sl.get(0).getName());
  45.159 -    }
  45.160 -    
  45.161 -    @OnFunction
  45.162 -    static void saveChanges(TwitterModel model) {
  45.163 -        Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
  45.164 -        int indx = model.getSavedLists().indexOf(t);
  45.165 -        if (indx != -1) {
  45.166 -            t.setName(model.getActiveTweetersName());
  45.167 -            t.getUserNames().clear();
  45.168 -            t.getUserNames().addAll(model.getActiveTweeters());
  45.169 -        }
  45.170 -    }
  45.171 -    
  45.172 -    @OnFunction
  45.173 -    static void addUser(TwitterModel model) {
  45.174 -        String n = model.getUserNameToAdd();
  45.175 -        model.getActiveTweeters().add(n);
  45.176 -    }
  45.177 -    @OnFunction
  45.178 -    static void removeUser(String data, TwitterModel model) {
  45.179 -        model.getActiveTweeters().remove(data);
  45.180 -    }
  45.181 -    
  45.182 -    private static Tweeters findByName(List<Tweeters> list, String name) {
  45.183 -        for (Tweeters l : list) {
  45.184 -            if (l.getName() != null && l.getName().equals(name)) {
  45.185 -                return l;
  45.186 -            }
  45.187 -        }
  45.188 -        return list.isEmpty() ? new Tweeters() : list.get(0);
  45.189 -    }
  45.190 -    
  45.191 -    private static Tweeters newTweeters(String listName, String... userNames) {
  45.192 -        Tweeters t = new Tweeters();
  45.193 -        t.setName(listName);
  45.194 -        t.getUserNames().addAll(Arrays.asList(userNames));
  45.195 -        return t;
  45.196 -    }
  45.197 -}
    46.1 --- a/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html	Tue Apr 29 15:25:58 2014 +0200
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,99 +0,0 @@
    46.4 -<?xml version="1.0" encoding="UTF-8"?>
    46.5 -<!--
    46.6 -
    46.7 -    Back 2 Browser Bytecode Translator
    46.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    46.9 -
   46.10 -    This program is free software: you can redistribute it and/or modify
   46.11 -    it under the terms of the GNU General Public License as published by
   46.12 -    the Free Software Foundation, version 2 of the License.
   46.13 -
   46.14 -    This program is distributed in the hope that it will be useful,
   46.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   46.17 -    GNU General Public License for more details.
   46.18 -
   46.19 -    You should have received a copy of the GNU General Public License
   46.20 -    along with this program. Look for COPYING file in the top folder.
   46.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
   46.22 -
   46.23 --->
   46.24 -
   46.25 -<!--
   46.26 -    Copied from knockout.js Twitter example:
   46.27 -    http://knockoutjs.com/examples/twitter.html
   46.28 --->
   46.29 -
   46.30 -<!DOCTYPE html>
   46.31 -<html xmlns="http://www.w3.org/1999/xhtml">
   46.32 -    <head>
   46.33 -        <title>Bck2Brwsr's Twitter</title>
   46.34 -    </head>
   46.35 -    <body>
   46.36 -        <link href='twitterExample.css' rel='Stylesheet' ></link>
   46.37 -        
   46.38 -        <style type='text/css'>
   46.39 -           .liveExample select { height: 1.7em; }
   46.40 -           .liveExample button { height: 2em; }
   46.41 -        </style>
   46.42 -        
   46.43 -        
   46.44 -        <h2>Bck2Brwsr's Twitter</h2>
   46.45 -        
   46.46 -        <p>
   46.47 -        This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
   46.48 -        uses almost unmodified HTML code. It just changes the model. It 
   46.49 -        is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
   46.50 -        virtual machine. The Java source code has about 190 lines and is available 
   46.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>
   46.52 -        - in fact it may even be more dense than the original JavaScript model.
   46.53 -        </p>
   46.54 -        
   46.55 -        <div class='liveExample'>
   46.56 -            <div class='configuration'>
   46.57 -                <div class='listChooser'>
   46.58 -                    <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
   46.59 -                    <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button> 
   46.60 -                    <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
   46.61 -                </div>
   46.62 -
   46.63 -                <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
   46.64 -                <div class='currentUsers' >
   46.65 -                    <ul data-bind='foreach: activeTweeters'>
   46.66 -                        <li>
   46.67 -                            <button data-bind='click: $root.removeUser'>Remove</button>
   46.68 -                            <div data-bind='text: $data'> </div>
   46.69 -                        </li>
   46.70 -                    </ul>
   46.71 -                </div>
   46.72 -
   46.73 -                <form data-bind='submit: addUser'>
   46.74 -                    <label>Add user:</label>
   46.75 -                    <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
   46.76 -                    <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
   46.77 -                </form>
   46.78 -            </div>
   46.79 -            <div class='tweets'>
   46.80 -                <div class='loadingIndicator'>Loading...</div>
   46.81 -                <table data-bind='foreach: currentTweets' width='100%'>
   46.82 -                    <tr>
   46.83 -                        <td><img data-bind='attr: { src: profile_image_url }' /></td>
   46.84 -                        <td>
   46.85 -                            <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
   46.86 -                            <span data-bind='html: html'> </span>
   46.87 -                            <div class='tweetInfo' data-bind='text: created_at'> </div>
   46.88 -                        </td>
   46.89 -                    </tr>
   46.90 -                </table>
   46.91 -            </div>
   46.92 -        </div>
   46.93 -        
   46.94 -        <script src="bck2brwsr.js"></script>
   46.95 -        <script type="text/javascript">
   46.96 -            var vm = bck2brwsr('demo-twitter-0.8-SNAPSHOT.jar');
   46.97 -            vm.loadClass('org.apidesign.bck2brwsr.demo.twitter.TwitterClient');
   46.98 -        </script>
   46.99 -
  46.100 -
  46.101 -    </body>
  46.102 -</html>
    47.1 --- a/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css	Tue Apr 29 15:25:58 2014 +0200
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,50 +0,0 @@
    47.4 -/**
    47.5 - * Back 2 Browser Bytecode Translator
    47.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    47.7 - *
    47.8 - * This program is free software: you can redistribute it and/or modify
    47.9 - * it under the terms of the GNU General Public License as published by
   47.10 - * the Free Software Foundation, version 2 of the License.
   47.11 - *
   47.12 - * This program is distributed in the hope that it will be useful,
   47.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   47.15 - * GNU General Public License for more details.
   47.16 - *
   47.17 - * You should have received a copy of the GNU General Public License
   47.18 - * along with this program. Look for COPYING file in the top folder.
   47.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   47.20 - */
   47.21 -
   47.22 -/*
   47.23 -    Copied from knockout.js Twitter example:
   47.24 -    http://knockoutjs.com/examples/twitter.html
   47.25 -*/
   47.26 -
   47.27 -.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
   47.28 -.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
   47.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; }
   47.30 -.tweets table { border-width: 0;}
   47.31 -.tweets tr { vertical-align: top; }
   47.32 -.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
   47.33 -.tweets img { width: 4em; }
   47.34 -.tweetInfo { color: Gray; font-size: 0.9em; }
   47.35 -.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
   47.36 -input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
   47.37 -
   47.38 -.listChooser select, .listChooser button { vertical-align:top; }
   47.39 -.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
   47.40 -.listChooser button { width: 19%; height:1.68em; float:right; }
   47.41 -
   47.42 -.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
   47.43 -.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
   47.44 -.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
   47.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; }
   47.46 -.currentUsers li div { padding: 0.6em; }
   47.47 -.currentUsers li:hover { background-color: #EEC; }
   47.48 -
   47.49 -.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
   47.50 -.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
   47.51 -.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
   47.52 -
   47.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; }
    48.1 --- a/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java	Tue Apr 29 15:25:58 2014 +0200
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,67 +0,0 @@
    48.4 -/**
    48.5 - * Back 2 Browser Bytecode Translator
    48.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    48.7 - *
    48.8 - * This program is free software: you can redistribute it and/or modify
    48.9 - * it under the terms of the GNU General Public License as published by
   48.10 - * the Free Software Foundation, version 2 of the License.
   48.11 - *
   48.12 - * This program is distributed in the hope that it will be useful,
   48.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.15 - * GNU General Public License for more details.
   48.16 - *
   48.17 - * You should have received a copy of the GNU General Public License
   48.18 - * along with this program. Look for COPYING file in the top folder.
   48.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   48.20 - */
   48.21 -package org.apidesign.bck2brwsr.demo.twitter;
   48.22 -
   48.23 -import java.util.List;
   48.24 -import static org.testng.Assert.*;
   48.25 -import org.testng.annotations.BeforeMethod;
   48.26 -import org.testng.annotations.Test;
   48.27 -
   48.28 -/** We can unit test the TwitterModel smoothly.
   48.29 - *
   48.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   48.31 - */
   48.32 -public class TwitterClientTest {
   48.33 -    private TwitterModel model;
   48.34 -    
   48.35 -
   48.36 -    @BeforeMethod
   48.37 -    public void initModel() {
   48.38 -        model = new TwitterModel().applyBindings();
   48.39 -    }
   48.40 -
   48.41 -    @Test public void testIsValidToAdd() {
   48.42 -        model.setUserNameToAdd("Joe");
   48.43 -        Tweeters t = new Tweeters();
   48.44 -        t.setName("test");
   48.45 -        model.getSavedLists().add(t);
   48.46 -        model.setActiveTweetersName("test");
   48.47 -        
   48.48 -        assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
   48.49 -        TwitterClient.addUser(model);
   48.50 -        assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
   48.51 -        assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
   48.52 -        
   48.53 -        List<String> mod = model.getActiveTweeters();
   48.54 -        assertTrue(model.isHasUnsavedChanges(), "We have modifications");
   48.55 -        assertEquals(mod.size(), 1, "One element in the list");
   48.56 -        assertEquals(mod.get(0), "Joe", "Its name is Joe");
   48.57 -        
   48.58 -        assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
   48.59 -        
   48.60 -        TwitterClient.saveChanges(model);
   48.61 -        assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
   48.62 -        
   48.63 -        assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
   48.64 -    }
   48.65 -    
   48.66 -    @Test public void httpAtTheEnd() {
   48.67 -        String res = TwitterClient.Twt.html("Ahoj http://kuk");
   48.68 -        assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
   48.69 -    }
   48.70 -}
    49.1 --- a/javaquery/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    49.2 +++ b/javaquery/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    49.3 @@ -4,17 +4,16 @@
    49.4    <parent>
    49.5      <artifactId>bck2brwsr</artifactId>
    49.6      <groupId>org.apidesign</groupId>
    49.7 -    <version>0.8-SNAPSHOT</version>
    49.8 +    <version>0.9-SNAPSHOT</version>
    49.9    </parent>
   49.10    <groupId>org.apidesign.bck2brwsr</groupId>
   49.11    <artifactId>javaquery</artifactId>
   49.12 -  <version>0.8-SNAPSHOT</version>
   49.13 +  <version>0.9-SNAPSHOT</version>
   49.14    <packaging>pom</packaging>
   49.15    <name>JavaQuery API and Demo</name>
   49.16      <modules>
   49.17          <module>api</module>
   49.18          <module>demo-calculator</module>
   49.19          <module>demo-calculator-dynamic</module>
   49.20 -    <module>demo-twitter</module>
   49.21    </modules>
   49.22 -</project>
   49.23 \ No newline at end of file
   49.24 +</project>
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/ko/archetype-test/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    50.3 @@ -0,0 +1,48 @@
    50.4 +<?xml version="1.0"?>
    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 +        <groupId>org.apidesign.bck2brwsr</groupId>
    50.9 +        <artifactId>ko</artifactId>
   50.10 +        <version>0.9-SNAPSHOT</version>
   50.11 +    </parent>
   50.12 +    <groupId>org.apidesign.bck2brwsr</groupId>
   50.13 +    <artifactId>ko-archetype-test</artifactId>
   50.14 +    <version>0.9-SNAPSHOT</version>
   50.15 +    <name>Knockout Bck2Brwsr Archetype Test</name>
   50.16 +    <url>http://maven.apache.org</url>
   50.17 +    <description>Verifies the Knockout &amp; net.java.html.json archetype behaves properly.</description>
   50.18 +    <properties>
   50.19 +        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   50.20 +    </properties>
   50.21 +    <dependencies>
   50.22 +        <dependency>
   50.23 +            <groupId>${project.groupId}</groupId>
   50.24 +            <artifactId>knockout4j-archetype</artifactId>
   50.25 +            <version>${project.version}</version>
   50.26 +        </dependency>
   50.27 +        <dependency>
   50.28 +            <groupId>org.testng</groupId>
   50.29 +            <artifactId>testng</artifactId>
   50.30 +            <scope>test</scope>
   50.31 +        </dependency>
   50.32 +        <dependency>                                
   50.33 +            <groupId>org.apache.maven.shared</groupId>
   50.34 +            <artifactId>maven-verifier</artifactId>
   50.35 +            <version>1.4</version>
   50.36 +            <scope>test</scope>
   50.37 +        </dependency>
   50.38 +        <dependency>
   50.39 +            <groupId>${project.groupId}</groupId>
   50.40 +            <artifactId>ko-fx</artifactId>
   50.41 +            <version>${project.version}</version>
   50.42 +            <scope>provided</scope>
   50.43 +        </dependency>
   50.44 +        <dependency>
   50.45 +            <groupId>${project.groupId}</groupId>
   50.46 +            <artifactId>ko-bck2brwsr</artifactId>
   50.47 +            <version>${project.version}</version>
   50.48 +            <scope>provided</scope>
   50.49 +        </dependency>
   50.50 +    </dependencies>
   50.51 +</project>
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/ArchetypeVersionTest.java	Wed Apr 30 15:04:10 2014 +0200
    51.3 @@ -0,0 +1,140 @@
    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.ko.archetype.test;
   51.22 +
   51.23 +import java.io.IOException;
   51.24 +import java.net.URL;
   51.25 +import javax.xml.XMLConstants;
   51.26 +import javax.xml.parsers.DocumentBuilderFactory;
   51.27 +import javax.xml.parsers.ParserConfigurationException;
   51.28 +import javax.xml.xpath.XPathConstants;
   51.29 +import javax.xml.xpath.XPathExpression;
   51.30 +import javax.xml.xpath.XPathExpressionException;
   51.31 +import javax.xml.xpath.XPathFactory;
   51.32 +import javax.xml.xpath.XPathFactoryConfigurationException;
   51.33 +import org.testng.annotations.Test;
   51.34 +import static org.testng.Assert.*;
   51.35 +import org.testng.annotations.BeforeClass;
   51.36 +import org.w3c.dom.Document;
   51.37 +import org.w3c.dom.NodeList;
   51.38 +import org.xml.sax.SAXException;
   51.39 +
   51.40 +/**
   51.41 + *
   51.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   51.43 + */
   51.44 +public class ArchetypeVersionTest {
   51.45 +    private String version;
   51.46 +    
   51.47 +    public ArchetypeVersionTest() {
   51.48 +    }
   51.49 +    
   51.50 +    @BeforeClass public void readCurrentVersion() throws Exception {
   51.51 +        version = findCurrentVersion();
   51.52 +        assertFalse(version.isEmpty(), "There should be some version string");
   51.53 +    }
   51.54 +    
   51.55 +
   51.56 +    @Test public void testComparePomDepsVersions() throws Exception {
   51.57 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   51.58 +        URL r = l.getResource("archetype-resources/pom.xml");
   51.59 +        assertNotNull(r, "Archetype pom found");
   51.60 +        
   51.61 +        final XPathFactory fact = XPathFactory.newInstance();
   51.62 +        XPathExpression xp2 = fact.newXPath().compile(
   51.63 +            "//properties/net.java.html.version/text()"
   51.64 +        );
   51.65 +        
   51.66 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
   51.67 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
   51.68 +        
   51.69 +        int snapshot = arch.indexOf("-SNAPSHOT");
   51.70 +        if (snapshot >= 0) {
   51.71 +            arch = arch.substring(0, snapshot);
   51.72 +        }
   51.73 +
   51.74 +        assertTrue(arch.matches("[0-9\\.]+"), "net.java.html.json version seems valid: " + arch);
   51.75 +    }
   51.76 +    
   51.77 +    @Test public void testCheckLauncher() throws Exception {
   51.78 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   51.79 +        URL r = l.getResource("archetype-resources/pom.xml");
   51.80 +        assertNotNull(r, "Archetype pom found");
   51.81 +        
   51.82 +        final XPathFactory fact = XPathFactory.newInstance();
   51.83 +        XPathExpression xp2 = fact.newXPath().compile(
   51.84 +            "//properties/bck2brwsr.launcher.version/text()"
   51.85 +        );
   51.86 +        
   51.87 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
   51.88 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
   51.89 +
   51.90 +        assertEquals(arch, version, "launcher dependency is on more recent version");
   51.91 +    }
   51.92 +    
   51.93 +    @Test public void testCheckBck2Brwsr() throws Exception {
   51.94 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   51.95 +        URL r = l.getResource("archetype-resources/pom.xml");
   51.96 +        assertNotNull(r, "Archetype pom found");
   51.97 +        
   51.98 +        final XPathFactory fact = XPathFactory.newInstance();
   51.99 +        XPathExpression xp2 = fact.newXPath().compile(
  51.100 +            "//properties/bck2brwsr.version/text()"
  51.101 +        );
  51.102 +        
  51.103 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  51.104 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  51.105 +        
  51.106 +        assertEquals(arch, version, "bck2brwsr dependency is on more recent version");
  51.107 +    }
  51.108 +    
  51.109 +    @Test public void testNbActions() throws Exception {
  51.110 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  51.111 +        URL r = l.getResource("archetype-resources/nbactions.xml");
  51.112 +        assertNotNull(r, "Archetype nb file found");
  51.113 +        
  51.114 +        final XPathFactory fact = XPathFactory.newInstance();
  51.115 +        XPathExpression xp2 = fact.newXPath().compile(
  51.116 +            "//goal/text()"
  51.117 +        );
  51.118 +        
  51.119 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  51.120 +        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  51.121 +        
  51.122 +        for (int i = 0; i < goals.getLength(); i++) {
  51.123 +            String s = goals.item(i).getTextContent();
  51.124 +            if (s.contains("apidesign")) {
  51.125 +                assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
  51.126 +            }
  51.127 +        }
  51.128 +    }
  51.129 +
  51.130 +    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
  51.131 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  51.132 +        URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/knockout4j-archetype/pom.xml");
  51.133 +        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
  51.134 +
  51.135 +        final XPathFactory fact = XPathFactory.newInstance();
  51.136 +        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
  51.137 +
  51.138 +        XPathExpression xp = fact.newXPath().compile("project/version/text()");
  51.139 +        
  51.140 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
  51.141 +        return xp.evaluate(dom);
  51.142 +    }
  51.143 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/VerifyArchetypeTest.java	Wed Apr 30 15:04:10 2014 +0200
    52.3 @@ -0,0 +1,133 @@
    52.4 +/**
    52.5 + * Back 2 Browser Bytecode Translator
    52.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    52.7 + *
    52.8 + * This program is free software: you can redistribute it and/or modify
    52.9 + * it under the terms of the GNU General Public License as published by
   52.10 + * the Free Software Foundation, version 2 of the License.
   52.11 + *
   52.12 + * This program is distributed in the hope that it will be useful,
   52.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.15 + * GNU General Public License for more details.
   52.16 + *
   52.17 + * You should have received a copy of the GNU General Public License
   52.18 + * along with this program. Look for COPYING file in the top folder.
   52.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   52.20 + */
   52.21 +package org.apidesign.bck2brwsr.ko.archetype.test;
   52.22 +
   52.23 +import java.io.File;
   52.24 +import java.io.IOException;
   52.25 +import java.io.InputStream;
   52.26 +import java.util.Properties;
   52.27 +import java.util.zip.ZipEntry;
   52.28 +import java.util.zip.ZipFile;
   52.29 +import org.apache.maven.it.Verifier;
   52.30 +import org.testng.annotations.Test;
   52.31 +import static org.testng.Assert.*;
   52.32 +import org.testng.reporters.Files;
   52.33 +
   52.34 +/**
   52.35 + *
   52.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   52.37 + */
   52.38 +public class VerifyArchetypeTest {
   52.39 +    @Test public void fxBrwsrCompiles() throws Exception {
   52.40 +        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
   52.41 +        generateFromArchetype(dir);
   52.42 +        
   52.43 +        File created = new File(dir, "o-a-test");
   52.44 +        assertTrue(created.isDirectory(), "Project created");
   52.45 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
   52.46 +        
   52.47 +        Verifier v = new Verifier(created.getAbsolutePath());
   52.48 +        v.executeGoal("verify");
   52.49 +        
   52.50 +        v.verifyErrorFreeLog();
   52.51 +        
   52.52 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
   52.53 +            if (l.contains("j2js")) {
   52.54 +                fail("No pre-compilaton:\n" + l);
   52.55 +            }
   52.56 +        }
   52.57 +        
   52.58 +        v.verifyTextInLog("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher");
   52.59 +        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-fxbrwsr.zip");
   52.60 +    }
   52.61 +    
   52.62 +    @Test public void bck2BrwsrCompiles() throws Exception {
   52.63 +        final File dir = new File("target/tests/b2bcompile/").getAbsoluteFile();
   52.64 +        generateFromArchetype(dir);
   52.65 +        
   52.66 +        File created = new File(dir, "o-a-test");
   52.67 +        assertTrue(created.isDirectory(), "Project created");
   52.68 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
   52.69 +        
   52.70 +        Verifier v = new Verifier(created.getAbsolutePath());
   52.71 +        Properties sysProp = v.getSystemProperties();
   52.72 +        if (Boolean.getBoolean("java.awt.headless")) {
   52.73 +            sysProp.put("java.awt.headless", "true");
   52.74 +        }
   52.75 +        v.addCliOption("-Pbck2brwsr");
   52.76 +        v.executeGoal("verify");
   52.77 +        
   52.78 +        v.verifyErrorFreeLog();
   52.79 +        
   52.80 +        // no longer does pre-compilation to JavaScript
   52.81 +        // v.verifyTextInLog("j2js");
   52.82 +        // uses Bck2BrwsrLauncher
   52.83 +        v.verifyTextInLog("BaseHTTPLauncher showBrwsr");
   52.84 +        // building zip:
   52.85 +        v.verifyTextInLog("b2bcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-bck2brwsr.zip");
   52.86 +        
   52.87 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
   52.88 +            if (l.contains("fxbrwsr")) {
   52.89 +                fail("No fxbrwsr:\n" + l);
   52.90 +            }
   52.91 +        }
   52.92 +
   52.93 +        File zip = new File(new File(created, "target"), "o-a-test-1.0-SNAPSHOT-bck2brwsr.zip");
   52.94 +        assertTrue(zip.isFile(), "Zip file with website was created");
   52.95 +        
   52.96 +        ZipFile zf = new ZipFile(zip);
   52.97 +        final ZipEntry index = zf.getEntry("public_html/index.html");
   52.98 +        assertNotNull(index, "index.html found");
   52.99 +        
  52.100 +        String txt = readText(zf.getInputStream(index));
  52.101 +        final int beg = txt.indexOf("${");
  52.102 +        if (beg >= 0) {
  52.103 +            int end = txt.indexOf("}", beg);
  52.104 +            if (end < beg) {
  52.105 +                end = txt.length();
  52.106 +            }
  52.107 +            fail("No substitutions in index.html. Found: " + txt.substring(beg, end));
  52.108 +        }
  52.109 +    }
  52.110 +
  52.111 +    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  52.112 +        Verifier v = new Verifier(dir.getAbsolutePath());
  52.113 +        v.setAutoclean(false);
  52.114 +        v.setLogFileName("generate.log");
  52.115 +        v.deleteDirectory("");
  52.116 +        dir.mkdirs();
  52.117 +        Properties sysProp = v.getSystemProperties();
  52.118 +        sysProp.put("groupId", "org.apidesign.test");
  52.119 +        sysProp.put("artifactId", "o-a-test");
  52.120 +        sysProp.put("package", "org.apidesign.test.oat");
  52.121 +        sysProp.put("archetypeGroupId", "org.apidesign.bck2brwsr");
  52.122 +        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  52.123 +        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  52.124 +        
  52.125 +        for (String p : params) {
  52.126 +            v.addCliOption(p);
  52.127 +        }
  52.128 +        v.executeGoal("archetype:generate");
  52.129 +        v.verifyErrorFreeLog();
  52.130 +        return v;
  52.131 +    }
  52.132 +    
  52.133 +    private static String readText(InputStream is) throws IOException {
  52.134 +        return Files.readFile(is);
  52.135 +    }
  52.136 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/ko/archetype/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    53.3 @@ -0,0 +1,58 @@
    53.4 +<?xml version="1.0" encoding="UTF-8"?>
    53.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">
    53.6 +  <modelVersion>4.0.0</modelVersion>
    53.7 +  <parent>
    53.8 +    <artifactId>ko</artifactId>
    53.9 +    <groupId>org.apidesign.bck2brwsr</groupId>
   53.10 +    <version>0.9-SNAPSHOT</version>
   53.11 +  </parent>
   53.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   53.13 +  <artifactId>knockout4j-archetype</artifactId>
   53.14 +  <version>0.9-SNAPSHOT</version>
   53.15 +  <packaging>jar</packaging>
   53.16 +  <name>Knockout Bck2Brwsr Maven Archetype</name>
   53.17 +  <description>
   53.18 +      HTML page with Knockout.js bindings driven by application model
   53.19 +      written in Java. Use your favorite language to code. Use
   53.20 +      HTML as a lightweight rendering toolkit. Deploy using JavaFX or 
   53.21 +      bck2brwsr virtual machine.
   53.22 +  </description>
   53.23 +  <build>
   53.24 +      <resources>
   53.25 +          <resource>
   53.26 +            <directory>src/main/resources</directory>
   53.27 +            <filtering>true</filtering>
   53.28 +            <includes>
   53.29 +                <include>**/pom.xml</include>
   53.30 +            </includes>
   53.31 +          </resource>
   53.32 +          <resource>
   53.33 +            <directory>src/main/resources</directory>
   53.34 +            <filtering>false</filtering>
   53.35 +            <excludes>
   53.36 +                <exclude>**/pom.xml</exclude>
   53.37 +            </excludes>
   53.38 +          </resource>
   53.39 +      </resources>      
   53.40 +      <plugins>
   53.41 +          <plugin>
   53.42 +              <groupId>org.apache.maven.plugins</groupId>
   53.43 +              <artifactId>maven-compiler-plugin</artifactId>
   53.44 +              <version>2.3.2</version>
   53.45 +              <configuration>
   53.46 +                  <source>1.6</source>
   53.47 +                  <target>1.6</target>
   53.48 +              </configuration>
   53.49 +          </plugin>
   53.50 +          <plugin>
   53.51 +              <groupId>org.apache.maven.plugins</groupId>
   53.52 +              <artifactId>maven-resources-plugin</artifactId>
   53.53 +              <version>2.6</version>
   53.54 +              <configuration>
   53.55 +                  <escapeString>\</escapeString>
   53.56 +                  <target>1.6</target>
   53.57 +              </configuration>
   53.58 +          </plugin>
   53.59 +      </plugins>
   53.60 +  </build>
   53.61 +</project>
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/ko/archetype/src/main/java/org/apidesign/bck2brwsr/ko/archetype/package-info.java	Wed Apr 30 15:04:10 2014 +0200
    54.3 @@ -0,0 +1,18 @@
    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.ko.archetype;
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml	Wed Apr 30 15:04:10 2014 +0200
    55.3 @@ -0,0 +1,63 @@
    55.4 +<?xml version="1.0" encoding="UTF-8"?>
    55.5 +<!--
    55.6 +
    55.7 +    Back 2 Browser Bytecode Translator
    55.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    55.9 +
   55.10 +    This program is free software: you can redistribute it and/or modify
   55.11 +    it under the terms of the GNU General Public License as published by
   55.12 +    the Free Software Foundation, version 2 of the License.
   55.13 +
   55.14 +    This program is distributed in the hope that it will be useful,
   55.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.17 +    GNU General Public License for more details.
   55.18 +
   55.19 +    You should have received a copy of the GNU General Public License
   55.20 +    along with this program. Look for COPYING file in the top folder.
   55.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   55.22 +
   55.23 +-->
   55.24 +<archetype-descriptor name="FX/Bck2Brwsr Example">
   55.25 +  <fileSets>
   55.26 +    <fileSet filtered="true" packaged="true">
   55.27 +      <directory>src/main/java</directory>
   55.28 +      <includes>
   55.29 +        <include>**/*.java</include>
   55.30 +      </includes>
   55.31 +    </fileSet>
   55.32 +    <fileSet filtered="true" packaged="false">
   55.33 +      <directory>src/main/webapp/pages</directory>
   55.34 +      <includes>
   55.35 +        <include>**/*.xhtml</include>
   55.36 +        <include>**/*.html</include>
   55.37 +        <include>**/*.css</include>
   55.38 +      </includes>
   55.39 +    </fileSet>
   55.40 +    <fileSet filtered="true" packaged="true">
   55.41 +      <directory>src/test/java</directory>
   55.42 +      <includes>
   55.43 +        <include>**/*Test.java</include>
   55.44 +      </includes>
   55.45 +    </fileSet>
   55.46 +    <fileSet filtered="true" packaged="false">
   55.47 +      <directory>src/main/assembly</directory>
   55.48 +      <includes>
   55.49 +        <include>**/*.xml</include>
   55.50 +      </includes>
   55.51 +    </fileSet>
   55.52 +    <fileSet filtered="false" packaged="false">
   55.53 +      <directory></directory>
   55.54 +      <includes>
   55.55 +        <include>nbactions*.xml</include>
   55.56 +      </includes>
   55.57 +    </fileSet>
   55.58 +    <fileSet filtered="true" packaged="false">
   55.59 +      <directory>assembly</directory>
   55.60 +      <includes>
   55.61 +        <include>fxbrwsr-assembly.xml</include>
   55.62 +        <include>bck2brwsr-assembly.xml</include>
   55.63 +      </includes>
   55.64 +    </fileSet>
   55.65 +  </fileSets>    
   55.66 +</archetype-descriptor>
   55.67 \ No newline at end of file
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml	Wed Apr 30 15:04:10 2014 +0200
    56.3 @@ -0,0 +1,14 @@
    56.4 +<?xml version="1.0" encoding="UTF-8"?>
    56.5 +<actions>
    56.6 +    <action>
    56.7 +        <actionName>run</actionName>
    56.8 +        <goals>
    56.9 +            <goal>package</goal>
   56.10 +            <goal>bck2brwsr:brwsr</goal>
   56.11 +        </goals>
   56.12 +        <properties>
   56.13 +            <skipTests>true</skipTests>
   56.14 +            <bck2brwsr.obfuscationlevel>NONE</bck2brwsr.obfuscationlevel>
   56.15 +        </properties>
   56.16 +    </action>
   56.17 +</actions>
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml	Wed Apr 30 15:04:10 2014 +0200
    57.3 @@ -0,0 +1,20 @@
    57.4 +<?xml version="1.0" encoding="UTF-8"?>
    57.5 +<actions>
    57.6 +    <action>
    57.7 +        <actionName>run</actionName>
    57.8 +        <goals>
    57.9 +            <goal>process-classes</goal>
   57.10 +            <goal>bck2brwsr:brwsr</goal>
   57.11 +        </goals>
   57.12 +    </action>
   57.13 +    <action>
   57.14 +        <actionName>debug</actionName>
   57.15 +        <goals>
   57.16 +            <goal>process-classes</goal>
   57.17 +            <goal>bck2brwsr:brwsr</goal>
   57.18 +        </goals>
   57.19 +        <properties>
   57.20 +            <jpda.listen>maven</jpda.listen>
   57.21 +        </properties>
   57.22 +    </action>
   57.23 +</actions>
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions.xml	Wed Apr 30 15:04:10 2014 +0200
    58.3 @@ -0,0 +1,20 @@
    58.4 +<?xml version="1.0" encoding="UTF-8"?>
    58.5 +<actions>
    58.6 +    <action>
    58.7 +        <actionName>run</actionName>
    58.8 +        <goals>
    58.9 +            <goal>process-classes</goal>
   58.10 +            <goal>bck2brwsr:brwsr</goal>
   58.11 +        </goals>
   58.12 +    </action>
   58.13 +    <action>
   58.14 +        <actionName>debug</actionName>
   58.15 +        <goals>
   58.16 +            <goal>process-classes</goal>
   58.17 +            <goal>bck2brwsr:brwsr</goal>
   58.18 +        </goals>
   58.19 +        <properties>
   58.20 +            <jpda.listen>maven</jpda.listen>
   58.21 +        </properties>
   58.22 +    </action>
   58.23 +</actions>
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/ko/archetype/src/main/resources/archetype-resources/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    59.3 @@ -0,0 +1,283 @@
    59.4 +<?xml version="1.0"?>
    59.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    59.6 +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    59.7 +  <modelVersion>4.0.0</modelVersion>
    59.8 +
    59.9 +  <groupId>\${groupId}</groupId>
   59.10 +  <artifactId>\${artifactId}</artifactId>
   59.11 +  <version>\${version}</version>
   59.12 +  <packaging>jar</packaging>
   59.13 +
   59.14 +  <name>\${artifactId}</name>
   59.15 +
   59.16 +  <repositories>
   59.17 +      <repository>
   59.18 +          <id>java.net</id>
   59.19 +          <name>Java.net</name>
   59.20 +          <url>https://maven.java.net/content/repositories/releases/</url>
   59.21 +          <snapshots>
   59.22 +              <enabled>true</enabled>
   59.23 +          </snapshots>
   59.24 +      </repository>
   59.25 +      <repository>
   59.26 +          <id>netbeans</id>
   59.27 +          <name>NetBeans</name>
   59.28 +          <url>http://bits.netbeans.org/maven2/</url>
   59.29 +      </repository>
   59.30 +  </repositories>
   59.31 +  <pluginRepositories>
   59.32 +      <pluginRepository>
   59.33 +          <id>java.net</id>
   59.34 +          <name>Java.net</name>
   59.35 +          <url>https://maven.java.net/content/repositories/releases/</url>
   59.36 +          <snapshots>
   59.37 +              <enabled>true</enabled>
   59.38 +          </snapshots>
   59.39 +      </pluginRepository>
   59.40 +  </pluginRepositories>
   59.41 +
   59.42 +  <properties>
   59.43 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   59.44 +    <net.java.html.version>${net.java.html.version}</net.java.html.version>
   59.45 +    <bck2brwsr.version>${project.version}</bck2brwsr.version>
   59.46 +    <bck2brwsr.launcher.version>${project.version}</bck2brwsr.launcher.version>
   59.47 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
   59.48 +    <brwsr.startpage>pages/index.html</brwsr.startpage>
   59.49 +    <netbeans.compile.on.save>none</netbeans.compile.on.save>
   59.50 +  </properties>
   59.51 +  <build>
   59.52 +      <plugins>
   59.53 +          <plugin>
   59.54 +              <groupId>org.apidesign.bck2brwsr</groupId>
   59.55 +              <artifactId>bck2brwsr-maven-plugin</artifactId>
   59.56 +              <version>\${bck2brwsr.launcher.version}</version>
   59.57 +              <executions>
   59.58 +                  <execution>
   59.59 +                      <goals>
   59.60 +                          <goal>brwsr</goal>
   59.61 +                      </goals>
   59.62 +                  </execution>
   59.63 +              </executions>
   59.64 +              <configuration>
   59.65 +                  <directory>\${basedir}/src/main/webapp/</directory>
   59.66 +                  <startpage>${brwsr.startpage}</startpage>
   59.67 +                  <launcher>${brwsr}</launcher>
   59.68 +              </configuration>
   59.69 +          </plugin>
   59.70 +          <plugin>
   59.71 +              <groupId>org.netbeans.html</groupId>
   59.72 +              <artifactId>html4j-maven-plugin</artifactId>
   59.73 +              <version>${net.java.html.version}</version>
   59.74 +              <executions>
   59.75 +                  <execution>
   59.76 +                      <id>js-classes</id>
   59.77 +                      <goals>
   59.78 +                          <goal>process-js-annotations</goal>
   59.79 +                      </goals>
   59.80 +                  </execution>
   59.81 +              </executions>
   59.82 +          </plugin>          
   59.83 +          <plugin>
   59.84 +              <groupId>org.apache.maven.plugins</groupId>
   59.85 +              <artifactId>maven-compiler-plugin</artifactId>
   59.86 +              <version>2.3.2</version>
   59.87 +              <configuration>
   59.88 +                  <source>1.7</source>
   59.89 +                  <target>1.7</target>
   59.90 +              </configuration>
   59.91 +          </plugin>
   59.92 +          <plugin>
   59.93 +              <groupId>org.apache.maven.plugins</groupId>
   59.94 +              <artifactId>maven-surefire-plugin</artifactId>
   59.95 +              <version>2.14.1</version>
   59.96 +              <configuration>
   59.97 +                  <systemPropertyVariables>
   59.98 +                      <vmtest.brwsrs>\${brwsr}</vmtest.brwsrs>
   59.99 +                  </systemPropertyVariables>
  59.100 +              </configuration>
  59.101 +          </plugin>
  59.102 +          <plugin>
  59.103 +              <groupId>org.apache.maven.plugins</groupId>
  59.104 +              <artifactId>maven-jar-plugin</artifactId>
  59.105 +              <version>2.4</version>
  59.106 +              <configuration>
  59.107 +                  <archive>
  59.108 +                      <manifest>
  59.109 +                          <addClasspath>true</addClasspath>
  59.110 +                          <classpathPrefix>lib/</classpathPrefix>
  59.111 +                      </manifest>
  59.112 +                  </archive>
  59.113 +              </configuration>
  59.114 +          </plugin>
  59.115 +          <plugin>
  59.116 +              <groupId>org.apache.maven.plugins</groupId>
  59.117 +              <artifactId>maven-deploy-plugin</artifactId>
  59.118 +              <version>2.7</version>
  59.119 +              <configuration>
  59.120 +                  <skip>true</skip>
  59.121 +              </configuration>
  59.122 +          </plugin>      
  59.123 +      </plugins>
  59.124 +  </build>
  59.125 +
  59.126 +  <dependencies>
  59.127 +    <dependency>
  59.128 +      <groupId>org.testng</groupId>
  59.129 +      <artifactId>testng</artifactId>
  59.130 +      <version>6.7</version>
  59.131 +      <scope>test</scope>
  59.132 +    </dependency>
  59.133 +    <dependency>
  59.134 +        <groupId>org.apidesign.bck2brwsr</groupId>
  59.135 +        <artifactId>launcher.http</artifactId>
  59.136 +        <version>\${bck2brwsr.launcher.version}</version>
  59.137 +        <scope>test</scope>
  59.138 +    </dependency>
  59.139 +    <dependency>
  59.140 +      <groupId>org.apidesign.bck2brwsr</groupId>
  59.141 +      <artifactId>vmtest</artifactId>
  59.142 +      <version>\${bck2brwsr.version}</version>
  59.143 +      <scope>test</scope>
  59.144 +    </dependency>
  59.145 +    <dependency>
  59.146 +      <groupId>org.netbeans.html</groupId>
  59.147 +      <artifactId>net.java.html.json</artifactId>
  59.148 +      <version>\${net.java.html.version}</version>
  59.149 +      <type>jar</type>
  59.150 +    </dependency>
  59.151 +    <dependency>
  59.152 +      <groupId>org.netbeans.html</groupId>
  59.153 +      <artifactId>net.java.html.boot</artifactId>
  59.154 +      <version>\${net.java.html.version}</version>
  59.155 +      <type>jar</type>
  59.156 +    </dependency>    
  59.157 +  </dependencies>
  59.158 +  <profiles>
  59.159 +      <profile>
  59.160 +          <id>fxbrwsr</id>
  59.161 +          <activation>
  59.162 +              <activeByDefault>true</activeByDefault>
  59.163 +          </activation>
  59.164 +          <properties>
  59.165 +              <brwsr>fxbrwsr</brwsr>
  59.166 +          </properties>
  59.167 +          <build>
  59.168 +            <plugins>
  59.169 +                <plugin>
  59.170 +                    <groupId>org.apache.maven.plugins</groupId>
  59.171 +                    <artifactId>maven-jar-plugin</artifactId>
  59.172 +                    <version>2.4</version>
  59.173 +                    <configuration>
  59.174 +                        <archive>
  59.175 +                            <manifest>
  59.176 +                                <mainClass>org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher</mainClass>
  59.177 +                                <addClasspath>true</addClasspath>
  59.178 +                                <classpathPrefix>lib/</classpathPrefix>
  59.179 +                            </manifest>
  59.180 +                            <manifestEntries>
  59.181 +                                <StartPage>\${brwsr.startpage}</StartPage>
  59.182 +                            </manifestEntries>
  59.183 +                        </archive>
  59.184 +                    </configuration>
  59.185 +                </plugin>
  59.186 +                <plugin>
  59.187 +                    <artifactId>maven-assembly-plugin</artifactId>
  59.188 +                    <version>2.4</version>
  59.189 +                    <executions>
  59.190 +                        <execution>
  59.191 +                            <id>distro-assembly</id>
  59.192 +                            <phase>package</phase>
  59.193 +                            <goals>
  59.194 +                                <goal>single</goal>
  59.195 +                            </goals>
  59.196 +                            <configuration>
  59.197 +                                <descriptors>
  59.198 +                                    <descriptor>src/main/assembly/fxbrwsr.xml</descriptor>
  59.199 +                                </descriptors>
  59.200 +                            </configuration>
  59.201 +                        </execution>
  59.202 +                    </executions>                
  59.203 +                </plugin>      
  59.204 +            </plugins>
  59.205 +          </build>
  59.206 +          <dependencies>
  59.207 +              <dependency>
  59.208 +                  <groupId>org.netbeans.html</groupId>
  59.209 +                  <artifactId>ko4j</artifactId>
  59.210 +                  <version>\${net.java.html.version}</version>
  59.211 +              </dependency>
  59.212 +              <dependency>
  59.213 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  59.214 +                  <artifactId>launcher.fx</artifactId>
  59.215 +                  <version>\${bck2brwsr.launcher.version}</version>
  59.216 +                  <scope>runtime</scope>
  59.217 +              </dependency>
  59.218 +          </dependencies>
  59.219 +      </profile>
  59.220 +      <profile>
  59.221 +          <id>bck2brwsr</id>
  59.222 +          <activation>
  59.223 +              <property>
  59.224 +                  <name>brwsr</name>
  59.225 +                  <value>bck2brwsr</value>
  59.226 +              </property>
  59.227 +          </activation>
  59.228 +          <build>
  59.229 +              <plugins>
  59.230 +                  <plugin>
  59.231 +                      <groupId>org.apache.maven.plugins</groupId>
  59.232 +                      <artifactId>maven-compiler-plugin</artifactId>
  59.233 +                      <configuration>
  59.234 +                          <compilerArguments>
  59.235 +                              <bootclasspath>netbeans.ignore.jdk.bootclasspath</bootclasspath>
  59.236 +                          </compilerArguments>
  59.237 +                          <testExcludes>
  59.238 +                              <exclude>**/JsInteractionTest*</exclude>
  59.239 +                          </testExcludes>
  59.240 +                      </configuration>
  59.241 +                  </plugin>
  59.242 +                  <plugin>
  59.243 +                      <artifactId>maven-assembly-plugin</artifactId>
  59.244 +                      <version>2.4</version>
  59.245 +                      <executions>
  59.246 +                          <execution>
  59.247 +                              <id>distro-assembly</id>
  59.248 +                              <phase>package</phase>
  59.249 +                              <goals>
  59.250 +                                  <goal>single</goal>
  59.251 +                              </goals>
  59.252 +                              <configuration>
  59.253 +                                  <descriptors>
  59.254 +                                      <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
  59.255 +                                  </descriptors>
  59.256 +                              </configuration>
  59.257 +                          </execution>
  59.258 +                      </executions>                
  59.259 +                  </plugin>      
  59.260 +              </plugins>
  59.261 +          </build>
  59.262 +          <dependencies>
  59.263 +              <dependency>
  59.264 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  59.265 +                  <artifactId>emul</artifactId>
  59.266 +                  <version>\${bck2brwsr.version}</version>
  59.267 +                  <classifier>rt</classifier>
  59.268 +              </dependency>
  59.269 +              <dependency>
  59.270 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  59.271 +                  <artifactId>ko-bck2brwsr</artifactId>
  59.272 +                  <version>\${bck2brwsr.version}</version>
  59.273 +                  <scope>runtime</scope>
  59.274 +              </dependency>
  59.275 +              <dependency>
  59.276 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  59.277 +                  <artifactId>vm4brwsr</artifactId>
  59.278 +                  <classifier>js</classifier>
  59.279 +                  <type>zip</type>
  59.280 +                  <version>\${bck2brwsr.version}</version>
  59.281 +                  <scope>provided</scope>
  59.282 +              </dependency>
  59.283 +          </dependencies>
  59.284 +      </profile>
  59.285 +  </profiles>
  59.286 +</project>
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml	Wed Apr 30 15:04:10 2014 +0200
    60.3 @@ -0,0 +1,43 @@
    60.4 +<?xml version="1.0"?>
    60.5 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    60.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">
    60.7 +  
    60.8 +  <id>bck2brwsr</id>
    60.9 +  <formats>
   60.10 +      <format>zip</format>
   60.11 +  </formats>
   60.12 +  <baseDirectory>public_html</baseDirectory>
   60.13 +  <dependencySets>
   60.14 +    <dependencySet>
   60.15 +        <useProjectArtifact>false</useProjectArtifact>
   60.16 +        <scope>runtime</scope>
   60.17 +        <outputDirectory>lib</outputDirectory>
   60.18 +        <includes>
   60.19 +            <include>*:jar</include>
   60.20 +            <include>*:rt</include>
   60.21 +        </includes>
   60.22 +    </dependencySet>
   60.23 +    <dependencySet>
   60.24 +        <useProjectArtifact>false</useProjectArtifact>
   60.25 +        <scope>provided</scope>
   60.26 +        <includes>
   60.27 +            <include>*:js</include>
   60.28 +        </includes>
   60.29 +        <unpack>true</unpack>
   60.30 +        <outputDirectory>/</outputDirectory>
   60.31 +    </dependencySet>
   60.32 +  </dependencySets> 
   60.33 +  <fileSets>
   60.34 +      <fileSet>
   60.35 +          <directory>src/main/webapp/pages</directory>
   60.36 +          <outputDirectory>/</outputDirectory>
   60.37 +          <filtered>true</filtered>
   60.38 +      </fileSet>
   60.39 +  </fileSets>
   60.40 +  <files>
   60.41 +    <file>
   60.42 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   60.43 +      <outputDirectory>/</outputDirectory>
   60.44 +    </file>
   60.45 +  </files>
   60.46 +</assembly>
   60.47 \ No newline at end of file
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml	Wed Apr 30 15:04:10 2014 +0200
    61.3 @@ -0,0 +1,33 @@
    61.4 +<?xml version="1.0"?>
    61.5 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    61.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">
    61.7 +  
    61.8 +  <id>fxbrwsr</id>
    61.9 +  <formats>
   61.10 +      <format>zip</format>
   61.11 +  </formats>
   61.12 +  <baseDirectory>${project.build.finalName}-fxbrwsr</baseDirectory>
   61.13 +  <dependencySets>
   61.14 +    <dependencySet>
   61.15 +        <useProjectArtifact>false</useProjectArtifact>
   61.16 +        <scope>runtime</scope>
   61.17 +        <outputDirectory>lib</outputDirectory>
   61.18 +    </dependencySet>
   61.19 +  </dependencySets> 
   61.20 +  <files>
   61.21 +    <file>
   61.22 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   61.23 +      <outputDirectory>/</outputDirectory>
   61.24 +    </file>
   61.25 +  </files>
   61.26 +  <fileSets>
   61.27 +    <fileSet>
   61.28 +       <directory>src/main/webapp/</directory>
   61.29 +       <outputDirectory>/</outputDirectory>
   61.30 +       <includes>
   61.31 +          <include>pages/**</include>
   61.32 +       </includes>
   61.33 +       <filtered>true</filtered>
   61.34 +    </fileSet>
   61.35 +  </fileSets>
   61.36 +</assembly>
   61.37 \ No newline at end of file
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/DataModel.java	Wed Apr 30 15:04:10 2014 +0200
    62.3 @@ -0,0 +1,45 @@
    62.4 +package ${package};
    62.5 +
    62.6 +import net.java.html.json.ComputedProperty;
    62.7 +import net.java.html.json.Function;
    62.8 +import net.java.html.json.Model;
    62.9 +import net.java.html.json.Property;
   62.10 +
   62.11 +/** Model annotation generates class Data with 
   62.12 + * one message property, boolean property and read only words property
   62.13 + */
   62.14 +@Model(className = "Data", properties = {
   62.15 +    @Property(name = "message", type = String.class),
   62.16 +    @Property(name = "on", type = boolean.class)
   62.17 +})
   62.18 +final class DataModel {
   62.19 +    @ComputedProperty static java.util.List<String> words(String message) {
   62.20 +        String[] arr = new String[6];
   62.21 +        String[] words = message == null ? new String[0] : message.split(" ", 6);
   62.22 +        for (int i = 0; i < 6; i++) {
   62.23 +            arr[i] = words.length > i ? words[i] : "!";
   62.24 +        }
   62.25 +        return java.util.Arrays.asList(arr);
   62.26 +    }
   62.27 +    
   62.28 +    @Function static void turnOn(Data model) {
   62.29 +        model.setOn(true);
   62.30 +    }
   62.31 +
   62.32 +    @Function static void turnOff(final Data model) {
   62.33 +        confirmByUser("Really turn off?", new Runnable() {
   62.34 +            @Override
   62.35 +            public void run() {
   62.36 +                model.setOn(false);
   62.37 +            }
   62.38 +        });
   62.39 +    }
   62.40 +    
   62.41 +    /** Shows direct interaction with JavaScript */
   62.42 +    @net.java.html.js.JavaScriptBody(
   62.43 +        args = { "msg", "callback" }, 
   62.44 +        javacall = true, 
   62.45 +        body = "alert(msg); callback.@java.lang.Runnable::run()();"
   62.46 +    )
   62.47 +    static native void confirmByUser(String msg, Runnable callback);
   62.48 +}
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/Main.java	Wed Apr 30 15:04:10 2014 +0200
    63.3 @@ -0,0 +1,15 @@
    63.4 +package ${package};
    63.5 +
    63.6 +public final class Main {
    63.7 +    private Main() {
    63.8 +    }
    63.9 +    
   63.10 +    /**
   63.11 +     * Called when the page is ready.
   63.12 +     */
   63.13 +    static {
   63.14 +        Data d = new Data();
   63.15 +        d.setMessage("Hello World from HTML and Java!");
   63.16 +        d.applyBindings();
   63.17 +    }
   63.18 +}
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/webapp/pages/index.html	Wed Apr 30 15:04:10 2014 +0200
    64.3 @@ -0,0 +1,72 @@
    64.4 +<!DOCTYPE html>
    64.5 +<html>
    64.6 +    <head>
    64.7 +        <title></title>
    64.8 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    64.9 +
   64.10 +        <style type="text/css">
   64.11 +            @-webkit-keyframes spin {
   64.12 +                0% { -webkit-transform: rotate(0deg); }
   64.13 +                100% { -webkit-transform: rotate(360deg); }
   64.14 +            }
   64.15 +            @keyframes spin {
   64.16 +                0% { transform: rotate(0deg); }
   64.17 +                100% { transform: rotate(360deg); }
   64.18 +            }
   64.19 +
   64.20 +            .rotate {
   64.21 +                -webkit-animation-name: spin;
   64.22 +                -webkit-animation-duration: 3s;
   64.23 +                -webkit-animation-iteration-count: infinite;
   64.24 +                -webkit-animation-direction: alternate;
   64.25 +                
   64.26 +                animation-name: spin;
   64.27 +                animation-duration: 3s;
   64.28 +                animation-iteration-count: infinite;
   64.29 +                animation-direction: alternate;
   64.30 +            }
   64.31 +
   64.32 +            #scene {
   64.33 +                position: relative;
   64.34 +                top: 60px;
   64.35 +                text-align: center;
   64.36 +            }
   64.37 +            
   64.38 +            #words span {
   64.39 +                border: 1px solid #ccc;
   64.40 +                background: rgba(255,255,155,0.8);
   64.41 +                text-align: center;
   64.42 +                font-size: 30px;                
   64.43 +                -webkit-box-shadow: inset 0 0 40px rgba(0,0,0,0.4);
   64.44 +                position: absolute;
   64.45 +            }
   64.46 +
   64.47 +            #words span:nth-child(1) { left: 45%; top: 0px; }
   64.48 +            #words span:nth-child(2) { left: 25%; top: 100px; }
   64.49 +            #words span:nth-child(3) { left: 65%; top: 100px; }
   64.50 +            #words span:nth-child(4) { left: 10%; top: 200px; }
   64.51 +            #words span:nth-child(5) { left: 45%; top: 200px; }
   64.52 +            #words span:nth-child(6) { left: 80%; top: 200px; }
   64.53 +            
   64.54 +        </style>
   64.55 +
   64.56 +    </head>
   64.57 +    <body>
   64.58 +        <h1>Words Demo</h1>
   64.59 +        <input data-bind="value: message, valueUpdate: 'afterkeydown'" size="80">
   64.60 +        <br>
   64.61 +        <button data-bind="enable: !on(), click: $root.turnOn">Start</button>
   64.62 +        <button data-bind="enable: on, click: $root.turnOff">Stop</button>
   64.63 +
   64.64 +        <div id="scene">
   64.65 +            <span id="words" data-bind="foreach: words">
   64.66 +                <span data-bind="text: $data, css: { 'rotate' : $root.on } "></span>
   64.67 +            </span>
   64.68 +        </div>
   64.69 +        <script type="text/javascript" src="bck2brwsr.js"></script>
   64.70 +        <script>
   64.71 +            var vm = bck2brwsr('${project.build.finalName}.jar');
   64.72 +            vm.loadClass('${package}.Main');
   64.73 +        </script>
   64.74 +    </body>
   64.75 +</html>
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/DataModelTest.java	Wed Apr 30 15:04:10 2014 +0200
    65.3 @@ -0,0 +1,16 @@
    65.4 +package ${package};
    65.5 +
    65.6 +import static org.testng.Assert.*;
    65.7 +import org.testng.annotations.Test;
    65.8 +
    65.9 +public class DataModelTest {
   65.10 +    @Test public void areHelloWorldTwoWords() {
   65.11 +        Data model = new Data();
   65.12 +        model.setMessage("Hello World!");
   65.13 +        
   65.14 +        java.util.List<String> arr = model.getWords();
   65.15 +        assertEquals(arr.size(), 6, "Six words always");
   65.16 +        assertEquals("Hello", arr.get(0), "Hello is the first word");
   65.17 +        assertEquals("World!", arr.get(1), "World is the second word");
   65.18 +    }
   65.19 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java	Wed Apr 30 15:04:10 2014 +0200
    66.3 @@ -0,0 +1,38 @@
    66.4 +package ${package};
    66.5 +
    66.6 +import org.apidesign.bck2brwsr.vmtest.Compare;
    66.7 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    66.8 +import org.testng.annotations.Factory;
    66.9 +
   66.10 +/** Bck2brwsr cares about compatibility with real Java. Whatever API is
   66.11 + * supported by bck2brwsr, it needs to behave the same way as when running
   66.12 + * in HotSpot VM. 
   66.13 + * <p>
   66.14 + * There can be bugs, however. To help us fix them, we kindly ask you to 
   66.15 + * write an "inconsistency" test. A test that compares behavior of the API
   66.16 + * between real VM and bck2brwsr VM. This class is skeleton of such test.
   66.17 + */
   66.18 +public class InconsistencyTest {
   66.19 +    /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
   66.20 +     * Make calls to an API that behaves strangely, return some result at
   66.21 +     * the end. No need to use any <code>assert</code>.
   66.22 +     * 
   66.23 +     * @return value to compare between HotSpot and bck2brwsr
   66.24 +     */
   66.25 +    @Compare
   66.26 +    public int checkStringHashCode() throws Exception {
   66.27 +        return "Is string hashCode the same?".hashCode();
   66.28 +    }
   66.29 +
   66.30 +    /** Factory method that creates a three tests for each method annotated with
   66.31 +     * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
   66.32 +     * HotSpot, one in Rhino and the last one compares the results.
   66.33 +     * 
   66.34 +     * @see org.apidesign.bck2brwsr.vmtest.VMTest
   66.35 +     */
   66.36 +    @Factory
   66.37 +    public static Object[] create() {
   66.38 +        return VMTest.create(InconsistencyTest.class);
   66.39 +    }
   66.40 +    
   66.41 +}
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java	Wed Apr 30 15:04:10 2014 +0200
    67.3 @@ -0,0 +1,31 @@
    67.4 +package ${package};
    67.5 +
    67.6 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    67.7 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
    67.8 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    67.9 +import org.testng.annotations.Factory;
   67.10 +
   67.11 +/** Sometimes it is useful to run tests inside of the real browser. 
   67.12 + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
   67.13 + * and that is it. If your code references elements on the HTML page,
   67.14 + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
   67.15 + * will be made available on the page before your test starts.
   67.16 + */
   67.17 +public class IntegrationTest {
   67.18 +    
   67.19 +    /** Write to testing code here. Use <code>assert</code> (but not TestNG's
   67.20 +     * Assert, as TestNG is not compiled with target 1.6 yet).
   67.21 +     */
   67.22 +    @HtmlFragment(
   67.23 +        "<h1>Put this snippet on the HTML page</h1>\n"
   67.24 +    )
   67.25 +    @BrwsrTest
   67.26 +    public void runThisTestInABrowser() {
   67.27 +    }
   67.28 +
   67.29 +    @Factory
   67.30 +    public static Object[] create() {
   67.31 +        return VMTest.create(IntegrationTest.class);
   67.32 +    }
   67.33 +    
   67.34 +}
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/JsInteractionTest.java	Wed Apr 30 15:04:10 2014 +0200
    68.3 @@ -0,0 +1,103 @@
    68.4 +package ${package};
    68.5 +
    68.6 +import java.io.Closeable;
    68.7 +import java.io.Reader;
    68.8 +import java.net.URL;
    68.9 +import java.util.ArrayList;
   68.10 +import java.util.List;
   68.11 +import javax.script.Invocable;
   68.12 +import javax.script.ScriptEngine;
   68.13 +import javax.script.ScriptEngineManager;
   68.14 +import javax.script.ScriptException;
   68.15 +import org.apidesign.html.boot.spi.Fn;
   68.16 +import static org.testng.Assert.assertEquals;
   68.17 +import org.testng.annotations.AfterMethod;
   68.18 +import org.testng.annotations.BeforeMethod;
   68.19 +import org.testng.annotations.Test;
   68.20 +
   68.21 +/** Tests for behavior of @JavaScriptBody methods. Set your JavaScript 
   68.22 + * environment up (for example define <code>alert</code> or use some
   68.23 + * emulation library like <em>env.js</em>), register script presenter 
   68.24 + * and then you can call methods that deal with JavaScript in your tests.
   68.25 + */
   68.26 +public class JsInteractionTest {
   68.27 +    private Closeable jsEngine;
   68.28 +    @BeforeMethod public void initializeJSEngine() throws Exception {
   68.29 +        jsEngine = Fn.activate(new ScriptPresenter());
   68.30 +    }
   68.31 +    
   68.32 +    @AfterMethod public void shutdownJSEngine() throws Exception {
   68.33 +        jsEngine.close();
   68.34 +    }
   68.35 +    
   68.36 +    @Test public void testCallbackFromJavaScript() throws Exception {
   68.37 +        class R implements Runnable {
   68.38 +            int called;
   68.39 +
   68.40 +            @Override
   68.41 +            public void run() {
   68.42 +                called++;
   68.43 +            }
   68.44 +        }
   68.45 +        R callback = new R();
   68.46 +        
   68.47 +        DataModel.confirmByUser("Hello", callback);
   68.48 +        
   68.49 +        assertEquals(callback.called, 1, "One immediate callback");
   68.50 +    }
   68.51 +
   68.52 +    private static class ScriptPresenter implements Fn.Presenter {
   68.53 +        private final ScriptEngine eng;
   68.54 +        
   68.55 +        public ScriptPresenter() throws ScriptException {
   68.56 +            eng = new ScriptEngineManager().getEngineByName("javascript");
   68.57 +            eng.eval("function alert(msg) { Packages.java.lang.System.out.println(msg); };");
   68.58 +        }
   68.59 +
   68.60 +        @Override
   68.61 +        public Fn defineFn(String code, String... names) {
   68.62 +            StringBuilder sb = new StringBuilder();
   68.63 +            sb.append("(function() {");
   68.64 +            sb.append("  return function(");
   68.65 +            String sep = "";
   68.66 +            for (String n : names) {
   68.67 +                sb.append(sep).append(n);
   68.68 +                sep = ",";
   68.69 +            }
   68.70 +            sb.append(") {\n");
   68.71 +            sb.append(code);
   68.72 +            sb.append("};");
   68.73 +            sb.append("})()");
   68.74 +            
   68.75 +            final Object fn;
   68.76 +            try {
   68.77 +                fn = eng.eval(sb.toString());
   68.78 +            } catch (ScriptException ex) {
   68.79 +                throw new IllegalStateException(ex);
   68.80 +            }
   68.81 +            return new Fn(this) {
   68.82 +                @Override
   68.83 +                public Object invoke(Object thiz, Object... args) throws Exception {
   68.84 +                    List<Object> all = new ArrayList<Object>(args.length + 1);
   68.85 +                    all.add(thiz == null ? fn : thiz);
   68.86 +                    for (int i = 0; i < args.length; i++) {
   68.87 +                        all.add(args[i]);
   68.88 +                    }
   68.89 +                    Object ret = ((Invocable)eng).invokeMethod(fn, "call", all.toArray()); // NOI18N
   68.90 +                    return fn.equals(ret) ? null : thiz;
   68.91 +                }
   68.92 +            };
   68.93 +        }
   68.94 +
   68.95 +        @Override
   68.96 +        public void displayPage(URL page, Runnable onPageLoad) {
   68.97 +            // not really displaying anything
   68.98 +            onPageLoad.run();
   68.99 +        }
  68.100 +
  68.101 +        @Override
  68.102 +        public void loadScript(Reader code) throws Exception {
  68.103 +            eng.eval(code);
  68.104 +        }
  68.105 +    }
  68.106 +}
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/ko/bck2brwsr/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    69.3 @@ -0,0 +1,135 @@
    69.4 +<?xml version="1.0"?>
    69.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">
    69.6 +  <modelVersion>4.0.0</modelVersion>
    69.7 +  <parent>
    69.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    69.9 +    <artifactId>ko</artifactId>
   69.10 +    <version>0.9-SNAPSHOT</version>
   69.11 +  </parent>
   69.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   69.13 +  <artifactId>ko-bck2brwsr</artifactId>
   69.14 +  <version>0.9-SNAPSHOT</version>
   69.15 +  <name>Knockout.b2b</name>
   69.16 +  <url>http://maven.apache.org</url>
   69.17 +  <build>
   69.18 +      <plugins>
   69.19 +          <plugin>
   69.20 +              <groupId>org.apache.maven.plugins</groupId>
   69.21 +              <artifactId>maven-compiler-plugin</artifactId>
   69.22 +              <version>2.3.2</version>
   69.23 +              <configuration>
   69.24 +                  <source>1.7</source>
   69.25 +                  <target>1.7</target>
   69.26 +              </configuration>
   69.27 +          </plugin>
   69.28 +          <plugin>
   69.29 +              <groupId>org.apache.maven.plugins</groupId>
   69.30 +              <artifactId>maven-javadoc-plugin</artifactId>
   69.31 +              <configuration>
   69.32 +                  <skip>false</skip>
   69.33 +              </configuration>
   69.34 +          </plugin>
   69.35 +      </plugins>
   69.36 +  </build>
   69.37 +  <dependencies>
   69.38 +    <dependency>
   69.39 +      <groupId>org.testng</groupId>
   69.40 +      <artifactId>testng</artifactId>
   69.41 +      <scope>test</scope>
   69.42 +      <exclusions>
   69.43 +        <exclusion>
   69.44 +          <artifactId>junit</artifactId>
   69.45 +          <groupId>junit</groupId>
   69.46 +        </exclusion>
   69.47 +      </exclusions>
   69.48 +    </dependency>
   69.49 +    <dependency>
   69.50 +      <groupId>org.netbeans.api</groupId>
   69.51 +      <artifactId>org-openide-util-lookup</artifactId>
   69.52 +      <scope>provided</scope>
   69.53 +    </dependency>
   69.54 +    <dependency>
   69.55 +      <groupId>org.apidesign.bck2brwsr</groupId>
   69.56 +      <artifactId>emul</artifactId>
   69.57 +      <version>${project.version}</version>
   69.58 +      <classifier>rt</classifier>
   69.59 +      <type>jar</type>
   69.60 +      <scope>compile</scope>
   69.61 +    </dependency>
   69.62 +    <dependency>
   69.63 +      <groupId>org.apidesign.bck2brwsr</groupId>
   69.64 +      <artifactId>vm4brwsr</artifactId>
   69.65 +      <version>${project.version}</version>
   69.66 +      <type>jar</type>
   69.67 +      <scope>test</scope>
   69.68 +      <exclusions>
   69.69 +        <exclusion>
   69.70 +          <artifactId>json</artifactId>
   69.71 +          <groupId>org.json</groupId>
   69.72 +        </exclusion>
   69.73 +      </exclusions>
   69.74 +    </dependency>
   69.75 +    <dependency>
   69.76 +      <groupId>org.apidesign.bck2brwsr</groupId>
   69.77 +      <artifactId>vmtest</artifactId>
   69.78 +      <version>${project.version}</version>
   69.79 +      <scope>test</scope>
   69.80 +    </dependency>
   69.81 +    <dependency>
   69.82 +      <groupId>org.apidesign.bck2brwsr</groupId>
   69.83 +      <artifactId>launcher.http</artifactId>
   69.84 +      <version>${project.version}</version>
   69.85 +      <scope>test</scope>
   69.86 +      <exclusions>
   69.87 +        <exclusion>
   69.88 +          <artifactId>asm</artifactId>
   69.89 +          <groupId>org.ow2.asm</groupId>
   69.90 +        </exclusion>
   69.91 +      </exclusions>
   69.92 +    </dependency>
   69.93 +    <dependency>
   69.94 +      <groupId>org.netbeans.html</groupId>
   69.95 +      <artifactId>net.java.html.json</artifactId>
   69.96 +      <version>${net.java.html.version}</version>
   69.97 +    </dependency>
   69.98 +    <dependency>
   69.99 +      <groupId>org.netbeans.html</groupId>
  69.100 +      <artifactId>net.java.html.json.tck</artifactId>
  69.101 +      <version>${net.java.html.version}</version>
  69.102 +      <scope>test</scope>
  69.103 +    </dependency>
  69.104 +    <dependency>
  69.105 +      <groupId>org.apidesign.bck2brwsr</groupId>
  69.106 +      <artifactId>core</artifactId>
  69.107 +      <version>${project.version}</version>
  69.108 +      <type>jar</type>
  69.109 +    </dependency>
  69.110 +    <dependency>
  69.111 +      <groupId>org.netbeans.html</groupId>
  69.112 +      <artifactId>net.java.html.boot</artifactId>
  69.113 +      <version>${net.java.html.version}</version>
  69.114 +      <type>jar</type>
  69.115 +      <exclusions>
  69.116 +        <exclusion>
  69.117 +          <artifactId>asm</artifactId>
  69.118 +          <groupId>org.ow2.asm</groupId>
  69.119 +        </exclusion>
  69.120 +      </exclusions>
  69.121 +    </dependency>
  69.122 +    <dependency>
  69.123 +      <groupId>org.netbeans.html</groupId>
  69.124 +      <artifactId>ko4j</artifactId>
  69.125 +      <version>${net.java.html.version}</version>
  69.126 +      <exclusions>
  69.127 +        <exclusion>
  69.128 +          <artifactId>json</artifactId>
  69.129 +          <groupId>org.json</groupId>
  69.130 +        </exclusion>
  69.131 +        <exclusion>
  69.132 +          <artifactId>org.json-osgi</artifactId>
  69.133 +          <groupId>de.twentyeleven.skysail</groupId>
  69.134 +        </exclusion>
  69.135 +      </exclusions>
  69.136 +    </dependency>
  69.137 +  </dependencies>
  69.138 +</project>
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/ko/bck2brwsr/src/test/java/org/apidesign/bck2brwsr/ko2brwsr/Bck2BrwsrJavaScriptBodyTest.java	Wed Apr 30 15:04:10 2014 +0200
    70.3 @@ -0,0 +1,34 @@
    70.4 +/**
    70.5 + * Back 2 Browser Bytecode Translator
    70.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    70.7 + *
    70.8 + * This program is free software: you can redistribute it and/or modify
    70.9 + * it under the terms of the GNU General Public License as published by
   70.10 + * the Free Software Foundation, version 2 of the License.
   70.11 + *
   70.12 + * This program is distributed in the hope that it will be useful,
   70.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   70.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   70.15 + * GNU General Public License for more details.
   70.16 + *
   70.17 + * You should have received a copy of the GNU General Public License
   70.18 + * along with this program. Look for COPYING file in the top folder.
   70.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   70.20 + */
   70.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   70.22 +
   70.23 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   70.24 +import org.apidesign.html.json.tck.JavaScriptTCK;
   70.25 +import org.apidesign.html.json.tck.KOTest;
   70.26 +import org.testng.annotations.Factory;
   70.27 +
   70.28 +/**
   70.29 + *
   70.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   70.31 + */
   70.32 +public class Bck2BrwsrJavaScriptBodyTest extends JavaScriptTCK {
   70.33 +    @Factory public static Object[] tests() {
   70.34 +        return VMTest.newTests().withClasses(testClasses())
   70.35 +            .withTestAnnotation(KOTest.class).build();
   70.36 +    }
   70.37 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/ko/bck2brwsr/src/test/java/org/apidesign/bck2brwsr/ko2brwsr/Bck2BrwsrKnockoutTest.java	Wed Apr 30 15:04:10 2014 +0200
    71.3 @@ -0,0 +1,122 @@
    71.4 +/**
    71.5 + * Back 2 Browser Bytecode Translator
    71.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    71.7 + *
    71.8 + * This program is free software: you can redistribute it and/or modify
    71.9 + * it under the terms of the GNU General Public License as published by
   71.10 + * the Free Software Foundation, version 2 of the License.
   71.11 + *
   71.12 + * This program is distributed in the hope that it will be useful,
   71.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   71.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   71.15 + * GNU General Public License for more details.
   71.16 + *
   71.17 + * You should have received a copy of the GNU General Public License
   71.18 + * along with this program. Look for COPYING file in the top folder.
   71.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   71.20 + */
   71.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   71.22 +
   71.23 +import java.io.IOException;
   71.24 +import java.net.URI;
   71.25 +import java.net.URISyntaxException;
   71.26 +import java.net.URL;
   71.27 +import java.util.Map;
   71.28 +import net.java.html.BrwsrCtx;
   71.29 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   71.30 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   71.31 +import org.apidesign.html.context.spi.Contexts;
   71.32 +import org.apidesign.html.json.spi.Technology;
   71.33 +import org.apidesign.html.json.spi.Transfer;
   71.34 +import org.apidesign.html.json.spi.WSTransfer;
   71.35 +import org.apidesign.html.json.tck.KOTest;
   71.36 +import org.apidesign.html.json.tck.KnockoutTCK;
   71.37 +import org.netbeans.html.ko4j.KO4J;
   71.38 +import org.openide.util.lookup.ServiceProvider;
   71.39 +import org.testng.annotations.Factory;
   71.40 +
   71.41 +/**
   71.42 + *
   71.43 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   71.44 + */
   71.45 +@ServiceProvider(service = KnockoutTCK.class)
   71.46 +public final class Bck2BrwsrKnockoutTest extends KnockoutTCK {
   71.47 +    @Factory public static Object[] create() {
   71.48 +        return VMTest.newTests().
   71.49 +            withClasses(testClasses()).
   71.50 +            withLaunchers("bck2brwsr").
   71.51 +            withTestAnnotation(KOTest.class).
   71.52 +            build();
   71.53 +    }
   71.54 +    
   71.55 +    @Override
   71.56 +    public BrwsrCtx createContext() {
   71.57 +        KO4J ko = new KO4J(null);
   71.58 +        return Contexts.newBuilder().
   71.59 +            register(Transfer.class, ko.transfer(), 9).
   71.60 +            register(WSTransfer.class, ko.websockets(), 9).
   71.61 +            register(Technology.class, ko.knockout(), 9).build();
   71.62 +    }
   71.63 +
   71.64 +
   71.65 +    
   71.66 +    @Override
   71.67 +    public Object createJSON(Map<String, Object> values) {
   71.68 +        Object json = createJSON();
   71.69 +        
   71.70 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
   71.71 +            putValue(json, entry.getKey(), entry.getValue());
   71.72 +        }
   71.73 +        return json;
   71.74 +    }
   71.75 +
   71.76 +    @JavaScriptBody(args = {}, body = "return new Object();")
   71.77 +    private static native Object createJSON();
   71.78 +
   71.79 +    @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;")
   71.80 +    private static native void putValue(Object json, String key, Object value);
   71.81 +
   71.82 +    @Override
   71.83 +    public Object executeScript(String script, Object[] arguments) {
   71.84 +        return execScript(script, arguments);
   71.85 +    }
   71.86 +    
   71.87 +    @JavaScriptBody(args = { "s", "args" }, body = 
   71.88 +        "var f = new Function(s); return f.apply(null, args);"
   71.89 +    )
   71.90 +    private static native Object execScript(String s, Object[] arguments);
   71.91 +    
   71.92 +    @JavaScriptBody(args = {  }, body = 
   71.93 +          "var h;"
   71.94 +        + "if (!!window && !!window.location && !!window.location.href)\n"
   71.95 +        + "  h = window.location.href;\n"
   71.96 +        + "else "
   71.97 +        + "  h = null;"
   71.98 +        + "return h;\n"
   71.99 +    )
  71.100 +    private static native String findBaseURL();
  71.101 +    
  71.102 +    @Override
  71.103 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
  71.104 +        try {
  71.105 +            final URL baseURL = new URL(findBaseURL());
  71.106 +            StringBuilder sb = new StringBuilder();
  71.107 +            sb.append("/dynamic?mimeType=").append(mimeType);
  71.108 +            for (int i = 0; i < parameters.length; i++) {
  71.109 +                sb.append("&param" + i).append("=").append(parameters[i]);
  71.110 +            }
  71.111 +            String mangle = content.replace("\n", "%0a")
  71.112 +                .replace("\"", "\\\"").replace(" ", "%20");
  71.113 +            sb.append("&content=").append(mangle);
  71.114 +
  71.115 +            URL query = new URL(baseURL, sb.toString());
  71.116 +            String uri = (String) query.getContent(new Class[] { String.class });
  71.117 +            URI connectTo = new URI(uri.trim());
  71.118 +            return connectTo;
  71.119 +        } catch (IOException ex) {
  71.120 +            throw new IllegalStateException(ex);
  71.121 +        } catch (URISyntaxException ex) {
  71.122 +            throw new IllegalStateException(ex);
  71.123 +        }
  71.124 +    }    
  71.125 +}
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/ko/fx/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    72.3 @@ -0,0 +1,119 @@
    72.4 +<?xml version="1.0"?>
    72.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">
    72.6 +  <modelVersion>4.0.0</modelVersion>
    72.7 +  <parent>
    72.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    72.9 +    <artifactId>ko</artifactId>
   72.10 +    <version>0.9-SNAPSHOT</version>
   72.11 +  </parent>
   72.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   72.13 +  <artifactId>ko-fx</artifactId>
   72.14 +  <version>0.9-SNAPSHOT</version>
   72.15 +  <name>Knockout.fx in Brwsr</name>
   72.16 +  <url>http://maven.apache.org</url>
   72.17 +  <properties>
   72.18 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   72.19 +  </properties>
   72.20 +  <build>
   72.21 +      <plugins>
   72.22 +          <plugin>
   72.23 +              <groupId>org.apache.maven.plugins</groupId>
   72.24 +              <artifactId>maven-javadoc-plugin</artifactId>
   72.25 +              <configuration>
   72.26 +                  <skip>false</skip>
   72.27 +              </configuration>
   72.28 +          </plugin>
   72.29 +      </plugins>
   72.30 +  </build>
   72.31 +  <dependencies>
   72.32 +    <dependency>
   72.33 +        <groupId>com.oracle</groupId>
   72.34 +        <artifactId>javafx</artifactId>
   72.35 +        <version>2.2</version>
   72.36 +        <scope>system</scope>
   72.37 +        <systemPath>${jfxrt.jar}</systemPath>
   72.38 +    </dependency>
   72.39 +    <dependency>
   72.40 +      <groupId>org.json</groupId>
   72.41 +      <artifactId>json</artifactId>
   72.42 +      <version>20090211</version>
   72.43 +      <type>jar</type>
   72.44 +    </dependency>
   72.45 +    <dependency>
   72.46 +      <groupId>org.netbeans.html</groupId>
   72.47 +      <artifactId>net.java.html.json</artifactId>
   72.48 +      <version>${net.java.html.version}</version>
   72.49 +    </dependency>
   72.50 +    <dependency>
   72.51 +      <groupId>org.testng</groupId>
   72.52 +      <artifactId>testng</artifactId>
   72.53 +      <scope>test</scope>
   72.54 +    </dependency>
   72.55 +    <dependency>
   72.56 +      <groupId>org.netbeans.html</groupId>
   72.57 +      <artifactId>net.java.html.json.tck</artifactId>
   72.58 +      <version>${net.java.html.version}</version>
   72.59 +      <scope>test</scope>
   72.60 +    </dependency>
   72.61 +    <dependency>
   72.62 +      <groupId>org.netbeans.api</groupId>
   72.63 +      <artifactId>org-openide-util</artifactId>
   72.64 +      <scope>provided</scope>
   72.65 +    </dependency>
   72.66 +    <dependency>
   72.67 +      <groupId>org.apidesign.bck2brwsr</groupId>
   72.68 +      <artifactId>launcher.fx</artifactId>
   72.69 +      <version>${project.version}</version>
   72.70 +      <scope>test</scope>
   72.71 +    </dependency>
   72.72 +    <dependency>
   72.73 +      <groupId>org.netbeans.html</groupId>
   72.74 +      <artifactId>net.java.html.boot</artifactId>
   72.75 +      <version>${net.java.html.version}</version>
   72.76 +      <type>jar</type>
   72.77 +    </dependency>
   72.78 +    <dependency>
   72.79 +      <groupId>org.netbeans.html</groupId>
   72.80 +      <artifactId>ko4j</artifactId>
   72.81 +      <version>${net.java.html.version}</version>
   72.82 +      <type>jar</type>
   72.83 +    </dependency>
   72.84 +    <dependency>
   72.85 +      <groupId>org.apidesign.bck2brwsr</groupId>
   72.86 +      <artifactId>vmtest</artifactId>
   72.87 +      <version>${project.version}</version>
   72.88 +      <scope>test</scope>
   72.89 +      <type>jar</type>
   72.90 +    </dependency>
   72.91 +    <dependency>
   72.92 +      <groupId>org.netbeans.html</groupId>
   72.93 +      <artifactId>ko-ws-tyrus</artifactId>
   72.94 +      <version>${net.java.html.version}</version>
   72.95 +      <scope>test</scope>
   72.96 +    </dependency>
   72.97 +  </dependencies>
   72.98 +  <profiles>
   72.99 +      <profile>
  72.100 +          <id>jdk8</id>
  72.101 +          <activation>
  72.102 +              <file>
  72.103 +                  <exists>${java.home}/lib/ext/jfxrt.jar</exists>
  72.104 +              </file>
  72.105 +          </activation>
  72.106 +          <properties>
  72.107 +            <jfxrt.jar>${java.home}/lib/ext/jfxrt.jar</jfxrt.jar>
  72.108 +          </properties>
  72.109 +      </profile>
  72.110 +      <profile>
  72.111 +          <id>jdk7</id>
  72.112 +          <activation>
  72.113 +              <file>
  72.114 +                  <exists>${java.home}/lib/jfxrt.jar</exists>
  72.115 +              </file>
  72.116 +          </activation>
  72.117 +          <properties>
  72.118 +            <jfxrt.jar>${java.home}/lib/jfxrt.jar</jfxrt.jar>
  72.119 +          </properties>
  72.120 +      </profile>
  72.121 +  </profiles>
  72.122 +</project>
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/JavaScriptBodyFXBrwsrTest.java	Wed Apr 30 15:04:10 2014 +0200
    73.3 @@ -0,0 +1,36 @@
    73.4 +/**
    73.5 + * Back 2 Browser Bytecode Translator
    73.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    73.7 + *
    73.8 + * This program is free software: you can redistribute it and/or modify
    73.9 + * it under the terms of the GNU General Public License as published by
   73.10 + * the Free Software Foundation, version 2 of the License.
   73.11 + *
   73.12 + * This program is distributed in the hope that it will be useful,
   73.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   73.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   73.15 + * GNU General Public License for more details.
   73.16 + *
   73.17 + * You should have received a copy of the GNU General Public License
   73.18 + * along with this program. Look for COPYING file in the top folder.
   73.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   73.20 + */
   73.21 +package org.apidesign.bck2brwsr.kofx;
   73.22 +
   73.23 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   73.24 +import org.apidesign.html.json.tck.JavaScriptTCK;
   73.25 +import org.apidesign.html.json.tck.KOTest;
   73.26 +import org.testng.annotations.Factory;
   73.27 +
   73.28 +/**
   73.29 + *
   73.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   73.31 + */
   73.32 +public class JavaScriptBodyFXBrwsrTest extends JavaScriptTCK {
   73.33 +    @Factory public static Object[] create() {
   73.34 +        return VMTest.newTests().
   73.35 +            withLaunchers("fxbrwsr").
   73.36 +            withClasses(testClasses()).
   73.37 +            withTestAnnotation(KOTest.class).build();
   73.38 +    }
   73.39 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/KnockoutFXTest.java	Wed Apr 30 15:04:10 2014 +0200
    74.3 @@ -0,0 +1,140 @@
    74.4 +/**
    74.5 + * Back 2 Browser Bytecode Translator
    74.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    74.7 + *
    74.8 + * This program is free software: you can redistribute it and/or modify
    74.9 + * it under the terms of the GNU General Public License as published by
   74.10 + * the Free Software Foundation, version 2 of the License.
   74.11 + *
   74.12 + * This program is distributed in the hope that it will be useful,
   74.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   74.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   74.15 + * GNU General Public License for more details.
   74.16 + *
   74.17 + * You should have received a copy of the GNU General Public License
   74.18 + * along with this program. Look for COPYING file in the top folder.
   74.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   74.20 + */
   74.21 +package org.apidesign.bck2brwsr.kofx;
   74.22 +
   74.23 +import java.io.BufferedReader;
   74.24 +import java.io.IOException;
   74.25 +import java.io.InputStreamReader;
   74.26 +import java.net.URI;
   74.27 +import java.net.URISyntaxException;
   74.28 +import java.net.URL;
   74.29 +import java.net.URLConnection;
   74.30 +import java.util.Map;
   74.31 +import java.util.concurrent.Executor;
   74.32 +import net.java.html.BrwsrCtx;
   74.33 +import net.java.html.js.JavaScriptBody;
   74.34 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   74.35 +import org.apidesign.html.boot.spi.Fn;
   74.36 +import org.apidesign.html.context.spi.Contexts;
   74.37 +import org.apidesign.html.json.spi.Technology;
   74.38 +import org.apidesign.html.json.spi.Transfer;
   74.39 +import org.apidesign.html.json.spi.WSTransfer;
   74.40 +import org.apidesign.html.json.tck.KOTest;
   74.41 +import org.apidesign.html.json.tck.KnockoutTCK;
   74.42 +import org.json.JSONException;
   74.43 +import org.json.JSONObject;
   74.44 +import org.netbeans.html.ko4j.KO4J;
   74.45 +import org.netbeans.html.wstyrus.TyrusContext;
   74.46 +import org.openide.util.lookup.ServiceProvider;
   74.47 +import org.testng.annotations.Factory;
   74.48 +
   74.49 +/**
   74.50 + *
   74.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   74.52 + */
   74.53 +@ServiceProvider(service = KnockoutTCK.class)
   74.54 +public final class KnockoutFXTest extends KnockoutTCK {
   74.55 +    public KnockoutFXTest() {
   74.56 +    }
   74.57 +
   74.58 +    @Factory public static Object[] compatibilityTests() {
   74.59 +        return VMTest.newTests().
   74.60 +            withClasses(testClasses()).
   74.61 +            withTestAnnotation(KOTest.class).
   74.62 +            withLaunchers("fxbrwsr").build();
   74.63 +    }
   74.64 +
   74.65 +    @Override
   74.66 +    public BrwsrCtx createContext() {
   74.67 +        final Fn.Presenter p = Fn.activePresenter();
   74.68 +        KO4J ko = new KO4J(p);
   74.69 +        TyrusContext tc = new TyrusContext();
   74.70 +        Contexts.Builder b = Contexts.newBuilder().
   74.71 +            register(Technology.class, ko.knockout(), 10).
   74.72 +            register(Transfer.class, ko.transfer(), 10);
   74.73 +        if (p instanceof Executor) {
   74.74 +            b.register(Executor.class, (Executor)p, 10);
   74.75 +        }
   74.76 +        try {
   74.77 +            Class.forName("java.util.function.Function");
   74.78 +            // prefer WebView's WebSockets on JDK8
   74.79 +            b.register(WSTransfer.class, ko.websockets(), 10);
   74.80 +        } catch (ClassNotFoundException ex) {
   74.81 +            // ok, JDK7 needs tyrus
   74.82 +            b.register(WSTransfer.class, tc, 20);
   74.83 +            b.register(Transfer.class, tc, 5);
   74.84 +        }
   74.85 +        return b.build();
   74.86 +    }
   74.87 +
   74.88 +    @Override
   74.89 +    public Object createJSON(Map<String, Object> values) {
   74.90 +        Object json = createJSON();
   74.91 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
   74.92 +            setProperty(json, entry.getKey(), entry.getValue());
   74.93 +        }
   74.94 +        return json;
   74.95 +    }
   74.96 +    
   74.97 +    @JavaScriptBody(args = {}, body = "return new Object();")
   74.98 +    private static native Object createJSON();
   74.99 +    @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;")
  74.100 +    private static native void setProperty(Object json, String key, Object value);
  74.101 +
  74.102 +    @Override
  74.103 +    @JavaScriptBody(args = { "s", "args" }, body = ""
  74.104 +        + "var f = new Function(s); "
  74.105 +        + "return f.apply(null, args);"
  74.106 +    )
  74.107 +    public native Object executeScript(String script, Object[] arguments);
  74.108 +
  74.109 +    @JavaScriptBody(args = {  }, body = 
  74.110 +          "var h;"
  74.111 +        + "if (!!window && !!window.location && !!window.location.href)\n"
  74.112 +        + "  h = window.location.href;\n"
  74.113 +        + "else "
  74.114 +        + "  h = null;"
  74.115 +        + "return h;\n"
  74.116 +    )
  74.117 +    private static native String findBaseURL();
  74.118 +    
  74.119 +    @Override
  74.120 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
  74.121 +        try {
  74.122 +            final URL baseURL = new URL(findBaseURL());
  74.123 +            StringBuilder sb = new StringBuilder();
  74.124 +            sb.append("/dynamic?mimeType=").append(mimeType);
  74.125 +            for (int i = 0; i < parameters.length; i++) {
  74.126 +                sb.append("&param" + i).append("=").append(parameters[i]);
  74.127 +            }
  74.128 +            String mangle = content.replace("\n", "%0a")
  74.129 +                .replace("\"", "\\\"").replace(" ", "%20");
  74.130 +            sb.append("&content=").append(mangle);
  74.131 +
  74.132 +            URL query = new URL(baseURL, sb.toString());
  74.133 +            URLConnection c = query.openConnection();
  74.134 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
  74.135 +            URI connectTo = new URI(br.readLine());
  74.136 +            return connectTo;
  74.137 +        } catch (IOException ex) {
  74.138 +            throw new IllegalStateException(ex);
  74.139 +        } catch (URISyntaxException ex) {
  74.140 +            throw new IllegalStateException(ex);
  74.141 +        }
  74.142 +    }
  74.143 +}
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/ko/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    75.3 @@ -0,0 +1,20 @@
    75.4 +<?xml version="1.0" encoding="UTF-8"?>
    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 +  <groupId>org.apidesign.bck2brwsr</groupId>
    75.8 +  <artifactId>ko</artifactId>
    75.9 +  <version>0.9-SNAPSHOT</version>
   75.10 +  <packaging>pom</packaging>
   75.11 +  <name>Bck2Brwsr Knockout Support</name>
   75.12 +  <parent>
   75.13 +    <groupId>org.apidesign</groupId>
   75.14 +    <artifactId>bck2brwsr</artifactId>
   75.15 +    <version>0.9-SNAPSHOT</version>
   75.16 +  </parent>  
   75.17 +  <modules>
   75.18 +    <module>archetype</module>
   75.19 +    <module>archetype-test</module>
   75.20 +    <module>bck2brwsr</module>
   75.21 +    <module>fx</module>
   75.22 +  </modules>
   75.23 +</project>
    76.1 --- a/launcher/api/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    76.2 +++ b/launcher/api/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    76.3 @@ -4,11 +4,11 @@
    76.4    <parent>
    76.5      <groupId>org.apidesign.bck2brwsr</groupId>
    76.6      <artifactId>launcher-pom</artifactId>
    76.7 -    <version>0.8-SNAPSHOT</version>
    76.8 +    <version>0.9-SNAPSHOT</version>
    76.9    </parent>
   76.10    <groupId>org.apidesign.bck2brwsr</groupId>
   76.11    <artifactId>launcher</artifactId>
   76.12 -  <version>0.8-SNAPSHOT</version>
   76.13 +  <version>0.9-SNAPSHOT</version>
   76.14    <name>Launcher API</name>
   76.15    <url>http://maven.apache.org</url>
   76.16    <properties>
    77.1 --- a/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Tue Apr 29 15:25:58 2014 +0200
    77.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Wed Apr 30 15:04:10 2014 +0200
    77.3 @@ -19,6 +19,7 @@
    77.4  
    77.5  import java.io.IOException;
    77.6  import java.io.InputStream;
    77.7 +import java.net.URI;
    77.8  import java.util.ArrayList;
    77.9  import java.util.List;
   77.10  import java.util.concurrent.CountDownLatch;
   77.11 @@ -95,7 +96,6 @@
   77.12          wait.countDown();
   77.13      }
   77.14  
   77.15 -
   77.16      static final class Resource {
   77.17          final InputStream httpContent;
   77.18          final String httpType;
    78.1 --- a/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Tue Apr 29 15:25:58 2014 +0200
    78.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Wed Apr 30 15:04:10 2014 +0200
    78.3 @@ -135,14 +135,34 @@
    78.4       * The <code>startpage</code> should be relative location inside the root 
    78.5       * directory. Opens a browser with URL showing the start page.
    78.6       * 
    78.7 +     * @param brwsr type of the browser to use
    78.8 +     * @param directory the root directory on disk
    78.9 +     * @param classes additional classloader with access to classes or <code>null</code>
   78.10 +     * @param startpage relative path from the root to the page
   78.11 +     * @return instance of server that can be closed
   78.12 +     * @exception IOException if something goes wrong.
   78.13 +     * @since 0.8
   78.14 +     */
   78.15 +    public static Closeable showDir(String brwsr, File directory, ClassLoader classes, String startpage) throws IOException {
   78.16 +        Launcher l = createBrowser(brwsr);
   78.17 +        if (classes != null) {
   78.18 +            l.addClassLoader(classes);
   78.19 +        }
   78.20 +        l.showDirectory(directory, startpage, classes != null);
   78.21 +        return (Closeable) l;
   78.22 +    }
   78.23 +    
   78.24 +    /** Starts an HTTP server which provides access to certain directory.
   78.25 +     * The <code>startpage</code> should be relative location inside the root 
   78.26 +     * directory. Opens a browser with URL showing the start page.
   78.27 +     * 
   78.28       * @param directory the root directory on disk
   78.29       * @param startpage relative path from the root to the page
   78.30 +     * @return instance of server that can be closed
   78.31       * @exception IOException if something goes wrong.
   78.32       */
   78.33      public static Closeable showDir(File directory, String startpage) throws IOException {
   78.34 -        Launcher l = createBrowser(null);
   78.35 -        l.showDirectory(directory, startpage);
   78.36 -        return (Closeable) l;
   78.37 +        return showDir(null, directory, null, startpage);
   78.38      }
   78.39  
   78.40      abstract InvocationContext runMethod(InvocationContext c) throws IOException; 
   78.41 @@ -152,7 +172,7 @@
   78.42          return Launcher.class.getClassLoader().loadClass(cn);
   78.43      }
   78.44  
   78.45 -    void showDirectory(File directory, String startpage) throws IOException {
   78.46 +    void showDirectory(File directory, String startpage, boolean addClasses) throws IOException {
   78.47          throw new UnsupportedOperationException();
   78.48      }
   78.49  
    79.1 --- a/launcher/fx/pom.xml	Tue Apr 29 15:25:58 2014 +0200
    79.2 +++ b/launcher/fx/pom.xml	Wed Apr 30 15:04:10 2014 +0200
    79.3 @@ -4,11 +4,11 @@
    79.4    <parent>
    79.5      <groupId>org.apidesign.bck2brwsr</groupId>
    79.6      <artifactId>launcher-pom</artifactId>
    79.7 -    <version>0.8-SNAPSHOT</version>
    79.8 +    <version>0.9-SNAPSHOT</version>
    79.9    </parent>
   79.10    <groupId>org.apidesign.bck2brwsr</groupId>
   79.11    <artifactId>launcher.fx</artifactId>
   79.12 -  <version>0.8-SNAPSHOT</version>
   79.13 +  <version>0.9-SNAPSHOT</version>
   79.14    <name>FXBrwsr Launcher</name>
   79.15    <url>http://maven.apache.org</url>
   79.16      <build>
   79.17 @@ -18,8 +18,8 @@
   79.18                  <artifactId>maven-compiler-plugin</artifactId>
   79.19                  <version>2.3.2</version>
   79.20                  <configuration>
   79.21 -                    <source>1.7</source>
   79.22 -                    <target>1.7</target>
   79.23 +                    <source>1.6</source>
   79.24 +                    <target>1.6</target>
   79.25                  </configuration>
   79.26              </plugin>
   79.27              <plugin>
   79.28 @@ -58,5 +58,44 @@
   79.29        <artifactId>testng</artifactId>
   79.30        <scope>test</scope>
   79.31      </dependency>
   79.32 +    <!--
   79.33 +    <dependency>
   79.34 +      <groupId>org.netbeans.modules</groupId>
   79.35 +      <artifactId>org-netbeans-bootstrap</artifactId>
   79.36 +      <version>RELEASE73</version>
   79.37 +    </dependency>
   79.38 +    -->
   79.39 +    <dependency>
   79.40 +      <groupId>${project.groupId}</groupId>
   79.41 +      <artifactId>core</artifactId>
   79.42 +      <version>${project.version}</version>
   79.43 +      <scope>compile</scope>
   79.44 +    </dependency>
   79.45 +    <dependency>
   79.46 +      <groupId>org.ow2.asm</groupId>
   79.47 +      <artifactId>asm</artifactId>
   79.48 +      <version>4.1</version>
   79.49 +    </dependency>
   79.50 +    <dependency>
   79.51 +      <groupId>org.netbeans.html</groupId>
   79.52 +      <artifactId>net.java.html.boot</artifactId>
   79.53 +      <version>${net.java.html.version}</version>
   79.54 +    </dependency>
   79.55 +    <dependency>
   79.56 +        <groupId>org.glassfish.grizzly</groupId>
   79.57 +        <artifactId>grizzly-websockets-server</artifactId>
   79.58 +        <version>${grizzly.version}</version>
   79.59 +        <type>jar</type>
   79.60 +    </dependency>
   79.61 +    <dependency>
   79.62 +        <groupId>org.glassfish.grizzly</groupId>
   79.63 +        <artifactId>grizzly-http-servlet</artifactId>
   79.64 +        <version>${grizzly.version}</version>
   79.65 +    </dependency>    
   79.66 +    <dependency>
   79.67 +        <groupId>javax.servlet</groupId>
   79.68 +        <artifactId>javax.servlet-api</artifactId>
   79.69 +        <version>3.1.0</version>
   79.70 +    </dependency>
   79.71    </dependencies>
   79.72  </project>
    80.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java	Tue Apr 29 15:25:58 2014 +0200
    80.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java	Wed Apr 30 15:04:10 2014 +0200
    80.3 @@ -17,6 +17,8 @@
    80.4   */
    80.5  package org.apidesign.bck2brwsr.launcher;
    80.6  
    80.7 +import java.io.ByteArrayInputStream;
    80.8 +import java.io.ByteArrayOutputStream;
    80.9  import java.io.Closeable;
   80.10  import java.io.File;
   80.11  import java.io.IOException;
   80.12 @@ -52,7 +54,13 @@
   80.13  import org.glassfish.grizzly.http.server.Request;
   80.14  import org.glassfish.grizzly.http.server.Response;
   80.15  import org.glassfish.grizzly.http.server.ServerConfiguration;
   80.16 +import org.glassfish.grizzly.http.server.StaticHttpHandler;
   80.17  import org.glassfish.grizzly.http.util.HttpStatus;
   80.18 +import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
   80.19 +import org.glassfish.grizzly.websockets.WebSocket;
   80.20 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
   80.21 +import org.glassfish.grizzly.websockets.WebSocketApplication;
   80.22 +import org.glassfish.grizzly.websockets.WebSocketEngine;
   80.23  
   80.24  /**
   80.25   * Lightweight server to launch Bck2Brwsr applications and tests.
   80.26 @@ -62,8 +70,8 @@
   80.27  abstract class BaseHTTPLauncher extends Launcher implements Closeable, Callable<HttpServer> {
   80.28      static final Logger LOG = Logger.getLogger(BaseHTTPLauncher.class.getName());
   80.29      private static final InvocationContext END = new InvocationContext(null, null, null);
   80.30 -    private final Set<ClassLoader> loaders = new LinkedHashSet<>();
   80.31 -    private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
   80.32 +    private final Set<ClassLoader> loaders = new LinkedHashSet<ClassLoader>();
   80.33 +    private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<InvocationContext>();
   80.34      private long timeOut;
   80.35      private final Res resources = new Res();
   80.36      private final String cmd;
   80.37 @@ -105,7 +113,7 @@
   80.38          if (!startpage.startsWith("/")) {
   80.39              startpage = "/" + startpage;
   80.40          }
   80.41 -        HttpServer s = initServer(".", true);
   80.42 +        HttpServer s = initServer(".", true, "");
   80.43          int last = startpage.lastIndexOf('/');
   80.44          String prefix = startpage.substring(0, last);
   80.45          String simpleName = startpage.substring(last);
   80.46 @@ -113,19 +121,24 @@
   80.47          server = s;
   80.48          try {
   80.49              launchServerAndBrwsr(s, simpleName);
   80.50 -        } catch (URISyntaxException | InterruptedException ex) {
   80.51 +        } catch (Exception ex) {
   80.52              throw new IOException(ex);
   80.53          }
   80.54      }
   80.55  
   80.56 -    void showDirectory(File dir, String startpage) throws IOException {
   80.57 +    void showDirectory(File dir, String startpage, boolean addClasses) throws IOException {
   80.58          if (!startpage.startsWith("/")) {
   80.59              startpage = "/" + startpage;
   80.60          }
   80.61 -        HttpServer s = initServer(dir.getPath(), false);
   80.62 +        String prefix = "";
   80.63 +        int last = startpage.lastIndexOf('/');
   80.64 +        if (last >= 0) {
   80.65 +            prefix = startpage.substring(0, last);
   80.66 +        }
   80.67 +        HttpServer s = initServer(dir.getPath(), addClasses, prefix);
   80.68          try {
   80.69              launchServerAndBrwsr(s, startpage);
   80.70 -        } catch (URISyntaxException | InterruptedException ex) {
   80.71 +        } catch (Exception ex) {
   80.72              throw new IOException(ex);
   80.73          }
   80.74      }
   80.75 @@ -149,16 +162,16 @@
   80.76          }
   80.77      }
   80.78      
   80.79 -    private HttpServer initServer(String path, boolean addClasses) throws IOException {
   80.80 -        HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
   80.81 -/*
   80.82 +    private HttpServer initServer(String path, boolean addClasses, String vmPrefix) throws IOException {
   80.83 +        HttpServer s = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
   80.84 +        /*
   80.85          ThreadPoolConfig fewThreads = ThreadPoolConfig.defaultConfig().copy().
   80.86              setPoolName("Fx/Bck2 Brwsr").
   80.87 -            setCorePoolSize(1).
   80.88 +            setCorePoolSize(3).
   80.89              setMaxPoolSize(5);
   80.90          ThreadPoolConfig oneKernel = ThreadPoolConfig.defaultConfig().copy().
   80.91              setPoolName("Kernel Fx/Bck2").
   80.92 -            setCorePoolSize(1).
   80.93 +            setCorePoolSize(3).
   80.94              setMaxPoolSize(3);
   80.95          for (NetworkListener nl : s.getListeners()) {
   80.96              nl.getTransport().setWorkerThreadPoolConfig(fewThreads);
   80.97 @@ -166,36 +179,81 @@
   80.98          }
   80.99  */        
  80.100          final ServerConfiguration conf = s.getServerConfiguration();
  80.101 +        VMAndPages vm = new VMAndPages();
  80.102 +        conf.addHttpHandler(vm, "/");
  80.103 +        if (vmPrefix != null) {
  80.104 +            vm.registerVM(vmPrefix + "/bck2brwsr.js");
  80.105 +        }
  80.106 +        if (path != null) {
  80.107 +            vm.addDocRoot(path);
  80.108 +        }
  80.109          if (addClasses) {
  80.110 -            conf.addHttpHandler(new VM(), "/bck2brwsr.js");
  80.111              conf.addHttpHandler(new Classes(resources), "/classes/");
  80.112          }
  80.113 +        final WebSocketAddOn addon = new WebSocketAddOn();
  80.114 +        for (NetworkListener listener : s.getListeners()) {
  80.115 +            listener.registerAddOn(addon);
  80.116 +        }
  80.117          return s;
  80.118      }
  80.119      
  80.120      private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
  80.121          wait = new CountDownLatch(1);
  80.122 -        server = initServer(".", true);
  80.123 +        server = initServer(".", true, "");
  80.124          final ServerConfiguration conf = server.getServerConfiguration();
  80.125          
  80.126          class DynamicResourceHandler extends HttpHandler {
  80.127              private final InvocationContext ic;
  80.128 +            private int resourcesCount;
  80.129 +            DynamicResourceHandler delegate;
  80.130              public DynamicResourceHandler(InvocationContext ic) {
  80.131 -                if (ic == null || ic.resources.isEmpty()) {
  80.132 -                    throw new NullPointerException();
  80.133 -                }
  80.134                  this.ic = ic;
  80.135                  for (Resource r : ic.resources) {
  80.136                      conf.addHttpHandler(this, r.httpPath);
  80.137                  }
  80.138              }
  80.139  
  80.140 -            public void close() {
  80.141 +            public void close(DynamicResourceHandler del) {
  80.142                  conf.removeHttpHandler(this);
  80.143 +                delegate = del;
  80.144              }
  80.145              
  80.146              @Override
  80.147              public void service(Request request, Response response) throws Exception {
  80.148 +                if (delegate != null) {
  80.149 +                    delegate.service(request, response);
  80.150 +                    return;
  80.151 +                }
  80.152 +                
  80.153 +                if ("/dynamic".equals(request.getRequestURI())) {
  80.154 +                    boolean webSocket = false;
  80.155 +                    String mimeType = request.getParameter("mimeType");
  80.156 +                    List<String> params = new ArrayList<String>();
  80.157 +                    for (int i = 0; ; i++) {
  80.158 +                        String p = request.getParameter("param" + i);
  80.159 +                        if (p == null) {
  80.160 +                            break;
  80.161 +                        }
  80.162 +                        params.add(p);
  80.163 +                        if ("protocol:ws".equals(p)) {
  80.164 +                            webSocket = true;
  80.165 +                            continue;
  80.166 +                        }                    }
  80.167 +                    final String cnt = request.getParameter("content");
  80.168 +                    String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
  80.169 +                    ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
  80.170 +                    URI url;
  80.171 +                    final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
  80.172 +                    if (webSocket) {
  80.173 +                        url = registerWebSocket(res);
  80.174 +                    } else {
  80.175 +                        url = registerResource(res);
  80.176 +                    }
  80.177 +                    response.getWriter().write(url.toString());
  80.178 +                    response.getWriter().write("\n");
  80.179 +                    return;
  80.180 +                }
  80.181 +                
  80.182                  for (Resource r : ic.resources) {
  80.183                      if (r.httpPath.equals(request.getRequestURI())) {
  80.184                          LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
  80.185 @@ -232,13 +290,26 @@
  80.186                      }
  80.187                  }
  80.188              }
  80.189 +            
  80.190 +            private URI registerWebSocket(Resource r) {
  80.191 +                WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
  80.192 +                return pageURL("ws", server, r.httpPath);
  80.193 +            }
  80.194 +
  80.195 +            private URI registerResource(Resource r) {
  80.196 +                if (!ic.resources.contains(r)) {
  80.197 +                    ic.resources.add(r);
  80.198 +                    conf.addHttpHandler(this, r.httpPath);
  80.199 +                }
  80.200 +                return pageURL("http", server, r.httpPath);
  80.201 +            }
  80.202          }
  80.203          
  80.204          conf.addHttpHandler(new Page(resources, harnessResource()), "/execute");
  80.205          
  80.206          conf.addHttpHandler(new HttpHandler() {
  80.207              int cnt;
  80.208 -            List<InvocationContext> cases = new ArrayList<>();
  80.209 +            List<InvocationContext> cases = new ArrayList<InvocationContext>();
  80.210              DynamicResourceHandler prev;
  80.211              @Override
  80.212              public void service(Request request, Response response) throws Exception {
  80.213 @@ -270,11 +341,6 @@
  80.214                      }
  80.215                  }
  80.216                  
  80.217 -                if (prev != null) {
  80.218 -                    prev.close();
  80.219 -                    prev = null;
  80.220 -                }
  80.221 -                
  80.222                  if (mi == null) {
  80.223                      mi = methods.take();
  80.224                      caseNmbr = cnt++;
  80.225 @@ -286,10 +352,12 @@
  80.226                      LOG.log(Level.INFO, "End of data reached. Exiting.");
  80.227                      return;
  80.228                  }
  80.229 -                
  80.230 -                if (!mi.resources.isEmpty()) {
  80.231 -                    prev = new DynamicResourceHandler(mi);
  80.232 +                final DynamicResourceHandler newRH = new DynamicResourceHandler(mi);
  80.233 +                if (prev != null) {
  80.234 +                    prev.close(newRH);
  80.235                  }
  80.236 +                prev = newRH;
  80.237 +                conf.addHttpHandler(prev, "/dynamic");
  80.238                  
  80.239                  cases.add(mi);
  80.240                  final String cn = mi.clazz.getName();
  80.241 @@ -382,10 +450,7 @@
  80.242  
  80.243      private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
  80.244          server.start();
  80.245 -        NetworkListener listener = server.getListeners().iterator().next();
  80.246 -        int port = listener.getPort();
  80.247 -        
  80.248 -        URI uri = new URI("http://localhost:" + port + page);
  80.249 +        URI uri = pageURL("http", server, page);
  80.250          return showBrwsr(uri);
  80.251      }
  80.252      private static String toUTF8(String value) throws UnsupportedEncodingException {
  80.253 @@ -503,6 +568,16 @@
  80.254          return null;
  80.255      }
  80.256  
  80.257 +    private static URI pageURL(String protocol, HttpServer server, final String page) {
  80.258 +        NetworkListener listener = server.getListeners().iterator().next();
  80.259 +        int port = listener.getPort();
  80.260 +        try {
  80.261 +            return new URI(protocol + "://localhost:" + port + page);
  80.262 +        } catch (URISyntaxException ex) {
  80.263 +            throw new IllegalStateException(ex);
  80.264 +        }
  80.265 +    }
  80.266 +
  80.267      final class Res {
  80.268          String compileJar(JarFile jar) throws IOException {
  80.269              return BaseHTTPLauncher.this.compileJar(jar);
  80.270 @@ -510,7 +585,10 @@
  80.271          String compileFromClassPath(URL f) throws IOException {
  80.272              return BaseHTTPLauncher.this.compileFromClassPath(f, this);
  80.273          }
  80.274 -        public URL get(String resource) throws IOException {
  80.275 +        public URL get(String resource, int skip) throws IOException {
  80.276 +            if (!resource.endsWith(".class")) {
  80.277 +                return getResource(resource, skip);
  80.278 +            }
  80.279              URL u = null;
  80.280              for (ClassLoader l : loaders) {
  80.281                  Enumeration<URL> en = l.getResources(resource);
  80.282 @@ -523,12 +601,30 @@
  80.283              }
  80.284              if (u != null) {
  80.285                  if (u.toExternalForm().contains("rt.jar")) {
  80.286 -                    LOG.log(Level.WARNING, "Fallback to bootclasspath for {0}", u);
  80.287 +                    LOG.log(Level.WARNING, "No fallback to bootclasspath for {0}", u);
  80.288 +                    return null;
  80.289                  }
  80.290                  return u;
  80.291              }
  80.292              throw new IOException("Can't find " + resource);
  80.293          }
  80.294 +        private URL getResource(String resource, int skip) throws IOException {
  80.295 +            for (ClassLoader l : loaders) {
  80.296 +                Enumeration<URL> en = l.getResources(resource);
  80.297 +                while (en.hasMoreElements()) {
  80.298 +                    final URL now = en.nextElement();
  80.299 +                    if (now.toExternalForm().contains("sisu-inject-bean")) {
  80.300 +                        // certainly we don't want this resource, as that
  80.301 +                        // module is not compiled with target 1.6, currently
  80.302 +                        continue;
  80.303 +                    }
  80.304 +                    if (--skip < 0) {
  80.305 +                        return now;
  80.306 +                    }
  80.307 +                }
  80.308 +            }
  80.309 +            throw new IOException("Not found (anymore of) " + resource);
  80.310 +        }
  80.311      }
  80.312  
  80.313      private static class Page extends HttpHandler {
  80.314 @@ -560,7 +656,8 @@
  80.315                  replace = args;
  80.316              }
  80.317              OutputStream os = response.getOutputStream();
  80.318 -            try (InputStream is = res.get(r).openStream()) {
  80.319 +            try { 
  80.320 +                InputStream is = res.get(r, 0).openStream();
  80.321                  copyStream(is, os, request.getRequestURL().toString(), replace);
  80.322              } catch (IOException ex) {
  80.323                  response.setDetailMessage(ex.getLocalizedMessage());
  80.324 @@ -592,14 +689,28 @@
  80.325          
  80.326      }
  80.327  
  80.328 -    private class VM extends HttpHandler {
  80.329 +    private class VMAndPages extends StaticHttpHandler {
  80.330 +        private String vmResource;
  80.331 +        
  80.332 +        public VMAndPages() {
  80.333 +            super((String[]) null);
  80.334 +        }
  80.335 +        
  80.336          @Override
  80.337          public void service(Request request, Response response) throws Exception {
  80.338 -            response.setCharacterEncoding("UTF-8");
  80.339 -            response.setContentType("text/javascript");
  80.340 -            StringBuilder sb = new StringBuilder();
  80.341 -            generateBck2BrwsrJS(sb, BaseHTTPLauncher.this.resources);
  80.342 -            response.getWriter().write(sb.toString());
  80.343 +            if (request.getRequestURI().equals(vmResource)) {
  80.344 +                response.setCharacterEncoding("UTF-8");
  80.345 +                response.setContentType("text/javascript");
  80.346 +                StringBuilder sb = new StringBuilder();
  80.347 +                generateBck2BrwsrJS(sb, BaseHTTPLauncher.this.resources);
  80.348 +                response.getWriter().write(sb.toString());
  80.349 +            } else {
  80.350 +                super.service(request, response);
  80.351 +            }
  80.352 +        }
  80.353 +
  80.354 +        private void registerVM(String vmResource) {
  80.355 +            this.vmResource = vmResource;
  80.356          }
  80.357      }
  80.358  
  80.359 @@ -616,7 +727,9 @@
  80.360              if (res.startsWith("/")) {
  80.361                  res = res.substring(1);
  80.362              }
  80.363 -            URL url = loader.get(res);
  80.364 +            String skip = request.getParameter("skip");
  80.365 +            int skipCnt = skip == null ? 0 : Integer.parseInt(skip);
  80.366 +            URL url = loader.get(res, skipCnt);
  80.367              if (url.getProtocol().equals("jar")) {
  80.368                  JarURLConnection juc = (JarURLConnection) url.openConnection();
  80.369                  String s = loader.compileJar(juc.getJarFile());
  80.370 @@ -639,6 +752,13 @@
  80.371              Exception ex = new Exception("Won't server bytes of " + url);
  80.372              /*
  80.373              try (InputStream is = url.openStream()) {
  80.374 +=======
  80.375 +            InputStream is = null;
  80.376 +            try {
  80.377 +                String skip = request.getParameter("skip");
  80.378 +                int skipCnt = skip == null ? 0 : Integer.parseInt(skip);
  80.379 +                is = loader.get(res, skipCnt);
  80.380 +>>>>>>> other
  80.381                  response.setContentType("text/javascript");
  80.382                  Writer w = response.getWriter();
  80.383                  w.append("([");
  80.384 @@ -664,8 +784,33 @@
  80.385                  response.setStatus(HttpStatus.NOT_FOUND_404);
  80.386                  response.setError();
  80.387                  response.setDetailMessage(ex.getMessage());
  80.388 +            } /*finally {
  80.389 +                if (is != null) {
  80.390 +                    is.close();
  80.391 +                }
  80.392 +            }*/
  80.393 +        }
  80.394 +
  80.395 +    }
  80.396 +    private static class WS extends WebSocketApplication {
  80.397 +
  80.398 +        private final Resource r;
  80.399 +
  80.400 +        private WS(Resource r) {
  80.401 +            this.r = r;
  80.402 +        }
  80.403 +
  80.404 +        @Override
  80.405 +        public void onMessage(WebSocket socket, String text) {
  80.406 +            try {
  80.407 +                r.httpContent.reset();
  80.408 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
  80.409 +                copyStream(r.httpContent, out, null, text);
  80.410 +                String s = new String(out.toByteArray(), "UTF-8");
  80.411 +                socket.send(s);
  80.412 +            } catch (IOException ex) {
  80.413 +                LOG.log(Level.WARNING, null, ex);
  80.414              }
  80.415          }
  80.416  
  80.417 -    }
  80.418 -}
  80.419 +    }}
    81.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java	Tue Apr 29 15:25:58 2014 +0200
    81.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java	Wed Apr 30 15:04:10 2014 +0200
    81.3 @@ -17,13 +17,17 @@
    81.4   */
    81.5  package org.apidesign.bck2brwsr.launcher;
    81.6  
    81.7 +import java.io.File;
    81.8  import org.apidesign.bck2brwsr.launcher.fximpl.FXBrwsr;
    81.9  import java.io.IOException;
   81.10  import java.io.InputStream;
   81.11  import java.lang.reflect.Method;
   81.12 +import java.net.JarURLConnection;
   81.13  import java.net.URI;
   81.14 +import java.net.URISyntaxException;
   81.15  import java.net.URL;
   81.16  import java.net.URLClassLoader;
   81.17 +import java.util.ArrayList;
   81.18  import java.util.Enumeration;
   81.19  import java.util.List;
   81.20  
   81.21 @@ -67,7 +71,17 @@
   81.22                  public void run() {
   81.23                      LOG.log(Level.INFO, "In FX thread. Launching!");
   81.24                      try {
   81.25 -                        FXBrwsr.launch(FXBrwsr.class, url.toString());
   81.26 +                        List<String> params = new ArrayList<String>();
   81.27 +                        params.add(url.toString());
   81.28 +                        if (isDebugged()) {
   81.29 +                            params.add("--toolbar=true");
   81.30 +                            params.add("--firebug=true");
   81.31 +                            String ud = System.getProperty("netbeans.user");
   81.32 +                            if (ud != null) {
   81.33 +                                params.add("--userdir=" + ud);
   81.34 +                            }
   81.35 +                        }
   81.36 +                        FXBrwsr.launch(FXBrwsr.class, params.toArray(new String[params.size()]));
   81.37                          LOG.log(Level.INFO, "Launcher is back. Closing");
   81.38                          close();
   81.39                          System.exit(0);
   81.40 @@ -87,17 +101,6 @@
   81.41          sb.append("(function() {\n"
   81.42              + "  var impl = this.bck2brwsr;\n"
   81.43              + "  this.bck2brwsr = function() { return impl; };\n");
   81.44 -        if (isDebugged()) {
   81.45 -            sb.append("var scr = window.document.createElement('script');\n");
   81.46 -            sb.append("scr.type = 'text/javascript';\n");
   81.47 -            sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
   81.48 -            sb.append("scr.text = '{ startOpened: true }';\n");
   81.49 -            sb.append("var head = window.document.getElementsByTagName('head')[0];");
   81.50 -            sb.append("head.appendChild(scr);\n");
   81.51 -            sb.append("var html = window.document.getElementsByTagName('html')[0];");
   81.52 -            sb.append("html.debug = true;\n");
   81.53 -        }
   81.54 -        
   81.55          sb.append("})(window);\n");
   81.56          JVMBridge.onBck2BrwsrLoad();
   81.57      }
   81.58 @@ -116,25 +119,46 @@
   81.59          String startPage = null;
   81.60  
   81.61          final ClassLoader cl = FXBrwsrLauncher.class.getClassLoader();
   81.62 -        startPage = findStartPage(cl, startPage);
   81.63 +        URL[] manifestURL = { null };
   81.64 +        startPage = findStartPage(cl, startPage, manifestURL);
   81.65          if (startPage == null) {
   81.66              throw new NullPointerException("Can't find StartPage tag in manifests!");
   81.67          }
   81.68          
   81.69 -        Launcher.showURL("fxbrwsr", cl, startPage);
   81.70 +        File dir = new File(".");
   81.71 +        if (manifestURL[0].getProtocol().equals("jar")) {
   81.72 +            try {
   81.73 +                dir = new File(
   81.74 +                    ((JarURLConnection)manifestURL[0].openConnection()).getJarFileURL().toURI()
   81.75 +                ).getParentFile();
   81.76 +            } catch (URISyntaxException ex) {
   81.77 +                LOG.log(Level.WARNING, "Can't find root directory", ex);
   81.78 +            }
   81.79 +        }
   81.80 +        
   81.81 +        Launcher.showDir("fxbrwsr", dir, cl, startPage);
   81.82      }
   81.83      
   81.84 -    private static String findStartPage(final ClassLoader cl, String startPage) throws IOException {
   81.85 +    private static String findStartPage(
   81.86 +        final ClassLoader cl, String startPage, URL[] startURL
   81.87 +    ) throws IOException {
   81.88          Enumeration<URL> en = cl.getResources("META-INF/MANIFEST.MF");
   81.89          while (en.hasMoreElements()) {
   81.90              URL url = en.nextElement();
   81.91              Manifest mf;
   81.92 -            try (InputStream is = url.openStream()) {
   81.93 +            InputStream is = null;
   81.94 +            try {
   81.95 +                is = url.openStream();
   81.96                  mf = new Manifest(is);
   81.97 +            } finally {
   81.98 +                if (is != null) is.close();
   81.99              }
  81.100              String sp = mf.getMainAttributes().getValue("StartPage");
  81.101              if (sp != null) {
  81.102                  startPage = sp;
  81.103 +                if (startURL != null) {
  81.104 +                    startURL[0] = url;
  81.105 +                }
  81.106                  break;
  81.107              }
  81.108          }
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java	Wed Apr 30 15:04:10 2014 +0200
    82.3 @@ -0,0 +1,381 @@
    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.launcher.fximpl;
   82.22 +
   82.23 +import java.util.ArrayList;
   82.24 +import java.util.List;
   82.25 +import javafx.beans.InvalidationListener;
   82.26 +import javafx.beans.Observable;
   82.27 +import javafx.beans.value.ChangeListener;
   82.28 +import javafx.beans.value.ObservableValue;
   82.29 +import javafx.collections.FXCollections;
   82.30 +import javafx.scene.control.ComboBox;
   82.31 +import javafx.scene.control.ScrollPane;
   82.32 +import javafx.scene.control.Separator;
   82.33 +import javafx.scene.control.Toggle;
   82.34 +import javafx.scene.control.ToggleButton;
   82.35 +import javafx.scene.control.ToggleGroup;
   82.36 +import javafx.scene.control.ToolBar;
   82.37 +import javafx.scene.control.Tooltip;
   82.38 +import javafx.scene.image.Image;
   82.39 +import javafx.scene.image.ImageView;
   82.40 +import javafx.scene.layout.Pane;
   82.41 +import javafx.scene.web.WebEngine;
   82.42 +import javafx.scene.web.WebView;
   82.43 +
   82.44 +final class BrowserToolbar extends ToolBar {
   82.45 +    private final ArrayList<ResizeBtn> resizeButtons;
   82.46 +    private final WebView webView;
   82.47 +    private final Pane container;
   82.48 +    private final ToggleGroup resizeGroup = new ToggleGroup();
   82.49 +    private final ComboBox<String> comboZoom = new ComboBox<String>();
   82.50 +    
   82.51 +    BrowserToolbar(WebView webView, Pane container, boolean useFirebug) {
   82.52 +        this.webView = webView;
   82.53 +        this.container = container;
   82.54 +        
   82.55 +        List<ResizeOption> options = ResizeOption.loadAll();
   82.56 +        options.add( 0, ResizeOption.SIZE_TO_FIT );
   82.57 +        resizeButtons = new ArrayList<ResizeBtn>( options.size() );
   82.58 +
   82.59 +        for( ResizeOption ro : options ) {
   82.60 +            ResizeBtn button = new ResizeBtn(ro);
   82.61 +            resizeButtons.add( button );
   82.62 +            resizeGroup.getToggles().add( button );
   82.63 +            getItems().add( button );
   82.64 +        }
   82.65 +        resizeButtons.get( 0 ).setSelected( true );
   82.66 +        resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
   82.67 +
   82.68 +            @Override
   82.69 +            public void invalidated( Observable o ) {
   82.70 +                resize();
   82.71 +            }
   82.72 +        });
   82.73 +        
   82.74 +        getItems().add( new Separator() );
   82.75 +
   82.76 +        getItems().add( comboZoom );
   82.77 +        ArrayList<String> zoomModel = new ArrayList<String>( 6 );
   82.78 +        zoomModel.add( "200%" ); //NOI18N
   82.79 +        zoomModel.add( "150%" ); //NOI18N
   82.80 +        zoomModel.add( "100%" ); //NOI18N
   82.81 +        zoomModel.add( "75%" ); //NOI18N
   82.82 +        zoomModel.add( "50%" ); //NOI18N
   82.83 +        comboZoom.setItems( FXCollections.observableList( zoomModel ) );
   82.84 +        comboZoom.setEditable( true );
   82.85 +        comboZoom.setValue( "100%" ); //NOI18N
   82.86 +        comboZoom.valueProperty().addListener( new ChangeListener<String>() {
   82.87 +
   82.88 +            @Override
   82.89 +            public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
   82.90 +                String newZoom = zoom( t1 );
   82.91 +                comboZoom.setValue( newZoom );
   82.92 +            }
   82.93 +        });
   82.94 +        
   82.95 +        if (useFirebug) {
   82.96 +            getItems().add(new Separator());
   82.97 +
   82.98 +            final ToggleButton firebug = new ToggleButton(null, new ImageView(
   82.99 +                new Image(BrowserToolbar.class.getResourceAsStream("firebug.png"))
  82.100 +            ));
  82.101 +            firebug.setTooltip(new Tooltip("Show/Hide firebug"));
  82.102 +            firebug.selectedProperty().addListener(new InvalidationListener() {
  82.103 +                @Override
  82.104 +                public void invalidated(Observable o) {
  82.105 +                    toggleFireBug(firebug.isSelected());
  82.106 +                }
  82.107 +            });
  82.108 +            getItems().add(firebug);
  82.109 +        }
  82.110 +    }
  82.111 +
  82.112 +    private String zoom( String zoomFactor ) {
  82.113 +        if( zoomFactor.trim().isEmpty() )
  82.114 +            return null;
  82.115 +
  82.116 +        try {
  82.117 +            zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
  82.118 +            zoomFactor = zoomFactor.trim();
  82.119 +            double zoom = Double.parseDouble( zoomFactor );
  82.120 +            zoom = Math.abs( zoom )/100;
  82.121 +            if( zoom <= 0.0 )
  82.122 +                return null;
  82.123 +            webView.setScaleX(zoom);
  82.124 +            webView.setScaleY(zoom);
  82.125 +            webView.setScaleZ(zoom);
  82.126 +            return (int)(100*zoom) + "%"; //NOI18N
  82.127 +        } catch( NumberFormatException nfe ) {
  82.128 +            //ignore
  82.129 +        }
  82.130 +        return null;
  82.131 +    }
  82.132 +
  82.133 +    private void resize() {
  82.134 +        Toggle selection = resizeGroup.getSelectedToggle();
  82.135 +        if( selection instanceof ResizeBtn ) {
  82.136 +            ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
  82.137 +            if( ro == ResizeOption.SIZE_TO_FIT ) {
  82.138 +                _autofit();
  82.139 +            } else {
  82.140 +                _resize( ro.getWidth(), ro.getHeight() );
  82.141 +            }
  82.142 +        }
  82.143 +
  82.144 +    }
  82.145 +
  82.146 +    private void _resize( final double width, final double height ) {
  82.147 +        ScrollPane scroll;
  82.148 +        if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
  82.149 +            scroll = new ScrollPane();
  82.150 +            scroll.setContent( webView );
  82.151 +            container.getChildren().clear();
  82.152 +            container.getChildren().add( scroll );
  82.153 +        } else {
  82.154 +            scroll = ( ScrollPane ) container.getChildren().get( 0 );
  82.155 +        }
  82.156 +        scroll.setPrefViewportWidth( width );
  82.157 +        scroll.setPrefViewportHeight(height );
  82.158 +        webView.setMaxWidth( width );
  82.159 +        webView.setMaxHeight( height );
  82.160 +        webView.setMinWidth( width );
  82.161 +        webView.setMinHeight( height );
  82.162 +    }
  82.163 +
  82.164 +    private void _autofit() {
  82.165 +        if( container.getChildren().get( 0) instanceof ScrollPane ) {
  82.166 +            container.getChildren().clear();
  82.167 +            container.getChildren().add( webView );
  82.168 +        }
  82.169 +        webView.setMaxWidth( Integer.MAX_VALUE );
  82.170 +        webView.setMaxHeight( Integer.MAX_VALUE );
  82.171 +        webView.setMinWidth( -1 );
  82.172 +        webView.setMinHeight( -1 );
  82.173 +        webView.autosize();
  82.174 +    }
  82.175 +
  82.176 +    final void toggleFireBug(boolean enable) {
  82.177 +        WebEngine eng = webView.getEngine();
  82.178 +        Object installed = eng.executeScript("window.Firebug");
  82.179 +        if ("undefined".equals(installed)) {
  82.180 +            StringBuilder sb = new StringBuilder();
  82.181 +            sb.append("var scr = window.document.createElement('script');\n");
  82.182 +            sb.append("scr.type = 'text/javascript';\n");
  82.183 +            sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
  82.184 +            sb.append("scr.text = '{ startOpened: true }';\n");
  82.185 +            sb.append("var head = window.document.getElementsByTagName('head')[0];");
  82.186 +            sb.append("head.appendChild(scr);\n");
  82.187 +            sb.append("var html = window.document.getElementsByTagName('html')[0];");
  82.188 +            sb.append("html.debug = true;\n");
  82.189 +            eng.executeScript(sb.toString());
  82.190 +        } else {
  82.191 +            if (enable) {
  82.192 +                eng.executeScript("Firebug.chrome.open()");
  82.193 +            } else {
  82.194 +                eng.executeScript("Firebug.chrome.close()");
  82.195 +            }
  82.196 +        }
  82.197 +    }
  82.198 +
  82.199 +    /**
  82.200 +     * Button to resize the browser window.
  82.201 +     * Taken from NetBeans. Kept GPLwithCPEx license.
  82.202 +     * Portions Copyrighted 2012 Sun Microsystems, Inc.
  82.203 +     *
  82.204 +     * @author S. Aubrecht
  82.205 +     */
  82.206 +    static final class ResizeBtn extends ToggleButton {
  82.207 +
  82.208 +        private final ResizeOption resizeOption;
  82.209 +
  82.210 +        ResizeBtn(ResizeOption resizeOption) {
  82.211 +            super(null, new ImageView(toImage(resizeOption)));
  82.212 +            this.resizeOption = resizeOption;
  82.213 +            setTooltip(new Tooltip(resizeOption.getToolTip()));
  82.214 +        }
  82.215 +
  82.216 +        ResizeOption getResizeOption() {
  82.217 +            return resizeOption;
  82.218 +        }
  82.219 +
  82.220 +        static Image toImage(ResizeOption ro) {
  82.221 +            if (ro == ResizeOption.SIZE_TO_FIT) {
  82.222 +                return ResizeOption.Type.CUSTOM.getImage();
  82.223 +            }
  82.224 +            return ro.getType().getImage();
  82.225 +        }
  82.226 +    }
  82.227 +
  82.228 +    /**
  82.229 +     * Immutable value class describing a single button to resize web browser window.
  82.230 +     * Taken from NetBeans. Kept GPLwithCPEx license.
  82.231 +     * Portions Copyrighted 2012 Sun Microsystems, Inc.
  82.232 +     *
  82.233 +     * @author S. Aubrecht
  82.234 +     */
  82.235 +    static final class ResizeOption {
  82.236 +
  82.237 +        private final Type type;
  82.238 +        private final String displayName;
  82.239 +        private final int width;
  82.240 +        private final int height;
  82.241 +        private final boolean isDefault;
  82.242 +
  82.243 +        enum Type {
  82.244 +            DESKTOP("desktop.png"), 
  82.245 +            TABLET_PORTRAIT("tabletPortrait.png"), 
  82.246 +            TABLET_LANDSCAPE("tabletLandscape.png"), 
  82.247 +            SMARTPHONE_PORTRAIT("handheldPortrait.png"), 
  82.248 +            SMARTPHONE_LANDSCAPE("handheldLandscape.png"), 
  82.249 +            WIDESCREEN("widescreen.png"), 
  82.250 +            NETBOOK("netbook.png"), 
  82.251 +            CUSTOM("sizeToFit.png");
  82.252 +            
  82.253 +            
  82.254 +            private final String resource;
  82.255 +
  82.256 +            private Type(String r) {
  82.257 +                resource = r;
  82.258 +            }
  82.259 +
  82.260 +            public Image getImage() {
  82.261 +                return new Image(Type.class.getResourceAsStream(resource));
  82.262 +            }
  82.263 +        }
  82.264 +
  82.265 +        private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
  82.266 +            super();
  82.267 +            this.type = type;
  82.268 +            this.displayName = displayName;
  82.269 +            this.width = width;
  82.270 +            this.height = height;
  82.271 +            this.isDefault = isDefault;
  82.272 +        }
  82.273 +
  82.274 +        static List<ResizeOption> loadAll() {
  82.275 +            List<ResizeOption> res = new ArrayList<ResizeOption>(10);
  82.276 +            res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
  82.277 +            res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
  82.278 +            res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
  82.279 +            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
  82.280 +            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
  82.281 +            res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
  82.282 +            res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
  82.283 +            return res;
  82.284 +        }
  82.285 +        
  82.286 +        /**
  82.287 +         * Creates a new instance.
  82.288 +         * @param type
  82.289 +         * @param displayName Display name to show in tooltip, cannot be empty.
  82.290 +         * @param width Screen width
  82.291 +         * @param height Screen height
  82.292 +         * @param showInToolbar True to show in web developer toolbar.
  82.293 +         * @param isDefault True if this is a predefined option that cannot be removed.
  82.294 +         * @return New instance.
  82.295 +         */
  82.296 +        public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
  82.297 +            if (width <= 0 || height <= 0) {
  82.298 +                throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
  82.299 +            }
  82.300 +            return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
  82.301 +        }
  82.302 +        /**
  82.303 +         * An extra option to size the browser content to fit its window.
  82.304 +         */
  82.305 +        public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
  82.306 +
  82.307 +        public String getDisplayName() {
  82.308 +            return displayName;
  82.309 +        }
  82.310 +
  82.311 +        public Type getType() {
  82.312 +            return type;
  82.313 +        }
  82.314 +
  82.315 +        public int getWidth() {
  82.316 +            return width;
  82.317 +        }
  82.318 +
  82.319 +        public int getHeight() {
  82.320 +            return height;
  82.321 +        }
  82.322 +
  82.323 +        public boolean isDefault() {
  82.324 +            return isDefault;
  82.325 +        }
  82.326 +
  82.327 +        @Override
  82.328 +        public String toString() {
  82.329 +            return displayName;
  82.330 +        }
  82.331 +
  82.332 +        public String getToolTip() {
  82.333 +            if (width < 0 || height < 0) {
  82.334 +                return displayName;
  82.335 +            }
  82.336 +            StringBuilder sb = new StringBuilder();
  82.337 +            sb.append(width);
  82.338 +            sb.append(" x "); //NOI18N
  82.339 +            sb.append(height);
  82.340 +            sb.append(" ("); //NOI18N
  82.341 +            sb.append(displayName);
  82.342 +            sb.append(')'); //NOI18N
  82.343 +            return sb.toString();
  82.344 +        }
  82.345 +
  82.346 +        @Override
  82.347 +        public boolean equals(Object obj) {
  82.348 +            if (obj == null) {
  82.349 +                return false;
  82.350 +            }
  82.351 +            if (getClass() != obj.getClass()) {
  82.352 +                return false;
  82.353 +            }
  82.354 +            final ResizeOption other = (ResizeOption) obj;
  82.355 +            if (this.type != other.type) {
  82.356 +                return false;
  82.357 +            }
  82.358 +            if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
  82.359 +                return false;
  82.360 +            }
  82.361 +            if (this.width != other.width) {
  82.362 +                return false;
  82.363 +            }
  82.364 +            if (this.height != other.height) {
  82.365 +                return false;
  82.366 +            }
  82.367 +            if (this.isDefault != other.isDefault) {
  82.368 +                return false;
  82.369 +            }
  82.370 +            return true;
  82.371 +        }
  82.372 +
  82.373 +        @Override
  82.374 +        public int hashCode() {
  82.375 +            int hash = 7;
  82.376 +            hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
  82.377 +            hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
  82.378 +            hash = 11 * hash + this.width;
  82.379 +            hash = 11 * hash + this.height;
  82.380 +            hash = 11 * hash + (this.isDefault ? 1 : 0);
  82.381 +            return hash;
  82.382 +        }
  82.383 +    }
  82.384 +}
    83.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java	Tue Apr 29 15:25:58 2014 +0200
    83.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java	Wed Apr 30 15:04:10 2014 +0200
    83.3 @@ -25,7 +25,7 @@
    83.4  import java.lang.reflect.Modifier;
    83.5  import java.net.URL;
    83.6  import java.util.Enumeration;
    83.7 -import javafx.scene.web.WebEngine;
    83.8 +import net.java.html.js.JavaScriptBody;
    83.9  import netscape.javascript.JSObject;
   83.10  
   83.11  /**
   83.12 @@ -35,17 +35,15 @@
   83.13  public final class Console {
   83.14      public Console() {
   83.15      }
   83.16 -    
   83.17 -    private static Object getAttr(Object elem, String attr) {
   83.18 -        return InvokeJS.CObject.call("getAttr", elem, attr);
   83.19 -    }
   83.20  
   83.21 -    private static void setAttr(String id, String attr, Object value) {
   83.22 -        InvokeJS.CObject.call("setAttrId", id, attr, value);
   83.23 -    }
   83.24 -    private static void setAttr(Object id, String attr, Object value) {
   83.25 -        InvokeJS.CObject.call("setAttr", id, attr, value);
   83.26 -    }
   83.27 +    @JavaScriptBody(args = { "elem", "attr" }, body = "return elem[attr].toString();")
   83.28 +    private static native Object getAttr(Object elem, String attr);
   83.29 +
   83.30 +    @JavaScriptBody(args = { "id", "attr", "value" }, body = "window.document.getElementById(id)[attr] = value;")
   83.31 +    private static native void setAttr(String id, String attr, Object value);
   83.32 +
   83.33 +    @JavaScriptBody(args = { "elem", "attr", "value" }, body = "elem[attr] = value;")
   83.34 +    private static native void setAttr(Object id, String attr, Object value);
   83.35      
   83.36      private static void closeWindow() {}
   83.37  
   83.38 @@ -62,8 +60,7 @@
   83.39      }
   83.40      
   83.41      private static void beginTest(Case c) {
   83.42 -        Object[] arr = new Object[2];
   83.43 -        beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
   83.44 +        Object[] arr = beginTest(c.getClassName() + "." + c.getMethodName(), c, new Object[2]);
   83.45          textArea = arr[0];
   83.46          statusArea = arr[1];
   83.47      }
   83.48 @@ -78,7 +75,7 @@
   83.49          textArea = null;
   83.50      }
   83.51  
   83.52 -    private static final String BEGIN_TEST =  
   83.53 +    @JavaScriptBody(args = { "test", "c", "arr" }, body = 
   83.54          "var ul = window.document.getElementById('bck2brwsr.result');\n"
   83.55          + "var li = window.document.createElement('li');\n"
   83.56          + "var span = window.document.createElement('span');"
   83.57 @@ -103,27 +100,24 @@
   83.58          + "p.appendChild(pre);\n"
   83.59          + "ul.appendChild(li);\n"
   83.60          + "arr[0] = pre;\n"
   83.61 -        + "arr[1] = status;\n";
   83.62 -        
   83.63 -    private static void beginTest(String test, Case c, Object[] arr) {
   83.64 -        InvokeJS.CObject.call("beginTest", test, c, arr);
   83.65 -    }
   83.66 +        + "arr[1] = status;\n"
   83.67 +        + "return arr;"
   83.68 +    )
   83.69 +    private static native Object[] beginTest(String test, Case c, Object[] arr);
   83.70      
   83.71 -    private static final String LOAD_TEXT = 
   83.72 +    @JavaScriptBody(args = { "url", "callback" }, javacall = true, body =
   83.73            "var request = new XMLHttpRequest();\n"
   83.74          + "request.open('GET', url, true);\n"
   83.75          + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
   83.76          + "request.onreadystatechange = function() {\n"
   83.77          + "  if (this.readyState!==4) return;\n"
   83.78 -        + " try {"
   83.79 -        + "  arr[0] = this.responseText;\n"
   83.80 -        + "  callback.run__V();\n"
   83.81 -        + " } catch (e) { alert(e); }"
   83.82 -        + "};"
   83.83 -        + "request.send();";
   83.84 -    private static void loadText(String url, Runnable callback, String[] arr) throws IOException {
   83.85 -        InvokeJS.CObject.call("loadText", url, new Run(callback), arr);
   83.86 -    }
   83.87 +        + " try {\n"
   83.88 +        + "  callback.@org.apidesign.bck2brwsr.launcher.fximpl.OnMessage::onMessage(Ljava/lang/String;)(this.responseText);\n"
   83.89 +        + " } catch (e) { alert(e); }\n"
   83.90 +        + "};\n"
   83.91 +        + "request.send();\n"
   83.92 +    )
   83.93 +    private static native void loadText(String url, OnMessage callback) throws IOException;
   83.94      
   83.95      public static void runHarness(String url) throws IOException {
   83.96          new Console().harness(url);
   83.97 @@ -134,7 +128,7 @@
   83.98          Request r = new Request(url);
   83.99      }
  83.100      
  83.101 -    private static class Request implements Runnable {
  83.102 +    private static class Request implements Runnable, OnMessage {
  83.103          private final String[] arr = { null };
  83.104          private final String url;
  83.105          private Case c;
  83.106 @@ -142,15 +136,22 @@
  83.107  
  83.108          private Request(String url) throws IOException {
  83.109              this.url = url;
  83.110 -            loadText(url, this, arr);
  83.111 +            loadText(url, this);
  83.112          }
  83.113          private Request(String url, String u) throws IOException {
  83.114              this.url = url;
  83.115 -            loadText(u, this, arr);
  83.116 +            loadText(u, this);
  83.117 +        }
  83.118 +
  83.119 +        @Override
  83.120 +        public void onMessage(String msg) {
  83.121 +            arr[0] = msg;
  83.122 +            run();
  83.123          }
  83.124          
  83.125          @Override
  83.126          public void run() {
  83.127 +            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
  83.128              try {
  83.129                  if (c == null) {
  83.130                      String data = arr[0];
  83.131 @@ -232,7 +233,9 @@
  83.132          if (u == null) {
  83.133              throw new IOException("Can't find " + name);
  83.134          }
  83.135 -        try (InputStream is = u.openStream()) {
  83.136 +        InputStream is = null;
  83.137 +        try {
  83.138 +            is = u.openStream();
  83.139              byte[] arr;
  83.140              arr = new byte[is.available()];
  83.141              int offset = 0;
  83.142 @@ -244,15 +247,20 @@
  83.143                  offset += len;
  83.144              }
  83.145              return arr;
  83.146 +        } finally {
  83.147 +            if (is != null) is.close();
  83.148          }
  83.149      }
  83.150     
  83.151      private static void turnAssetionStatusOn() {
  83.152      }
  83.153  
  83.154 -    private static Object schedule(Runnable r, int time) {
  83.155 -        return InvokeJS.CObject.call("schedule", new Run(r), time);
  83.156 -    }
  83.157 +    @JavaScriptBody(args = { "r", "time" }, javacall = true, body = 
  83.158 +        "return window.setTimeout(function() { "
  83.159 +        + "r.@java.lang.Runnable::run()(); "
  83.160 +        + "}, time);"
  83.161 +    )
  83.162 +    private static native Object schedule(Runnable r, int time);
  83.163      
  83.164      private static final class Case {
  83.165          private final Object data;
  83.166 @@ -348,48 +356,16 @@
  83.167              }
  83.168              return res;
  83.169          }
  83.170 -        
  83.171 -        private static Object toJSON(String s) {
  83.172 -            return InvokeJS.CObject.call("toJSON", s);
  83.173 -        }
  83.174 +
  83.175 +        @JavaScriptBody(args = { "s" }, body = "return eval('(' + s + ')');")
  83.176 +        private static native Object toJSON(String s);
  83.177          
  83.178          private static Object value(String p, Object d) {
  83.179              return ((JSObject)d).getMember(p);
  83.180          }
  83.181      }
  83.182      
  83.183 -    private static String safe(String txt) {
  83.184 -        return "try {" + txt + "} catch (err) { alert(err); }";
  83.185 -    }
  83.186 -    
  83.187      static {
  83.188          turnAssetionStatusOn();
  83.189      }
  83.190 -    
  83.191 -    private static final class InvokeJS {
  83.192 -        static final JSObject CObject = initJS();
  83.193 -
  83.194 -        private static JSObject initJS() {
  83.195 -            WebEngine web = (WebEngine) System.getProperties().get("webEngine");
  83.196 -            return (JSObject) web.executeScript("(function() {"
  83.197 -                + "var CObject = {};"
  83.198 -
  83.199 -                + "CObject.getAttr = function(elem, attr) { return elem[attr].toString(); };"
  83.200 -
  83.201 -                + "CObject.setAttrId = function(id, attr, value) { window.document.getElementById(id)[attr] = value; };"
  83.202 -                + "CObject.setAttr = function(elem, attr, value) { elem[attr] = value; };"
  83.203 -
  83.204 -                + "CObject.beginTest = function(test, c, arr) {" + safe(BEGIN_TEST) + "};"
  83.205 -
  83.206 -                + "CObject.loadText = function(url, callback, arr) {" + safe(LOAD_TEXT.replace("run__V", "run")) + "};"
  83.207 -
  83.208 -                + "CObject.schedule = function(r, time) { return window.setTimeout(function() { r.run(); }, time); };"
  83.209 -
  83.210 -                + "CObject.toJSON = function(s) { return eval('(' + s + ')'); };"
  83.211 -
  83.212 -                + "return CObject;"
  83.213 -            + "})(this)");
  83.214 -        }
  83.215 -    }
  83.216 -    
  83.217  }
    84.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Tue Apr 29 15:25:58 2014 +0200
    84.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Wed Apr 30 15:04:10 2014 +0200
    84.3 @@ -27,16 +27,13 @@
    84.4  import javafx.beans.value.ObservableValue;
    84.5  import javafx.event.ActionEvent;
    84.6  import javafx.event.EventHandler;
    84.7 -import javafx.geometry.HPos;
    84.8  import javafx.geometry.Insets;
    84.9  import javafx.geometry.Pos;
   84.10 -import javafx.geometry.VPos;
   84.11 -import javafx.scene.Node;
   84.12  import javafx.scene.Scene;
   84.13  import javafx.scene.control.Button;
   84.14 -import javafx.scene.layout.ColumnConstraints;
   84.15 -import javafx.scene.layout.GridPane;
   84.16 -import javafx.scene.layout.Pane;
   84.17 +import javafx.scene.control.ToolBar;
   84.18 +import javafx.scene.layout.BorderPane;
   84.19 +import javafx.scene.layout.HBox;
   84.20  import javafx.scene.layout.Priority;
   84.21  import javafx.scene.layout.VBox;
   84.22  import javafx.scene.text.Text;
   84.23 @@ -55,30 +52,52 @@
   84.24   */
   84.25  public class FXBrwsr extends Application {
   84.26      private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
   84.27 -
   84.28 +    
   84.29      @Override
   84.30      public void start(Stage primaryStage) throws Exception {
   84.31 -        Pane root = new WebViewPane(getParameters().getUnnamed());
   84.32 -        primaryStage.setScene(new Scene(root, 1024, 768));
   84.33 -        LOG.info("Showing the stage");
   84.34 +        WebView view = new WebView();
   84.35 +        WebController wc = new WebController(view, getParameters().getUnnamed());
   84.36 +        
   84.37 +        FXInspect.initialize(view.getEngine());
   84.38 +
   84.39 +        final VBox vbox = new VBox();
   84.40 +        vbox.setAlignment( Pos.CENTER );
   84.41 +        vbox.setStyle( "-fx-background-color: #808080;");
   84.42 +
   84.43 +
   84.44 +        HBox hbox = new HBox();
   84.45 +        hbox.setStyle( "-fx-background-color: #808080;");
   84.46 +        hbox.setAlignment(Pos.CENTER);
   84.47 +        hbox.getChildren().add(vbox);
   84.48 +        HBox.setHgrow(vbox, Priority.ALWAYS);
   84.49 +        vbox.getChildren().add(view);
   84.50 +        VBox.setVgrow(view, Priority.ALWAYS);
   84.51 +
   84.52 +        BorderPane root = new BorderPane();
   84.53 +        final boolean showToolbar = "true".equals(this.getParameters().getNamed().get("toolbar")); // NOI18N
   84.54 +        final boolean useFirebug = "true".equals(this.getParameters().getNamed().get("firebug")); // NOI18N
   84.55 +        if (showToolbar) {
   84.56 +            final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug);
   84.57 +            root.setTop( toolbar );
   84.58 +        }
   84.59 +        root.setCenter(hbox);
   84.60 +
   84.61 +        Scene scene = new Scene(root, 800, 600);
   84.62 +
   84.63 +        primaryStage.setTitle( "Device Emulator" );
   84.64 +        primaryStage.setScene( scene );
   84.65          primaryStage.show();
   84.66 -        LOG.log(Level.INFO, "State shown: {0}", primaryStage.isShowing());
   84.67      }
   84.68      
   84.69      /**
   84.70       * Create a resizable WebView pane
   84.71       */
   84.72 -    private class WebViewPane extends Pane {
   84.73 -        private final JVMBridge bridge = new JVMBridge();
   84.74 +    private static class WebController {
   84.75 +        private final JVMBridge bridge;
   84.76  
   84.77 -        public WebViewPane(List<String> params) {
   84.78 +        public WebController(WebView view, List<String> params) {
   84.79 +            this.bridge = new JVMBridge(view.getEngine());
   84.80              LOG.log(Level.INFO, "Initializing WebView with {0}", params);
   84.81 -            VBox.setVgrow(this, Priority.ALWAYS);
   84.82 -            setMaxWidth(Double.MAX_VALUE);
   84.83 -            setMaxHeight(Double.MAX_VALUE);
   84.84 -            WebView view = new WebView();
   84.85 -            view.setMinSize(500, 400);
   84.86 -            view.setPrefSize(500, 400);
   84.87              final WebEngine eng = view.getEngine();
   84.88              try {
   84.89                  JVMBridge.addBck2BrwsrLoad(new InitBck2Brwsr(eng));
   84.90 @@ -120,13 +139,6 @@
   84.91                      dialogStage.showAndWait();
   84.92                  }
   84.93              });
   84.94 -            GridPane grid = new GridPane();
   84.95 -            grid.setVgap(5);
   84.96 -            grid.setHgap(5);
   84.97 -            GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS);
   84.98 -            grid.getColumnConstraints().addAll(new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true), new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true));
   84.99 -            grid.getChildren().addAll(view);
  84.100 -            getChildren().add(grid);
  84.101          }
  84.102  
  84.103          boolean initBck2Brwsr(WebEngine webEngine) {
  84.104 @@ -134,28 +146,12 @@
  84.105              LOG.log(Level.FINE, "window: {0}", jsobj);
  84.106              Object prev = jsobj.getMember("bck2brwsr");
  84.107              if ("undefined".equals(prev)) {
  84.108 -                System.getProperties().put("webEngine", webEngine);
  84.109                  jsobj.setMember("bck2brwsr", bridge);
  84.110                  return true;
  84.111              }
  84.112              return false;
  84.113          }
  84.114  
  84.115 -        @Override
  84.116 -        protected void layoutChildren() {
  84.117 -            List<Node> managed = getManagedChildren();
  84.118 -            double width = getWidth();
  84.119 -            double height = getHeight();
  84.120 -            double top = getInsets().getTop();
  84.121 -            double right = getInsets().getRight();
  84.122 -            double left = getInsets().getLeft();
  84.123 -            double bottom = getInsets().getBottom();
  84.124 -            for (int i = 0; i < managed.size(); i++) {
  84.125 -                Node child = managed.get(i);
  84.126 -                layoutInArea(child, left, top, width - left - right, height - top - bottom, 0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
  84.127 -            }
  84.128 -        }
  84.129 -
  84.130          private class InitBck2Brwsr implements ChangeListener<Void>, Runnable {
  84.131              private final WebEngine eng;
  84.132  
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXInspect.java	Wed Apr 30 15:04:10 2014 +0200
    85.3 @@ -0,0 +1,111 @@
    85.4 +/**
    85.5 + * Back 2 Browser Bytecode Translator
    85.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    85.7 + *
    85.8 + * This program is free software: you can redistribute it and/or modify
    85.9 + * it under the terms of the GNU General Public License as published by
   85.10 + * the Free Software Foundation, version 2 of the License.
   85.11 + *
   85.12 + * This program is distributed in the hope that it will be useful,
   85.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   85.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   85.15 + * GNU General Public License for more details.
   85.16 + *
   85.17 + * You should have received a copy of the GNU General Public License
   85.18 + * along with this program. Look for COPYING file in the top folder.
   85.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   85.20 + */
   85.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   85.22 +
   85.23 +import com.sun.javafx.scene.web.Debugger;
   85.24 +import java.io.IOException;
   85.25 +import java.io.ObjectInputStream;
   85.26 +import java.io.ObjectOutputStream;
   85.27 +import java.net.InetAddress;
   85.28 +import java.net.Socket;
   85.29 +import java.nio.charset.StandardCharsets;
   85.30 +import java.util.logging.Level;
   85.31 +import java.util.logging.Logger;
   85.32 +import javafx.application.Platform;
   85.33 +import javafx.scene.web.WebEngine;
   85.34 +import javafx.util.Callback;
   85.35 +
   85.36 +/**
   85.37 + *
   85.38 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   85.39 + */
   85.40 +final class FXInspect implements Runnable {
   85.41 +    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
   85.42 +    
   85.43 +    
   85.44 +    private final WebEngine engine;
   85.45 +    private final ObjectInputStream input;
   85.46 +    
   85.47 +    private FXInspect(WebEngine engine, int port) throws IOException {
   85.48 +        this.engine = engine;
   85.49 +        
   85.50 +        Socket socket = new Socket(InetAddress.getByName(null), port);
   85.51 +        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
   85.52 +        this.input = new ObjectInputStream(socket.getInputStream());
   85.53 +        initializeDebugger(output);
   85.54 +    }
   85.55 +    
   85.56 +    static boolean initialize(WebEngine engine) {
   85.57 +        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
   85.58 +        if (inspectPort != -1) {
   85.59 +            try {
   85.60 +                FXInspect inspector = new FXInspect(engine, inspectPort);
   85.61 +                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
   85.62 +                t.start();
   85.63 +                return true;
   85.64 +            } catch (IOException ex) {
   85.65 +                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
   85.66 +            }
   85.67 +        }
   85.68 +        return false;
   85.69 +    }
   85.70 +    
   85.71 +    private void initializeDebugger(final ObjectOutputStream output) {
   85.72 +        Platform.runLater(new Runnable() {
   85.73 +            @Override
   85.74 +            public void run() {
   85.75 +                Debugger debugger = engine.impl_getDebugger();
   85.76 +                debugger.setEnabled(true);
   85.77 +                debugger.setMessageCallback(new Callback<String,Void>() {
   85.78 +                    @Override
   85.79 +                    public Void call(String message) {
   85.80 +                        try {
   85.81 +                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
   85.82 +                            output.writeInt(bytes.length);
   85.83 +                            output.write(bytes);
   85.84 +                            output.flush();
   85.85 +                        } catch (IOException ioex) {
   85.86 +                            ioex.printStackTrace();
   85.87 +                        }
   85.88 +                        return null;
   85.89 +                    }
   85.90 +                });
   85.91 +            }
   85.92 +        });
   85.93 +    }
   85.94 +
   85.95 +    @Override
   85.96 +    public void run() {
   85.97 +        try {
   85.98 +            while (true) {
   85.99 +                int length = input.readInt();
  85.100 +                byte[] bytes = new byte[length];
  85.101 +                input.readFully(bytes);
  85.102 +                final String message = new String(bytes, StandardCharsets.UTF_8);
  85.103 +                Platform.runLater(new Runnable() {
  85.104 +                    @Override
  85.105 +                    public void run() {
  85.106 +                        engine.impl_getDebugger().sendMessage(message);
  85.107 +                    }
  85.108 +                });
  85.109 +            }
  85.110 +        } catch (IOException ioex) {
  85.111 +            ioex.printStackTrace();
  85.112 +        }
  85.113 +    }
  85.114 +}
    86.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Tue Apr 29 15:25:58 2014 +0200
    86.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Wed Apr 30 15:04:10 2014 +0200
    86.3 @@ -17,16 +17,45 @@
    86.4   */
    86.5  package org.apidesign.bck2brwsr.launcher.fximpl;
    86.6  
    86.7 +import java.io.BufferedReader;
    86.8 +import java.io.Reader;
    86.9 +import java.net.URL;
   86.10 +import java.util.ArrayList;
   86.11 +import java.util.Arrays;
   86.12 +import java.util.Collection;
   86.13 +import java.util.List;
   86.14  import java.util.TooManyListenersException;
   86.15 +import java.util.concurrent.Executor;
   86.16 +import java.util.logging.Level;
   86.17 +import java.util.logging.Logger;
   86.18 +import javafx.application.Platform;
   86.19  import javafx.beans.value.ChangeListener;
   86.20 +import javafx.scene.web.WebEngine;
   86.21 +import netscape.javascript.JSObject;
   86.22 +import org.apidesign.html.boot.spi.Fn;
   86.23 +import org.netbeans.html.boot.impl.FindResources;
   86.24 +import org.netbeans.html.boot.impl.FnUtils;
   86.25  
   86.26  /**
   86.27   *
   86.28   * @author Jaroslav Tulach <jtulach@netbeans.org>
   86.29   */
   86.30  public final class JVMBridge {
   86.31 +    static final Logger LOG = Logger.getLogger(JVMBridge.class.getName());
   86.32 +    
   86.33 +    private final WebEngine engine;
   86.34 +    private final ClassLoader cl;
   86.35 +    private final WebPresenter presenter;
   86.36 +    
   86.37      private static ClassLoader[] ldrs;
   86.38      private static ChangeListener<Void> onBck2BrwsrLoad;
   86.39 +    
   86.40 +    JVMBridge(WebEngine eng) {
   86.41 +        this.engine = eng;
   86.42 +        final ClassLoader p = JVMBridge.class.getClassLoader().getParent();
   86.43 +        this.presenter = new WebPresenter();
   86.44 +        this.cl = FnUtils.newLoader(presenter, presenter, p);
   86.45 +    }
   86.46          
   86.47      public static void registerClassLoaders(ClassLoader[] loaders) {
   86.48          ldrs = loaders.clone();
   86.49 @@ -47,18 +76,189 @@
   86.50      }
   86.51      
   86.52      public Class<?> loadClass(String name) throws ClassNotFoundException {
   86.53 -        System.err.println("trying to load " + name);
   86.54 -        ClassNotFoundException ex = null;
   86.55 -        if (ldrs != null) for (ClassLoader l : ldrs) {
   86.56 -            try {
   86.57 -                return Class.forName(name, true, l);
   86.58 -            } catch (ClassNotFoundException ex2) {
   86.59 -                ex = ex2;
   86.60 +        Fn.activate(presenter);
   86.61 +        return Class.forName(name, true, cl);
   86.62 +    }
   86.63 +    
   86.64 +    private final class WebPresenter 
   86.65 +    implements FindResources, Fn.Presenter, Fn.ToJavaScript, Fn.FromJavaScript, Executor {
   86.66 +        @Override
   86.67 +        public void findResources(String name, Collection<? super URL> results, boolean oneIsEnough) {
   86.68 +            if (ldrs != null) for (ClassLoader l : ldrs) {
   86.69 +                URL u = l.getResource(name);
   86.70 +                if (u != null) {
   86.71 +                    results.add(u);
   86.72 +                }
   86.73              }
   86.74          }
   86.75 -        if (ex == null) {
   86.76 -            ex = new ClassNotFoundException("No loaders");
   86.77 +
   86.78 +        @Override
   86.79 +        public Fn defineFn(String code, String... names) {
   86.80 +            return defineJSFn(code, names);
   86.81          }
   86.82 -        throw ex;
   86.83 +        private JSFn defineJSFn(String code, String... names) {
   86.84 +            StringBuilder sb = new StringBuilder();
   86.85 +            sb.append("(function() {");
   86.86 +            sb.append("  return function(");
   86.87 +            String sep = "";
   86.88 +            for (String n : names) {
   86.89 +                sb.append(sep).append(n);
   86.90 +                sep = ",";
   86.91 +            }
   86.92 +            sb.append(") {\n");
   86.93 +            sb.append(code);
   86.94 +            sb.append("};");
   86.95 +            sb.append("})()");
   86.96 +            
   86.97 +            JSObject x = (JSObject) engine.executeScript(sb.toString());
   86.98 +            return new JSFn(this, x);
   86.99 +        }
  86.100 +
  86.101 +        @Override
  86.102 +        public void displayPage(URL page, Runnable onPageLoad) {
  86.103 +            throw new UnsupportedOperationException("Not supported yet.");
  86.104 +        }
  86.105 +
  86.106 +        @Override
  86.107 +        public void loadScript(Reader code) throws Exception {
  86.108 +            BufferedReader r = new BufferedReader(code);
  86.109 +            StringBuilder sb = new StringBuilder();
  86.110 +            for (;;) {
  86.111 +                String l = r.readLine();
  86.112 +                if (l == null) {
  86.113 +                    break;
  86.114 +                }
  86.115 +                sb.append(l).append('\n');
  86.116 +            }
  86.117 +            engine.executeScript(sb.toString());
  86.118 +        }
  86.119 +
  86.120 +        @Override
  86.121 +        public Object toJava(Object js) {
  86.122 +            return checkArray(js);
  86.123 +        }
  86.124 +
  86.125 +        @Override
  86.126 +        public Object toJavaScript(Object toReturn) {
  86.127 +            if (toReturn instanceof Object[]) {
  86.128 +                return convertArrays((Object[]) toReturn);
  86.129 +            }
  86.130 +            return toReturn;
  86.131 +        }
  86.132 +
  86.133 +        @Override
  86.134 +        public void execute(Runnable command) {
  86.135 +            if (Platform.isFxApplicationThread()) {
  86.136 +                command.run();
  86.137 +            } else {
  86.138 +                Platform.runLater(command);
  86.139 +            }
  86.140 +        }
  86.141 +        
  86.142 +        final JSObject convertArrays(Object[] arr) {
  86.143 +            for (int i = 0; i < arr.length; i++) {
  86.144 +                if (arr[i] instanceof Object[]) {
  86.145 +                    arr[i] = convertArrays((Object[]) arr[i]);
  86.146 +                }
  86.147 +            }
  86.148 +            final JSObject wrapArr = (JSObject) wrapArrFn().call("array", arr); // NOI18N
  86.149 +            return wrapArr;
  86.150 +        }
  86.151 +
  86.152 +        private JSObject wrapArrImpl;
  86.153 +
  86.154 +        private final JSObject wrapArrFn() {
  86.155 +            if (wrapArrImpl == null) {
  86.156 +                try {
  86.157 +                    wrapArrImpl = (JSObject) defineJSFn("  var k = {};"
  86.158 +                        + "  k.array= function() {"
  86.159 +                        + "    return Array.prototype.slice.call(arguments);"
  86.160 +                        + "  };"
  86.161 +                        + "  return k;"
  86.162 +                    ).invokeImpl(null, false);
  86.163 +                } catch (Exception ex) {
  86.164 +                    throw new IllegalStateException(ex);
  86.165 +                }
  86.166 +            }
  86.167 +            return wrapArrImpl;
  86.168 +        }
  86.169 +
  86.170 +        final Object checkArray(Object val) {
  86.171 +            int length = ((Number) arraySizeFn().call("array", val, null)).intValue();
  86.172 +            if (length == -1) {
  86.173 +                return val;
  86.174 +            }
  86.175 +            Object[] arr = new Object[length];
  86.176 +            arraySizeFn().call("array", val, arr);
  86.177 +            return arr;
  86.178 +        }
  86.179 +        private JSObject arraySize;
  86.180 +
  86.181 +        private final JSObject arraySizeFn() {
  86.182 +            if (arraySize == null) {
  86.183 +                try {
  86.184 +                    arraySize = (JSObject) defineJSFn("  var k = {};"
  86.185 +                        + "  k.array = function(arr, to) {"
  86.186 +                        + "    if (to === null) {"
  86.187 +                        + "      if (Object.prototype.toString.call(arr) === '[object Array]') return arr.length;"
  86.188 +                        + "      else return -1;"
  86.189 +                        + "    } else {"
  86.190 +                        + "      var l = arr.length;"
  86.191 +                        + "      for (var i = 0; i < l; i++) to[i] = arr[i];"
  86.192 +                        + "      return l;"
  86.193 +                        + "    }"
  86.194 +                        + "  };"
  86.195 +                        + "  return k;"
  86.196 +                    ).invokeImpl(null, false);
  86.197 +                } catch (Exception ex) {
  86.198 +                    throw new IllegalStateException(ex);
  86.199 +                }
  86.200 +            }
  86.201 +            return arraySize;
  86.202 +        }
  86.203 +        
  86.204 +    }
  86.205 +    
  86.206 +    private static final class JSFn extends Fn {
  86.207 +        private final JSObject fn;
  86.208 +
  86.209 +        private JSFn(WebPresenter cl, JSObject fn) {
  86.210 +            super(cl);
  86.211 +            this.fn = fn;
  86.212 +        }
  86.213 +
  86.214 +        @Override
  86.215 +        public Object invoke(Object thiz, Object... args) throws Exception {
  86.216 +            return invokeImpl(thiz, true, args);
  86.217 +        }
  86.218 +
  86.219 +        final Object invokeImpl(Object thiz, boolean arrayChecks, Object... args) throws Exception {
  86.220 +            try {
  86.221 +                List<Object> all = new ArrayList<Object>(args.length + 1);
  86.222 +                all.add(thiz == null ? fn : thiz);
  86.223 +                for (int i = 0; i < args.length; i++) {
  86.224 +                    if (arrayChecks && args[i] instanceof Object[]) {
  86.225 +                        Object[] arr = (Object[]) args[i];
  86.226 +                        Object conv = ((WebPresenter) presenter()).convertArrays(arr);
  86.227 +                        args[i] = conv;
  86.228 +                    }
  86.229 +                    all.add(args[i]);
  86.230 +                }
  86.231 +                Object ret = fn.call("call", all.toArray()); // NOI18N
  86.232 +                if (ret == fn) {
  86.233 +                    return null;
  86.234 +                }
  86.235 +                if (!arrayChecks) {
  86.236 +                    return ret;
  86.237 +                }
  86.238 +                return ((WebPresenter) presenter()).checkArray(ret);
  86.239 +            } catch (Error t) {
  86.240 +                t.printStackTrace();
  86.241 +                throw t;
  86.242 +            } catch (Exception t) {
  86.243 +                t.printStackTrace();
  86.244 +                throw t;
  86.245 +            }
  86.246 +        }
  86.247      }
  86.248  }
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/OnMessage.java	Wed Apr 30 15:04:10 2014 +0200
    87.3 @@ -0,0 +1,26 @@
    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.fximpl;
   87.22 +
   87.23 +/**
   87.24 + *
   87.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   87.26 + */
   87.27 +interface OnMessage {
   87.28 +    public void onMessage(String msg);
   87.29 +}
    88.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java	Tue Apr 29 15:25:58 2014 +0200
    88.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.3 @@ -1,35 +0,0 @@
    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 -
   88.22 -package org.apidesign.bck2brwsr.launcher.fximpl;
   88.23 -
   88.24 -/**
   88.25 - *
   88.26 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   88.27 - */
   88.28 -public final class Run implements Runnable {
   88.29 -    private final Runnable r;
   88.30 -    Run(Runnable r) {
   88.31 -        this.r = r;
   88.32 -    }
   88.33 -
   88.34 -    @Override
   88.35 -    public void run() {
   88.36 -        r.run();
   88.37 -    }
   88.38 -}
    89.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/desktop.png has changed
    90.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/firebug.png has changed
    91.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldLandscape.png has changed
    92.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldPortrait.png has changed
    93.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/netbook.png has changed
    94.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/selectionMode.png has changed
    95.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/sizeToFit.png has changed
    96.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletLandscape.png has changed
    97.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletPortrait.png has changed
    98.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/widescreen.png has changed
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Wed Apr 30 15:04:10 2014 +0200
    99.3 @@ -0,0 +1,182 @@
    99.4 +/**
    99.5 + * Back 2 Browser Bytecode Translator
    99.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    99.7 + *
    99.8 + * This program is free software: you can redistribute it and/or modify
    99.9 + * it under the terms of the GNU General Public License as published by
   99.10 + * the Free Software Foundation, version 2 of the License.
   99.11 + *
   99.12 + * This program is distributed in the hope that it will be useful,
   99.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   99.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   99.15 + * GNU General Public License for more details.
   99.16 + *
   99.17 + * You should have received a copy of the GNU General Public License
   99.18 + * along with this program. Look for COPYING file in the top folder.
   99.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   99.20 + */
   99.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   99.22 +
   99.23 +import java.io.Reader;
   99.24 +import java.lang.reflect.InvocationTargetException;
   99.25 +import java.lang.reflect.Method;
   99.26 +import java.net.URL;
   99.27 +import java.net.URLClassLoader;
   99.28 +import java.util.ArrayList;
   99.29 +import java.util.Arrays;
   99.30 +import java.util.Collection;
   99.31 +import java.util.List;
   99.32 +import javax.script.Invocable;
   99.33 +import javax.script.ScriptEngine;
   99.34 +import javax.script.ScriptEngineManager;
   99.35 +import javax.script.ScriptException;
   99.36 +import org.apidesign.html.boot.spi.Fn;
   99.37 +import org.netbeans.html.boot.impl.FindResources;
   99.38 +import org.netbeans.html.boot.impl.FnUtils;
   99.39 +import static org.testng.Assert.*;
   99.40 +import org.testng.annotations.BeforeClass;
   99.41 +import org.testng.annotations.BeforeMethod;
   99.42 +import org.testng.annotations.Test;
   99.43 +
   99.44 +/**
   99.45 + *
   99.46 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   99.47 + */
   99.48 +public class JsClassLoaderTest {
   99.49 +    private static ClassLoader loader;
   99.50 +    private static Class<?> methodClass;
   99.51 +    private static Fn.Presenter presenter;
   99.52 +    
   99.53 +    public JsClassLoaderTest() {
   99.54 +    }
   99.55 +
   99.56 +    @BeforeClass
   99.57 +    public static void setUpClass() throws Exception {
   99.58 +        ScriptEngineManager sem = new ScriptEngineManager();
   99.59 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
   99.60 +        
   99.61 +        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
   99.62 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
   99.63 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
   99.64 +        class Fr implements FindResources, Fn.Presenter {
   99.65 +            @Override
   99.66 +            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
   99.67 +                URL u = ul.getResource(path);
   99.68 +                if (u != null) {
   99.69 +                    results.add(u);
   99.70 +                }
   99.71 +            }
   99.72 +
   99.73 +            @Override
   99.74 +            public Fn defineFn(String code, String... names) {
   99.75 +                StringBuilder sb = new StringBuilder();
   99.76 +                sb.append("(function() {");
   99.77 +                sb.append("return function(");
   99.78 +                String sep = "";
   99.79 +                for (String n : names) {
   99.80 +                    sb.append(sep);
   99.81 +                    sb.append(n);
   99.82 +                    sep = ", ";
   99.83 +                }
   99.84 +                sb.append(") {");
   99.85 +                sb.append(code);
   99.86 +                sb.append("};");
   99.87 +                sb.append("})()");
   99.88 +                try {
   99.89 +                    final Object val = eng.eval(sb.toString());
   99.90 +                    return new Fn(this) {
   99.91 +                        @Override
   99.92 +                        public Object invoke(Object thiz, Object... args) throws Exception {
   99.93 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
   99.94 +                            all.add(thiz == null ? val : thiz);
   99.95 +                            all.addAll(Arrays.asList(args));
   99.96 +                            Invocable inv = (Invocable)eng;
   99.97 +                            Object ret = inv.invokeMethod(val, "call", all.toArray());
   99.98 +                            return val.equals(ret) ? null : ret;
   99.99 +                        }
  99.100 +                    };
  99.101 +                } catch (ScriptException ex) {
  99.102 +                    throw new LinkageError("Can't parse: " + sb, ex);
  99.103 +                }
  99.104 +            }
  99.105 +
  99.106 +            @Override
  99.107 +            public void displayPage(URL page, Runnable onPageLoad) {
  99.108 +                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  99.109 +            }
  99.110 +
  99.111 +            @Override
  99.112 +            public void loadScript(Reader code) throws Exception {
  99.113 +                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
  99.114 +            }
  99.115 +        }
  99.116 +        
  99.117 +        Fr fr = new Fr();
  99.118 +        presenter = fr;
  99.119 +        loader = FnUtils.newLoader(fr, fr, parent);
  99.120 +        methodClass = loader.loadClass(JsMethods.class.getName());
  99.121 +    }
  99.122 +    
  99.123 +    @BeforeMethod public void registerPresenter() {
  99.124 +        Fn.activate(presenter);
  99.125 +    }
  99.126 +    
  99.127 +    @Test public void noParamMethod() throws Throwable {
  99.128 +        Method plus = methodClass.getMethod("fortyTwo");
  99.129 +        try {
  99.130 +            final Object val = plus.invoke(null);
  99.131 +            assertTrue(val instanceof Number, "A number returned " + val);
  99.132 +            assertEquals(((Number)val).intValue(), 42);
  99.133 +        } catch (InvocationTargetException ex) {
  99.134 +            throw ex.getTargetException();
  99.135 +        }
  99.136 +    }
  99.137 +    
  99.138 +    @Test public void testExecuteScript() throws Throwable {
  99.139 +        Method plus = methodClass.getMethod("plus", int.class, int.class);
  99.140 +        try {
  99.141 +            assertEquals(plus.invoke(null, 10, 20), 30);
  99.142 +        } catch (InvocationTargetException ex) {
  99.143 +            throw ex.getTargetException();
  99.144 +        }
  99.145 +    }
  99.146 +
  99.147 +    @Test public void overloadedMethod() throws Throwable {
  99.148 +        Method plus = methodClass.getMethod("plus", int.class);
  99.149 +        try {
  99.150 +            assertEquals(plus.invoke(null, 10), 10);
  99.151 +        } catch (InvocationTargetException ex) {
  99.152 +            throw ex.getTargetException();
  99.153 +        }
  99.154 +    }
  99.155 +    
  99.156 +    @Test public void instanceMethod() throws Throwable {
  99.157 +        Method plus = methodClass.getMethod("plusInst", int.class);
  99.158 +        Object inst = methodClass.newInstance();
  99.159 +        try {
  99.160 +            assertEquals(plus.invoke(inst, 10), 10);
  99.161 +        } catch (InvocationTargetException ex) {
  99.162 +            throw ex.getTargetException();
  99.163 +        }
  99.164 +    }
  99.165 +    
  99.166 +    @Test public void staticThis() throws Throwable {
  99.167 +        Method st = methodClass.getMethod("staticThis");
  99.168 +        try {
  99.169 +            assertNull(st.invoke(null));
  99.170 +        } catch (InvocationTargetException ex) {
  99.171 +            throw ex.getTargetException();
  99.172 +        }
  99.173 +    }
  99.174 +
  99.175 +    @Test public void getThis() throws Throwable {
  99.176 +        Object th = methodClass.newInstance();
  99.177 +        Method st = methodClass.getMethod("getThis");
  99.178 +        try {
  99.179 +            assertEquals(st.invoke(th), th);
  99.180 +        } catch (InvocationTargetException ex) {
  99.181 +            throw ex.getTargetException();
  99.182 +        }
  99.183 +    }
  99.184 +    
  99.185 +}
  99.186 \ No newline at end of file
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java	Wed Apr 30 15:04:10 2014 +0200
   100.3 @@ -0,0 +1,45 @@
   100.4 +/**
   100.5 + * Back 2 Browser Bytecode Translator
   100.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   100.7 + *
   100.8 + * This program is free software: you can redistribute it and/or modify
   100.9 + * it under the terms of the GNU General Public License as published by
  100.10 + * the Free Software Foundation, version 2 of the License.
  100.11 + *
  100.12 + * This program is distributed in the hope that it will be useful,
  100.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  100.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  100.15 + * GNU General Public License for more details.
  100.16 + *
  100.17 + * You should have received a copy of the GNU General Public License
  100.18 + * along with this program. Look for COPYING file in the top folder.
  100.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  100.20 + */
  100.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
  100.22 +
  100.23 +import net.java.html.js.JavaScriptBody;
  100.24 +
  100.25 +/**
  100.26 + *
  100.27 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  100.28 + */
  100.29 +public class JsMethods {
  100.30 +    @JavaScriptBody(args = {}, body = "return 42;")
  100.31 +    public static Object fortyTwo() {
  100.32 +        return -42;
  100.33 +    }
  100.34 +    
  100.35 +    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
  100.36 +    public static native int plus(int x, int y);
  100.37 +    
  100.38 +    @JavaScriptBody(args = {"x"}, body = "return x;")
  100.39 +    public static native int plus(int x);
  100.40 +    
  100.41 +    @JavaScriptBody(args = {}, body = "return this;")
  100.42 +    public static native Object staticThis();
  100.43 +    
  100.44 +    @JavaScriptBody(args = {}, body = "return this;")
  100.45 +    public native Object getThis();
  100.46 +    @JavaScriptBody(args = {"x"}, body = "return x;")
  100.47 +    public native int plusInst(int x);
  100.48 +}
   101.1 --- a/launcher/http/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   101.2 +++ b/launcher/http/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   101.3 @@ -4,11 +4,11 @@
   101.4    <parent>
   101.5      <groupId>org.apidesign.bck2brwsr</groupId>
   101.6      <artifactId>launcher-pom</artifactId>
   101.7 -    <version>0.8-SNAPSHOT</version>
   101.8 +    <version>0.9-SNAPSHOT</version>
   101.9    </parent>
  101.10    <groupId>org.apidesign.bck2brwsr</groupId>
  101.11    <artifactId>launcher.http</artifactId>
  101.12 -  <version>0.8-SNAPSHOT</version>
  101.13 +  <version>0.9-SNAPSHOT</version>
  101.14    <name>Bck2Brwsr Launcher</name>
  101.15    <url>http://maven.apache.org</url>
  101.16      <build>
   102.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Tue Apr 29 15:25:58 2014 +0200
   102.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Wed Apr 30 15:04:10 2014 +0200
   102.3 @@ -17,9 +17,17 @@
   102.4   */
   102.5  package org.apidesign.bck2brwsr.launcher;
   102.6  
   102.7 +import java.io.File;
   102.8 +import java.io.FileReader;
   102.9  import java.io.IOException;
  102.10 +import java.io.InputStream;
  102.11 +import java.io.InputStreamReader;
  102.12 +import java.io.Reader;
  102.13 +import java.net.MalformedURLException;
  102.14  import java.net.URL;
  102.15  import java.util.jar.JarFile;
  102.16 +import java.util.logging.Level;
  102.17 +import org.apidesign.vm4brwsr.Bck2Brwsr;
  102.18  
  102.19  /**
  102.20   * Lightweight server to launch Bck2Brwsr applications and tests.
  102.21 @@ -48,15 +56,54 @@
  102.22      
  102.23      @Override
  102.24      void generateBck2BrwsrJS(StringBuilder sb, final Res loader) throws IOException {
  102.25 -        CompileCP.compileVM(sb, loader);
  102.26 +        String b2b = System.getProperty("bck2brwsr.js");
  102.27 +        if (b2b != null) {
  102.28 +            LOG.log(Level.INFO, "Serving bck2brwsr.js from {0}", b2b);
  102.29 +            URL bu;
  102.30 +            try {
  102.31 +                bu = new URL(b2b);
  102.32 +            } catch (MalformedURLException ex) {
  102.33 +                File f = new File(b2b);
  102.34 +                if (f.exists()) {
  102.35 +                    bu = f.toURI().toURL();
  102.36 +                } else {
  102.37 +                    throw ex;
  102.38 +                }
  102.39 +            }
  102.40 +            try (Reader r = new InputStreamReader(bu.openStream())) {
  102.41 +                char[] arr = new char[4096];
  102.42 +                for (;;) {
  102.43 +                   int len = r.read(arr);
  102.44 +                   if (len == -1) {
  102.45 +                       break;
  102.46 +                   }
  102.47 +                   sb.append(arr, 0, len);
  102.48 +                }
  102.49 +            }
  102.50 +        } else {
  102.51 +            LOG.log(Level.INFO, "Generating bck2brwsr.js from scratch", b2b);
  102.52 +            CompileCP.compileVM(sb, loader);
  102.53 +        }
  102.54          sb.append(
  102.55 -              "(function WrapperVM(global) {"
  102.56 -            + "  function ldCls(res) {\n"
  102.57 +              "(function WrapperVM(global) {\n"
  102.58 +            + "  var cache = {};\n"
  102.59 +            + "  function ldCls(res, skip) {\n"
  102.60 +            + "    var c = cache[res];\n"
  102.61 +            + "    if (c) {\n"
  102.62 +            + "      if (c[skip]) return c[skip];\n"
  102.63 +            + "      if (c[skip] === null) return null;\n"
  102.64 +            + "    } else {\n"
  102.65 +            + "      cache[res] = c = new Array();\n"
  102.66 +            + "    }\n"
  102.67              + "    var request = new XMLHttpRequest();\n"
  102.68 -            + "    request.open('GET', '/classes/' + res, false);\n"
  102.69 +            + "    request.open('GET', '/classes/' + res + '?skip=' + skip, false);\n"
  102.70              + "    request.send();\n"
  102.71 -            + "    if (request.status !== 200) return null;\n"
  102.72 +            + "    if (request.status !== 200) {\n"
  102.73 +            + "      c[skip] = null;\n"
  102.74 +            + "      return null;\n"
  102.75 +            + "    }\n"
  102.76              + "    var arr = eval(request.responseText);\n"
  102.77 +            + "    c[skip] = arr;\n"
  102.78              + "    return arr;\n"
  102.79              + "  }\n"
  102.80              + "  var prevvm = global.bck2brwsr;\n"
  102.81 @@ -68,6 +115,7 @@
  102.82              + "  global.bck2brwsr.registerExtension = prevvm.registerExtension;\n"
  102.83              + "})(this);\n"
  102.84          );
  102.85 +        LOG.log(Level.INFO, "Serving bck2brwsr.js", b2b);
  102.86      }
  102.87  
  102.88  }
   103.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java	Tue Apr 29 15:25:58 2014 +0200
   103.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/CompileCP.java	Wed Apr 30 15:04:10 2014 +0200
   103.3 @@ -93,7 +93,7 @@
   103.4                      .resources(new EmulationResources() {
   103.5                          @Override
   103.6                          public InputStream get(String resource) throws IOException {
   103.7 -                            return r != null ? r.get(resource).openStream() : super.get(resource);
   103.8 +                            return r != null ? r.get(resource, 0).openStream() : super.get(resource);
   103.9                          }
  103.10                      })
  103.11                      .generate(w);
  103.12 @@ -156,7 +156,7 @@
  103.13      }
  103.14  
  103.15      static void compileVM(StringBuilder sb, final Res r) throws IOException {
  103.16 -        URL u = r.get(InterruptedException.class.getName().replace('.', '/') + ".class");
  103.17 +        URL u = r.get(InterruptedException.class.getName().replace('.', '/') + ".class", 0);
  103.18          JarURLConnection juc = (JarURLConnection)u.openConnection();
  103.19          
  103.20          List<String> arr = new ArrayList<>();
  103.21 @@ -167,7 +167,7 @@
  103.22              .resources(new Bck2Brwsr.Resources() {
  103.23                  @Override
  103.24                  public InputStream get(String resource) throws IOException {
  103.25 -                    return r.get(resource).openStream();
  103.26 +                    return r.get(resource, 0).openStream();
  103.27                  }
  103.28              }).generate(sb);
  103.29      }
   104.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Tue Apr 29 15:25:58 2014 +0200
   104.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Wed Apr 30 15:04:10 2014 +0200
   104.3 @@ -126,6 +126,10 @@
   104.4                      u = en.nextElement();
   104.5                  }
   104.6                  if (u != null) {
   104.7 +                    if (u.toExternalForm().contains("rt.jar")) {
   104.8 +                        LOG.log(Level.WARNING, "No fallback to bootclasspath for {0}", u);
   104.9 +                        return null;
  104.10 +                    }
  104.11                      return u.openStream();
  104.12                  }
  104.13              }
   105.1 --- a/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Tue Apr 29 15:25:58 2014 +0200
   105.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Wed Apr 30 15:04:10 2014 +0200
   105.3 @@ -221,14 +221,22 @@
   105.4       * @return the array of bytes in the given resource
   105.5       * @throws IOException I/O in case something goes wrong
   105.6       */
   105.7 -    public static byte[] read(String name) throws IOException {
   105.8 +    public static byte[] read(String name, int skip) throws IOException {
   105.9          URL u = null;
  105.10 -        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  105.11 -        while (en.hasMoreElements()) {
  105.12 -            u = en.nextElement();
  105.13 +        if (!name.endsWith(".class")) {
  105.14 +            u = getResource(name, skip);
  105.15 +        } else {
  105.16 +            Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  105.17 +            while (en.hasMoreElements()) {
  105.18 +                u = en.nextElement();
  105.19 +            }
  105.20          }
  105.21          if (u == null) {
  105.22 -            throw new IOException("Can't find " + name);
  105.23 +            if (name.endsWith(".class")) {
  105.24 +                throw new IOException("Can't find " + name);
  105.25 +            } else {
  105.26 +                return null;
  105.27 +            }
  105.28          }
  105.29          try (InputStream is = u.openStream()) {
  105.30              byte[] arr;
  105.31 @@ -245,6 +253,19 @@
  105.32          }
  105.33      }
  105.34     
  105.35 +    private static URL getResource(String resource, int skip) throws IOException {
  105.36 +        URL u = null;
  105.37 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(resource);
  105.38 +        while (en.hasMoreElements()) {
  105.39 +            final URL now = en.nextElement();
  105.40 +            if (--skip < 0) {
  105.41 +                u = now;
  105.42 +                break;
  105.43 +            }
  105.44 +        }
  105.45 +        return u;
  105.46 +    }
  105.47 +    
  105.48      @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
  105.49      private static void turnAssetionStatusOn() {
  105.50      }
   106.1 --- a/launcher/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   106.2 +++ b/launcher/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   106.3 @@ -4,15 +4,15 @@
   106.4    <parent>
   106.5      <artifactId>bck2brwsr</artifactId>
   106.6      <groupId>org.apidesign</groupId>
   106.7 -    <version>0.8-SNAPSHOT</version>
   106.8 +    <version>0.9-SNAPSHOT</version>
   106.9    </parent>
  106.10    <groupId>org.apidesign.bck2brwsr</groupId>
  106.11    <artifactId>launcher-pom</artifactId>
  106.12 -  <version>0.8-SNAPSHOT</version>
  106.13 +  <version>0.9-SNAPSHOT</version>
  106.14    <packaging>pom</packaging>
  106.15    <name>Launchers</name>
  106.16    <properties>
  106.17 -      <grizzly.version>2.3.2</grizzly.version>
  106.18 +      <grizzly.version>2.3.3</grizzly.version>
  106.19    </properties>
  106.20    <modules>
  106.21      <module>api</module>
   107.1 --- a/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   107.2 +++ b/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   107.3 @@ -3,7 +3,7 @@
   107.4    <modelVersion>4.0.0</modelVersion>
   107.5    <groupId>org.apidesign</groupId>
   107.6    <artifactId>bck2brwsr</artifactId>
   107.7 -  <version>0.8-SNAPSHOT</version>
   107.8 +  <version>0.9-SNAPSHOT</version>
   107.9    <packaging>pom</packaging>
  107.10    <name>Back 2 Browser</name>
  107.11    <parent>
  107.12 @@ -15,13 +15,13 @@
  107.13        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  107.14        <netbeans.version>RELEASE80</netbeans.version>
  107.15        <license>COPYING</license>
  107.16 +      <net.java.html.version>0.7.6</net.java.html.version>
  107.17        <netbeans.compile.on.save>none</netbeans.compile.on.save>
  107.18    </properties>
  107.19    <modules>
  107.20 -    <module>dew</module>
  107.21      <module>javaquery</module>
  107.22      <module>benchmarks</module>
  107.23 -    <module>ide</module>
  107.24 +    <module>ko</module>
  107.25      <module>launcher</module>
  107.26      <module>rt</module>
  107.27    </modules>
  107.28 @@ -85,12 +85,13 @@
  107.29                    <excludes>
  107.30                         <exclude>*</exclude>
  107.31                         <exclude>.*/**</exclude>
  107.32 -                       <exclude>rt/emul/*/src/main/**</exclude>
  107.33 +                       <exclude>rt/emul/mini/src/main/**</exclude>
  107.34 +                       <exclude>rt/emul/compact/src/main/**</exclude>
  107.35                         <exclude>rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java</exclude>
  107.36                         <exclude>rt/archetype/src/main/resources/archetype-resources/**</exclude>
  107.37                         <exclude>rt/emul/*/src/test/resources/**</exclude>
  107.38 -                       <exclude>dew/src/main/resources/org/apidesign/bck2brwsr/dew/**</exclude>
  107.39                         <exclude>javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js</exclude>
  107.40 +                       <exclude>ko/archetype/src/main/resources/archetype-resources/**</exclude>
  107.41                    </excludes>
  107.42                </configuration>
  107.43            </plugin>
   108.1 --- a/rt/archetype/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   108.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   108.3 @@ -1,87 +0,0 @@
   108.4 -<?xml version="1.0" encoding="UTF-8"?>
   108.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">
   108.6 -  <modelVersion>4.0.0</modelVersion>
   108.7 -  <parent>
   108.8 -    <artifactId>rt</artifactId>
   108.9 -    <groupId>org.apidesign.bck2brwsr</groupId>
  108.10 -    <version>0.8-SNAPSHOT</version>
  108.11 -  </parent>
  108.12 -  <groupId>org.apidesign.bck2brwsr</groupId>
  108.13 -  <artifactId>bck2brwsr-archetype-html-sample</artifactId>
  108.14 -  <version>0.8-SNAPSHOT</version>
  108.15 -  <packaging>jar</packaging>
  108.16 -  <name>Bck2Brwsr Maven Archetype</name>
  108.17 -  <description>
  108.18 -      Creates a skeletal HTML page and associated Java controller class.
  108.19 -      Runs in any browser (even without Java plugin) with the help of Bck2Brwsr
  108.20 -      virtual machine.
  108.21 -  </description>
  108.22 -  <build>
  108.23 -      <resources>
  108.24 -          <resource>
  108.25 -            <directory>src/main/resources</directory>
  108.26 -            <filtering>true</filtering>
  108.27 -            <includes>
  108.28 -                <include>**/pom.xml</include>
  108.29 -            </includes>
  108.30 -          </resource>
  108.31 -          <resource>
  108.32 -            <directory>src/main/resources</directory>
  108.33 -            <filtering>false</filtering>
  108.34 -            <excludes>
  108.35 -                <exclude>**/pom.xml</exclude>
  108.36 -            </excludes>
  108.37 -          </resource>
  108.38 -      </resources>      
  108.39 -      <plugins>
  108.40 -          <plugin>
  108.41 -              <groupId>org.apache.maven.plugins</groupId>
  108.42 -              <artifactId>maven-compiler-plugin</artifactId>
  108.43 -              <version>2.3.2</version>
  108.44 -              <configuration>
  108.45 -                  <source>1.6</source>
  108.46 -                  <target>1.6</target>
  108.47 -              </configuration>
  108.48 -          </plugin>
  108.49 -          <plugin>
  108.50 -              <groupId>org.apache.maven.plugins</groupId>
  108.51 -              <artifactId>maven-resources-plugin</artifactId>
  108.52 -              <version>2.6</version>
  108.53 -              <configuration>
  108.54 -                  <escapeString>\</escapeString>
  108.55 -                  <target>1.6</target>
  108.56 -              </configuration>
  108.57 -          </plugin>
  108.58 -          <plugin>
  108.59 -              <groupId>org.apache.maven.plugins</groupId>
  108.60 -              <artifactId>maven-surefire-plugin</artifactId>
  108.61 -              <configuration>
  108.62 -                  <skipTests>true</skipTests>
  108.63 -              </configuration>
  108.64 -              <executions>
  108.65 -                  <execution>
  108.66 -                      <id>test</id>
  108.67 -                      <goals>
  108.68 -                          <goal>test</goal>
  108.69 -                      </goals>
  108.70 -                      <phase>integration-test</phase>
  108.71 -                      <configuration>
  108.72 -                          <additionalClasspathElements>
  108.73 -                              <additionalClasspathElement>${project.build.directory}/bck2brwsr-archetype-html-sample-${project.version}.jar</additionalClasspathElement>
  108.74 -                          </additionalClasspathElements>
  108.75 -                          <skipTests>false</skipTests>
  108.76 -                      </configuration>
  108.77 -                  </execution>
  108.78 -                  
  108.79 -              </executions>
  108.80 -          </plugin>
  108.81 -      </plugins>
  108.82 -  </build>
  108.83 -  <dependencies>
  108.84 -      <dependency>
  108.85 -          <groupId>org.testng</groupId>
  108.86 -          <artifactId>testng</artifactId>
  108.87 -          <scope>test</scope>
  108.88 -      </dependency>
  108.89 -  </dependencies>
  108.90 -</project>
   109.1 --- a/rt/archetype/src/main/java/org/apidesign/bck2brwsr/archetype/package-info.java	Tue Apr 29 15:25:58 2014 +0200
   109.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   109.3 @@ -1,18 +0,0 @@
   109.4 -/**
   109.5 - * Back 2 Browser Bytecode Translator
   109.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   109.7 - *
   109.8 - * This program is free software: you can redistribute it and/or modify
   109.9 - * it under the terms of the GNU General Public License as published by
  109.10 - * the Free Software Foundation, version 2 of the License.
  109.11 - *
  109.12 - * This program is distributed in the hope that it will be useful,
  109.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  109.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  109.15 - * GNU General Public License for more details.
  109.16 - *
  109.17 - * You should have received a copy of the GNU General Public License
  109.18 - * along with this program. Look for COPYING file in the top folder.
  109.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  109.20 - */
  109.21 -package org.apidesign.bck2brwsr.archetype;
   110.1 --- a/rt/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml	Tue Apr 29 15:25:58 2014 +0200
   110.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3 @@ -1,55 +0,0 @@
   110.4 -<?xml version="1.0" encoding="UTF-8"?>
   110.5 -<!--
   110.6 -
   110.7 -    Back 2 Browser Bytecode Translator
   110.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   110.9 -
  110.10 -    This program is free software: you can redistribute it and/or modify
  110.11 -    it under the terms of the GNU General Public License as published by
  110.12 -    the Free Software Foundation, version 2 of the License.
  110.13 -
  110.14 -    This program is distributed in the hope that it will be useful,
  110.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  110.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  110.17 -    GNU General Public License for more details.
  110.18 -
  110.19 -    You should have received a copy of the GNU General Public License
  110.20 -    along with this program. Look for COPYING file in the top folder.
  110.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
  110.22 -
  110.23 --->
  110.24 -<archetype-descriptor name="Get Java Bck2Brwsr!">
  110.25 -  <fileSets>
  110.26 -    <fileSet filtered="true" packaged="true">
  110.27 -      <directory>src/main/java</directory>
  110.28 -      <includes>
  110.29 -        <include>**/App.java</include>
  110.30 -      </includes>
  110.31 -    </fileSet>
  110.32 -    <fileSet filtered="true" packaged="true">
  110.33 -      <directory>src/main/resources</directory>
  110.34 -      <includes>
  110.35 -        <include>**/*.xhtml</include>
  110.36 -        <include>**/*.html</include>
  110.37 -      </includes>
  110.38 -    </fileSet>
  110.39 -    <fileSet filtered="true" packaged="true">
  110.40 -      <directory>src/test/java</directory>
  110.41 -      <includes>
  110.42 -        <include>**/*Test.java</include>
  110.43 -      </includes>
  110.44 -    </fileSet>
  110.45 -    <fileSet filtered="false" packaged="false">
  110.46 -      <directory></directory>
  110.47 -      <includes>
  110.48 -        <include>nbactions.xml</include>
  110.49 -      </includes>
  110.50 -    </fileSet>
  110.51 -    <fileSet filtered="true" packaged="false">
  110.52 -      <directory></directory>
  110.53 -      <includes>
  110.54 -        <include>bck2brwsr-assembly.xml</include>
  110.55 -      </includes>
  110.56 -    </fileSet>
  110.57 -  </fileSets>    
  110.58 -</archetype-descriptor>
  110.59 \ No newline at end of file
   111.1 --- a/rt/archetype/src/main/resources/archetype-resources/bck2brwsr-assembly.xml	Tue Apr 29 15:25:58 2014 +0200
   111.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.3 @@ -1,61 +0,0 @@
   111.4 -<?xml version="1.0"?>
   111.5 -<!--
   111.6 -
   111.7 -    Back 2 Browser Bytecode Translator
   111.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   111.9 -
  111.10 -    This program is free software: you can redistribute it and/or modify
  111.11 -    it under the terms of the GNU General Public License as published by
  111.12 -    the Free Software Foundation, version 2 of the License.
  111.13 -
  111.14 -    This program is distributed in the hope that it will be useful,
  111.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  111.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  111.17 -    GNU General Public License for more details.
  111.18 -
  111.19 -    You should have received a copy of the GNU General Public License
  111.20 -    along with this program. Look for COPYING file in the top folder.
  111.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
  111.22 -
  111.23 --->
  111.24 -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  111.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">
  111.26 -  
  111.27 -  <id>bck2brwsr</id>
  111.28 -  <formats>
  111.29 -      <format>zip</format>
  111.30 -  </formats>
  111.31 -  <baseDirectory>public_html</baseDirectory>
  111.32 -  <dependencySets>
  111.33 -    <dependencySet>
  111.34 -        <useProjectArtifact>false</useProjectArtifact>
  111.35 -        <scope>runtime</scope>
  111.36 -        <outputDirectory>lib</outputDirectory>
  111.37 -        <includes>
  111.38 -            <include>*:jar</include>
  111.39 -            <include>*:rt</include>
  111.40 -        </includes>
  111.41 -    </dependencySet>
  111.42 -    <dependencySet>
  111.43 -        <useProjectArtifact>false</useProjectArtifact>
  111.44 -        <scope>provided</scope>
  111.45 -        <includes>
  111.46 -            <include>*:js</include>
  111.47 -        </includes>
  111.48 -        <unpack>true</unpack>
  111.49 -        <outputDirectory>/</outputDirectory>
  111.50 -    </dependencySet>
  111.51 -  </dependencySets> 
  111.52 -  <files>
  111.53 -    <file>
  111.54 -      <source>${project.build.directory}/${project.build.finalName}.jar</source>
  111.55 -      <outputDirectory>/</outputDirectory>
  111.56 -    </file>
  111.57 -    <file>
  111.58 -      <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
  111.59 -      <outputDirectory>/</outputDirectory>
  111.60 -      <destName>index.html</destName>
  111.61 -    </file>
  111.62 -  </files>
  111.63 -
  111.64 -</assembly>
  111.65 \ No newline at end of file
   112.1 --- a/rt/archetype/src/main/resources/archetype-resources/nbactions.xml	Tue Apr 29 15:25:58 2014 +0200
   112.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.3 @@ -1,10 +0,0 @@
   112.4 -<?xml version="1.0" encoding="UTF-8"?>
   112.5 -<actions>
   112.6 -    <action>
   112.7 -        <actionName>run</actionName>
   112.8 -        <goals>
   112.9 -            <goal>process-classes</goal>
  112.10 -            <goal>bck2brwsr:brwsr</goal>
  112.11 -        </goals>
  112.12 -    </action>
  112.13 -</actions>
   113.1 --- a/rt/archetype/src/main/resources/archetype-resources/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   113.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.3 @@ -1,135 +0,0 @@
   113.4 -<?xml version="1.0"?>
   113.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   113.6 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   113.7 -  <modelVersion>4.0.0</modelVersion>
   113.8 -
   113.9 -  <groupId>\${groupId}</groupId>
  113.10 -  <artifactId>\${artifactId}</artifactId>
  113.11 -  <version>\${version}</version>
  113.12 -  <packaging>jar</packaging>
  113.13 -
  113.14 -  <name>\${artifactId}</name>
  113.15 -
  113.16 -  <repositories>
  113.17 -      <repository>
  113.18 -          <id>java.net</id>
  113.19 -          <name>Java.net</name>
  113.20 -          <url>https://maven.java.net/content/repositories/releases/</url>
  113.21 -          <snapshots>
  113.22 -              <enabled>true</enabled>
  113.23 -          </snapshots>
  113.24 -      </repository>
  113.25 -      <repository>
  113.26 -          <id>netbeans</id>
  113.27 -          <name>NetBeans</name>
  113.28 -          <url>http://bits.netbeans.org/maven2/</url>
  113.29 -      </repository>
  113.30 -  </repositories>
  113.31 -  <pluginRepositories>
  113.32 -      <pluginRepository>
  113.33 -          <id>java.net</id>
  113.34 -          <name>Java.net</name>
  113.35 -          <url>https://maven.java.net/content/repositories/releases/</url>
  113.36 -          <snapshots>
  113.37 -              <enabled>true</enabled>
  113.38 -          </snapshots>
  113.39 -      </pluginRepository>
  113.40 -  </pluginRepositories>
  113.41 -
  113.42 -  <properties>
  113.43 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  113.44 -  </properties>
  113.45 -  <build>
  113.46 -      <plugins>
  113.47 -            <plugin>
  113.48 -                <groupId>org.apidesign.bck2brwsr</groupId>
  113.49 -                <artifactId>bck2brwsr-maven-plugin</artifactId>
  113.50 -                <version>${project.version}</version>
  113.51 -                <executions>
  113.52 -                    <execution>
  113.53 -                        <goals>
  113.54 -                            <goal>brwsr</goal>
  113.55 -                        </goals>
  113.56 -                    </execution>
  113.57 -                </executions>
  113.58 -                <configuration>
  113.59 -                    <startpage>\${package.replace('.','/')}/index.html</startpage>
  113.60 -                </configuration>
  113.61 -            </plugin>
  113.62 -         <plugin>
  113.63 -            <groupId>org.apache.maven.plugins</groupId>
  113.64 -            <artifactId>maven-compiler-plugin</artifactId>
  113.65 -            <version>2.3.2</version>
  113.66 -            <configuration>
  113.67 -               <source>1.7</source>
  113.68 -               <target>1.7</target>
  113.69 -            </configuration>
  113.70 -         </plugin>
  113.71 -         <plugin>
  113.72 -             <groupId>org.apache.maven.plugins</groupId>
  113.73 -             <artifactId>maven-jar-plugin</artifactId>
  113.74 -             <version>2.4</version>
  113.75 -             <configuration>
  113.76 -                 <archive>
  113.77 -                     <manifest>
  113.78 -                         <addClasspath>true</addClasspath>
  113.79 -                         <classpathPrefix>lib/</classpathPrefix>
  113.80 -                     </manifest>
  113.81 -                 </archive>
  113.82 -             </configuration>
  113.83 -         </plugin>
  113.84 -         <plugin>
  113.85 -             <artifactId>maven-assembly-plugin</artifactId>
  113.86 -             <version>2.4</version>
  113.87 -             <executions>
  113.88 -                 <execution>
  113.89 -                     <id>distro-assembly</id>
  113.90 -                     <phase>package</phase>
  113.91 -                     <goals>
  113.92 -                         <goal>single</goal>
  113.93 -                     </goals>
  113.94 -                     <configuration>
  113.95 -                         <descriptors>
  113.96 -                             <descriptor>bck2brwsr-assembly.xml</descriptor>
  113.97 -                         </descriptors>
  113.98 -                     </configuration>
  113.99 -                 </execution>
 113.100 -             </executions>                
 113.101 -         </plugin>      
 113.102 -      </plugins>
 113.103 -  </build>
 113.104 -
 113.105 -  <dependencies>
 113.106 -    <dependency>
 113.107 -      <groupId>org.apidesign.bck2brwsr</groupId>
 113.108 -      <artifactId>emul</artifactId>
 113.109 -      <version>${project.version}</version>
 113.110 -      <classifier>rt</classifier>
 113.111 -    </dependency>
 113.112 -    <dependency>
 113.113 -      <groupId>org.apidesign.bck2brwsr</groupId>
 113.114 -      <artifactId>javaquery.api</artifactId>
 113.115 -      <version>${project.version}</version>
 113.116 -    </dependency>
 113.117 -    <dependency>
 113.118 -      <groupId>org.testng</groupId>
 113.119 -      <artifactId>testng</artifactId>
 113.120 -      <version>6.5.2</version>
 113.121 -      <scope>test</scope>
 113.122 -    </dependency>
 113.123 -    <dependency>
 113.124 -      <groupId>org.apidesign.bck2brwsr</groupId>
 113.125 -      <artifactId>vm4brwsr</artifactId>
 113.126 -      <classifier>js</classifier>
 113.127 -      <type>zip</type>
 113.128 -      <version>${project.version}</version>
 113.129 -      <scope>provided</scope>
 113.130 -    </dependency>
 113.131 -    <dependency>
 113.132 -      <groupId>org.apidesign.bck2brwsr</groupId>
 113.133 -      <artifactId>vmtest</artifactId>
 113.134 -      <version>${project.version}</version>
 113.135 -      <scope>test</scope>
 113.136 -    </dependency>
 113.137 -  </dependencies>
 113.138 -</project>
   114.1 --- a/rt/archetype/src/main/resources/archetype-resources/src/main/java/App.java	Tue Apr 29 15:25:58 2014 +0200
   114.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.3 @@ -1,88 +0,0 @@
   114.4 -package ${package};
   114.5 -
   114.6 -import java.util.List;
   114.7 -import org.apidesign.bck2brwsr.htmlpage.api.*;
   114.8 -import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   114.9 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
  114.10 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
  114.11 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
  114.12 -
  114.13 -/** This is the controller class for associated index.html page. The <code>Index</code>
  114.14 - * is autogenerated by parsing the index.html page. It fields represent individual
  114.15 - * elements annotated by "id" in the page.
  114.16 - */
  114.17 -@Page(xhtml="index.html", className="Index", properties={
  114.18 -    @Property(name="name", type=String.class),
  114.19 -    @Property(name="messages", type=String.class, array=true),
  114.20 -})
  114.21 -public class App {
  114.22 -    static {
  114.23 -        Index model = new Index();
  114.24 -        model.setName("World");
  114.25 -        model.applyBindings();
  114.26 -    }
  114.27 -    
  114.28 -    /** 
  114.29 -     * @param m the model of the index page creates in static initializer
  114.30 -     */
  114.31 -    @On(event = CLICK, id="hello")
  114.32 -    static void hello(Index m) {
  114.33 -        display(m.getHelloMessage(), m);
  114.34 -        m.getMessages().add(m.getHelloMessage());
  114.35 -    }
  114.36 -
  114.37 -    /** Reacts when mouse moves over the canvas.
  114.38 -     * 
  114.39 -     * @param m the model of the page
  114.40 -     * @param x property "x" extracted from the event generated by the browser
  114.41 -     * @param y property "y" from the mouse event
  114.42 -     */
  114.43 -    @On(event = MOUSE_MOVE, id="canvas")
  114.44 -    static void clearPoint(Index m, int x, int y) {
  114.45 -        GraphicsContext g = m.canvas.getContext();
  114.46 -        boolean even = (x + y) % 2 == 0;
  114.47 -        if (even) {
  114.48 -            g.setFillStyle("blue");
  114.49 -        } else {
  114.50 -            g.setFillStyle("red");
  114.51 -        }
  114.52 -        g.clearRect(0, 0, 1000, 1000);
  114.53 -        g.setFont("italic 40px Calibri");
  114.54 -        g.fillText(m.getHelloMessage(), 10, 40);
  114.55 -    }
  114.56 -
  114.57 -    /** Callback function called by the KnockOut/Java binding on elements
  114.58 -     * representing href's with individual messages being their data.
  114.59 -     * 
  114.60 -     * @param data the data associated with the element 
  114.61 -     * @param m the model of the page
  114.62 -     */
  114.63 -    @OnFunction
  114.64 -    static void display(String data, Index m) {
  114.65 -        GraphicsContext g = m.canvas.getContext();
  114.66 -        g.clearRect(0, 0, 1000, 1000);
  114.67 -        g.setFillStyle("black");
  114.68 -        g.setFont("italic 40px Calibri");
  114.69 -        g.fillText(data, 10, 40);
  114.70 -    }
  114.71 -
  114.72 -    /** Callback function.
  114.73 -     * 
  114.74 -     * @param data data associated with the actual element on the page
  114.75 -     * @param m the model of the page
  114.76 -     */
  114.77 -    @OnFunction
  114.78 -    static void remove(String data, Index m) {
  114.79 -        m.getMessages().remove(data);
  114.80 -    }
  114.81 -    
  114.82 -    @ComputedProperty
  114.83 -    static String helloMessage(String name) {
  114.84 -        return "Hello " + name + "!";
  114.85 -    }
  114.86 -    
  114.87 -    @ComputedProperty
  114.88 -    static boolean noMessages(List<String> messages) {
  114.89 -        return messages.isEmpty();
  114.90 -    }
  114.91 -}
   115.1 --- a/rt/archetype/src/main/resources/archetype-resources/src/main/resources/index.html	Tue Apr 29 15:25:58 2014 +0200
   115.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.3 @@ -1,31 +0,0 @@
   115.4 -<?xml version="1.0" encoding="UTF-8"?>
   115.5 -<!DOCTYPE html>
   115.6 -<html xmlns="http://www.w3.org/1999/xhtml">
   115.7 -    <head>
   115.8 -        <title>Bck2Brwsr's Hello World</title>
   115.9 -    </head>
  115.10 -    <body>
  115.11 -        <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
  115.12 -        Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
  115.13 -        <button id="hello">Say Hello!</button>
  115.14 -        <p>
  115.15 -            <canvas id="canvas" width="300" height="50">
  115.16 -            </canvas>
  115.17 -        </p>
  115.18 -        
  115.19 -        
  115.20 -        <div data-bind="if: noMessages">No message displayed yet.</div>
  115.21 -        <ul data-bind="foreach: messages">
  115.22 -            <li>
  115.23 -                <a href="#" data-bind="text: $data, click: $root.display"></a>
  115.24 -                (<a href="#" data-bind="click: $root.remove">delete</a>)
  115.25 -            </li>
  115.26 -        </ul>
  115.27 -      
  115.28 -        <script src="bck2brwsr.js"></script>
  115.29 -        <script type="text/javascript">
  115.30 -            var vm = bck2brwsr('${artifactId}-${version}.jar');
  115.31 -            vm.loadClass('${package}.App');
  115.32 -        </script>
  115.33 -    </body>
  115.34 -</html>
   116.1 --- a/rt/archetype/src/main/resources/archetype-resources/src/test/java/AppTest.java	Tue Apr 29 15:25:58 2014 +0200
   116.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.3 @@ -1,26 +0,0 @@
   116.4 -package ${package};
   116.5 -
   116.6 -import static org.testng.Assert.*;
   116.7 -import org.testng.annotations.BeforeMethod;
   116.8 -import org.testng.annotations.Test;
   116.9 -
  116.10 -/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
  116.11 - * as it does not reference any HTML elements or browser functionality. Just
  116.12 - * operates on the page model.
  116.13 - *
  116.14 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  116.15 - */
  116.16 -public class AppTest {
  116.17 -    private Index model;
  116.18 -    
  116.19 -
  116.20 -    @BeforeMethod
  116.21 -    public void initModel() {
  116.22 -        model = new Index().applyBindings();
  116.23 -    }
  116.24 -
  116.25 -    @Test public void testHelloMessage() {
  116.26 -        model.setName("Joe");
  116.27 -        assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
  116.28 -    }
  116.29 -}
   117.1 --- a/rt/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java	Tue Apr 29 15:25:58 2014 +0200
   117.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.3 @@ -1,40 +0,0 @@
   117.4 -package ${package};
   117.5 -
   117.6 -import org.apidesign.bck2brwsr.vmtest.Compare;
   117.7 -import org.apidesign.bck2brwsr.vmtest.VMTest;
   117.8 -import org.testng.annotations.Factory;
   117.9 -
  117.10 -/** Bck2brwsr cares about compatibility with real Java. Whatever API is
  117.11 - * supported by bck2brwsr, it needs to behave the same way as when running
  117.12 - * in HotSpot VM. 
  117.13 - * <p>
  117.14 - * There can be bugs, however. To help us fix them, we kindly ask you to 
  117.15 - * write an "inconsistency" test. A test that compares behavior of the API
  117.16 - * between real VM and bck2brwsr VM. This class is skeleton of such test.
  117.17 - *
  117.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  117.19 - */
  117.20 -public class InconsistencyTest {
  117.21 -    /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
  117.22 -     * Make calls to an API that behaves strangely, return some result at
  117.23 -     * the end. No need to use any <code>assert</code>.
  117.24 -     * 
  117.25 -     * @return value to compare between HotSpot and bck2brwsr
  117.26 -     */
  117.27 -    @Compare
  117.28 -    public int checkStringHashCode() throws Exception {
  117.29 -        return "Is string hashCode the same?".hashCode();
  117.30 -    }
  117.31 -
  117.32 -    /** Factory method that creates a three tests for each method annotated with
  117.33 -     * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
  117.34 -     * HotSpot, one in Rhino and the last one compares the results.
  117.35 -     * 
  117.36 -     * @see org.apidesign.bck2brwsr.vmtest.VMTest
  117.37 -     */
  117.38 -    @Factory
  117.39 -    public static Object[] create() {
  117.40 -        return VMTest.create(InconsistencyTest.class);
  117.41 -    }
  117.42 -    
  117.43 -}
   118.1 --- a/rt/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java	Tue Apr 29 15:25:58 2014 +0200
   118.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.3 @@ -1,46 +0,0 @@
   118.4 -package ${package};
   118.5 -
   118.6 -import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
   118.7 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   118.8 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
   118.9 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  118.10 -import org.testng.annotations.Factory;
  118.11 -
  118.12 -/** Sometimes it is useful to run tests inside of the real browser. 
  118.13 - * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
  118.14 - * and that is it. If your code references elements on the HTML page,
  118.15 - * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
  118.16 - * will be made available on the page before your test starts.
  118.17 - *
  118.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  118.19 - */
  118.20 -public class IntegrationTest {
  118.21 -    
  118.22 -    /** Write to testing code here. Use <code>assert</code> (but not TestNG's
  118.23 -     * Assert, as TestNG is not compiled with target 1.6 yet).
  118.24 -     */
  118.25 -    @HtmlFragment(
  118.26 -        "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
  118.27 -        "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
  118.28 -        "<button id=\"hello\">Say Hello!</button>\n" +
  118.29 -        "<p>\n" +
  118.30 -        "    <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
  118.31 -        "</p>\n"
  118.32 -    )
  118.33 -    @BrwsrTest
  118.34 -    public void modifyValueAssertChangeInModel() {
  118.35 -        Index m = new Index();
  118.36 -        m.setName("Joe Hacker");
  118.37 -        m.applyBindings();
  118.38 -        assert "Joe Hacker".equals(m.input.getValue()) : "Value is really Joe Hacker: " + m.input.getValue();
  118.39 -        m.input.setValue("Happy Joe");
  118.40 -        m.triggerEvent(m.input, OnEvent.CHANGE);
  118.41 -        assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
  118.42 -    }
  118.43 -
  118.44 -    @Factory
  118.45 -    public static Object[] create() {
  118.46 -        return VMTest.create(IntegrationTest.class);
  118.47 -    }
  118.48 -    
  118.49 -}
   119.1 --- a/rt/archetype/src/test/java/org/apidesign/bck2brwsr/archetype/ArchetypeVersionTest.java	Tue Apr 29 15:25:58 2014 +0200
   119.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.3 @@ -1,101 +0,0 @@
   119.4 -/**
   119.5 - * Back 2 Browser Bytecode Translator
   119.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   119.7 - *
   119.8 - * This program is free software: you can redistribute it and/or modify
   119.9 - * it under the terms of the GNU General Public License as published by
  119.10 - * the Free Software Foundation, version 2 of the License.
  119.11 - *
  119.12 - * This program is distributed in the hope that it will be useful,
  119.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  119.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  119.15 - * GNU General Public License for more details.
  119.16 - *
  119.17 - * You should have received a copy of the GNU General Public License
  119.18 - * along with this program. Look for COPYING file in the top folder.
  119.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  119.20 - */
  119.21 -package org.apidesign.bck2brwsr.archetype;
  119.22 -
  119.23 -import java.net.URL;
  119.24 -import javax.xml.XMLConstants;
  119.25 -import javax.xml.parsers.DocumentBuilderFactory;
  119.26 -import javax.xml.xpath.XPathConstants;
  119.27 -import javax.xml.xpath.XPathExpression;
  119.28 -import javax.xml.xpath.XPathFactory;
  119.29 -import org.testng.annotations.Test;
  119.30 -import static org.testng.Assert.*;
  119.31 -import org.testng.annotations.BeforeClass;
  119.32 -import org.w3c.dom.Document;
  119.33 -import org.w3c.dom.NodeList;
  119.34 -
  119.35 -/**
  119.36 - *
  119.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  119.38 - */
  119.39 -public class ArchetypeVersionTest {
  119.40 -    private String version;
  119.41 -    
  119.42 -    public ArchetypeVersionTest() {
  119.43 -    }
  119.44 -    
  119.45 -    @BeforeClass public void readCurrentVersion() throws Exception {
  119.46 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  119.47 -        URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/bck2brwsr-archetype-html-sample/pom.xml");
  119.48 -        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
  119.49 -
  119.50 -        final XPathFactory fact = XPathFactory.newInstance();
  119.51 -        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
  119.52 -
  119.53 -        XPathExpression xp = fact.newXPath().compile("project/version/text()");
  119.54 -        
  119.55 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
  119.56 -        version = xp.evaluate(dom);
  119.57 -
  119.58 -        assertFalse(version.isEmpty(), "There should be some version string");
  119.59 -    }
  119.60 -    
  119.61 -
  119.62 -    @Test public void testComparePomDepsVersions() throws Exception {
  119.63 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  119.64 -        URL r = l.getResource("archetype-resources/pom.xml");
  119.65 -        assertNotNull(r, "Archetype pom found");
  119.66 -        
  119.67 -        final XPathFactory fact = XPathFactory.newInstance();
  119.68 -        XPathExpression xp2 = fact.newXPath().compile(
  119.69 -            "//version[../groupId/text() = 'org.apidesign.bck2brwsr']/text()"
  119.70 -        );
  119.71 -        
  119.72 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  119.73 -        NodeList arch = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  119.74 -
  119.75 -        if (arch.getLength() < 3) {
  119.76 -            fail("There should be at least three dependencies to bck2brwsr APIs: " + arch.getLength());
  119.77 -        }
  119.78 -        
  119.79 -        for (int i = 0; i < arch.getLength(); i++) {
  119.80 -            assertEquals(arch.item(i).getTextContent(), version, i + "th dependency needs to be on latest version of bck2brwsr");
  119.81 -        }
  119.82 -    }
  119.83 -    
  119.84 -    @Test public void testNbActions() throws Exception {
  119.85 -        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  119.86 -        URL r = l.getResource("archetype-resources/nbactions.xml");
  119.87 -        assertNotNull(r, "Archetype nb file found");
  119.88 -        
  119.89 -        final XPathFactory fact = XPathFactory.newInstance();
  119.90 -        XPathExpression xp2 = fact.newXPath().compile(
  119.91 -            "//goal/text()"
  119.92 -        );
  119.93 -        
  119.94 -        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  119.95 -        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  119.96 -        
  119.97 -        for (int i = 0; i < goals.getLength(); i++) {
  119.98 -            String s = goals.item(i).getTextContent();
  119.99 -            if (s.contains("bck2brwsr")) {
 119.100 -                assertFalse(s.matches(".*bck2brwsr.*[0-9].*"), "No numbers: " + s);
 119.101 -            }
 119.102 -        }
 119.103 -    }
 119.104 -}
   120.1 --- a/rt/core/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   120.2 +++ b/rt/core/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   120.3 @@ -4,11 +4,11 @@
   120.4    <parent>
   120.5      <groupId>org.apidesign.bck2brwsr</groupId>
   120.6      <artifactId>rt</artifactId>
   120.7 -    <version>0.8-SNAPSHOT</version>
   120.8 +    <version>0.9-SNAPSHOT</version>
   120.9    </parent>
  120.10    <groupId>org.apidesign.bck2brwsr</groupId>
  120.11    <artifactId>core</artifactId>
  120.12 -  <version>0.8-SNAPSHOT</version>
  120.13 +  <version>0.9-SNAPSHOT</version>
  120.14    <name>Bck2Brwsr Native Annotations</name>
  120.15    <url>http://maven.apache.org</url>
  120.16      <build>
   121.1 --- a/rt/emul/brwsrtest/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   121.2 +++ b/rt/emul/brwsrtest/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   121.3 @@ -4,11 +4,11 @@
   121.4    <parent>
   121.5      <groupId>org.apidesign.bck2brwsr</groupId>
   121.6      <artifactId>emul.pom</artifactId>
   121.7 -    <version>0.8-SNAPSHOT</version>
   121.8 +    <version>0.9-SNAPSHOT</version>
   121.9    </parent>
  121.10    <groupId>org.apidesign.bck2brwsr</groupId>
  121.11    <artifactId>brwsrtest</artifactId>
  121.12 -  <version>0.8-SNAPSHOT</version>
  121.13 +  <version>0.9-SNAPSHOT</version>
  121.14    <name>Tests Inside Real Browser</name>
  121.15    <url>http://maven.apache.org</url>
  121.16    <properties>
   122.1 --- a/rt/emul/brwsrtest/src/test/java/org/apidesign/bck2brwsr/brwsrtest/ResourcesInBrwsrTest.java	Tue Apr 29 15:25:58 2014 +0200
   122.2 +++ b/rt/emul/brwsrtest/src/test/java/org/apidesign/bck2brwsr/brwsrtest/ResourcesInBrwsrTest.java	Wed Apr 30 15:04:10 2014 +0200
   122.3 @@ -17,7 +17,10 @@
   122.4   */
   122.5  package org.apidesign.bck2brwsr.brwsrtest;
   122.6  
   122.7 +import java.io.IOException;
   122.8  import java.io.InputStream;
   122.9 +import java.net.URL;
  122.10 +import java.util.Enumeration;
  122.11  import org.apidesign.bck2brwsr.vmtest.Compare;
  122.12  import org.apidesign.bck2brwsr.vmtest.VMTest;
  122.13  import org.testng.annotations.Factory;
  122.14 @@ -30,14 +33,36 @@
  122.15      
  122.16      @Compare public String readResourceAsStream() throws Exception {
  122.17          InputStream is = getClass().getResourceAsStream("Resources.txt");
  122.18 -        assert is != null : "The stream for Resources.txt should be found";
  122.19 -        byte[] b = new byte[30];
  122.20 -        int len = is.read(b);
  122.21 +        return readString(is);
  122.22 +    }
  122.23 +    
  122.24 +    @Compare public String readResourceViaConnection() throws Exception {
  122.25 +        InputStream is = getClass().getResource("Resources.txt").openConnection().getInputStream();
  122.26 +        return readString(is);
  122.27 +    }
  122.28 +
  122.29 +    private String readString(InputStream is) throws IOException {
  122.30          StringBuilder sb = new StringBuilder();
  122.31 -        for (int i = 0; i < len; i++) {
  122.32 -            sb.append((char)b[i]);
  122.33 +        byte[] b = new byte[512];
  122.34 +        for (;;) { 
  122.35 +            int len = is.read(b);
  122.36 +            if (len == -1) {
  122.37 +                return sb.toString();
  122.38 +            }
  122.39 +            for (int i = 0; i < len; i++) {
  122.40 +                sb.append((char)b[i]);
  122.41 +            }
  122.42          }
  122.43 -        return sb.toString();
  122.44 +    }
  122.45 +
  122.46 +    @Compare public String readResourceAsStreamFromClassLoader() throws Exception {
  122.47 +        InputStream is = getClass().getClassLoader().getResourceAsStream("org/apidesign/bck2brwsr/brwsrtest/Resources.txt");
  122.48 +        return readString(is);
  122.49 +    }
  122.50 +    
  122.51 +    @Compare public String toURIFromURL() throws Exception {
  122.52 +        URL u = new URL("http://apidesign.org");
  122.53 +        return u.toURI().toString();
  122.54      }
  122.55      
  122.56      @Factory public static Object[] create() {
   123.1 --- a/rt/emul/compact/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   123.2 +++ b/rt/emul/compact/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   123.3 @@ -4,11 +4,11 @@
   123.4    <parent>
   123.5      <groupId>org.apidesign.bck2brwsr</groupId>
   123.6      <artifactId>emul.pom</artifactId>
   123.7 -    <version>0.8-SNAPSHOT</version>
   123.8 +    <version>0.9-SNAPSHOT</version>
   123.9    </parent>
  123.10    <groupId>org.apidesign.bck2brwsr</groupId>
  123.11    <artifactId>emul</artifactId>
  123.12 -  <version>0.8-SNAPSHOT</version>
  123.13 +  <version>0.9-SNAPSHOT</version>
  123.14    <name>Bck2Brwsr API Profile</name>
  123.15    <url>http://maven.apache.org</url>
  123.16    <properties>
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/rt/emul/compact/src/main/java/java/io/BufferedInputStream.java	Wed Apr 30 15:04:10 2014 +0200
   124.3 @@ -0,0 +1,458 @@
   124.4 +/*
   124.5 + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
   124.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   124.7 + *
   124.8 + * This code is free software; you can redistribute it and/or modify it
   124.9 + * under the terms of the GNU General Public License version 2 only, as
  124.10 + * published by the Free Software Foundation.  Oracle designates this
  124.11 + * particular file as subject to the "Classpath" exception as provided
  124.12 + * by Oracle in the LICENSE file that accompanied this code.
  124.13 + *
  124.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  124.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  124.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  124.17 + * version 2 for more details (a copy is included in the LICENSE file that
  124.18 + * accompanied this code).
  124.19 + *
  124.20 + * You should have received a copy of the GNU General Public License version
  124.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  124.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  124.23 + *
  124.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  124.25 + * or visit www.oracle.com if you need additional information or have any
  124.26 + * questions.
  124.27 + */
  124.28 +
  124.29 +package java.io;
  124.30 +
  124.31 +/**
  124.32 + * A <code>BufferedInputStream</code> adds
  124.33 + * functionality to another input stream-namely,
  124.34 + * the ability to buffer the input and to
  124.35 + * support the <code>mark</code> and <code>reset</code>
  124.36 + * methods. When  the <code>BufferedInputStream</code>
  124.37 + * is created, an internal buffer array is
  124.38 + * created. As bytes  from the stream are read
  124.39 + * or skipped, the internal buffer is refilled
  124.40 + * as necessary  from the contained input stream,
  124.41 + * many bytes at a time. The <code>mark</code>
  124.42 + * operation  remembers a point in the input
  124.43 + * stream and the <code>reset</code> operation
  124.44 + * causes all the  bytes read since the most
  124.45 + * recent <code>mark</code> operation to be
  124.46 + * reread before new bytes are  taken from
  124.47 + * the contained input stream.
  124.48 + *
  124.49 + * @author  Arthur van Hoff
  124.50 + * @since   JDK1.0
  124.51 + */
  124.52 +public
  124.53 +class BufferedInputStream extends FilterInputStream {
  124.54 +
  124.55 +    private static int defaultBufferSize = 8192;
  124.56 +
  124.57 +    /**
  124.58 +     * The internal buffer array where the data is stored. When necessary,
  124.59 +     * it may be replaced by another array of
  124.60 +     * a different size.
  124.61 +     */
  124.62 +    protected volatile byte buf[];
  124.63 +
  124.64 +
  124.65 +    /**
  124.66 +     * The index one greater than the index of the last valid byte in
  124.67 +     * the buffer.
  124.68 +     * This value is always
  124.69 +     * in the range <code>0</code> through <code>buf.length</code>;
  124.70 +     * elements <code>buf[0]</code>  through <code>buf[count-1]
  124.71 +     * </code>contain buffered input data obtained
  124.72 +     * from the underlying  input stream.
  124.73 +     */
  124.74 +    protected int count;
  124.75 +
  124.76 +    /**
  124.77 +     * The current position in the buffer. This is the index of the next
  124.78 +     * character to be read from the <code>buf</code> array.
  124.79 +     * <p>
  124.80 +     * This value is always in the range <code>0</code>
  124.81 +     * through <code>count</code>. If it is less
  124.82 +     * than <code>count</code>, then  <code>buf[pos]</code>
  124.83 +     * is the next byte to be supplied as input;
  124.84 +     * if it is equal to <code>count</code>, then
  124.85 +     * the  next <code>read</code> or <code>skip</code>
  124.86 +     * operation will require more bytes to be
  124.87 +     * read from the contained  input stream.
  124.88 +     *
  124.89 +     * @see     java.io.BufferedInputStream#buf
  124.90 +     */
  124.91 +    protected int pos;
  124.92 +
  124.93 +    /**
  124.94 +     * The value of the <code>pos</code> field at the time the last
  124.95 +     * <code>mark</code> method was called.
  124.96 +     * <p>
  124.97 +     * This value is always
  124.98 +     * in the range <code>-1</code> through <code>pos</code>.
  124.99 +     * If there is no marked position in  the input
 124.100 +     * stream, this field is <code>-1</code>. If
 124.101 +     * there is a marked position in the input
 124.102 +     * stream,  then <code>buf[markpos]</code>
 124.103 +     * is the first byte to be supplied as input
 124.104 +     * after a <code>reset</code> operation. If
 124.105 +     * <code>markpos</code> is not <code>-1</code>,
 124.106 +     * then all bytes from positions <code>buf[markpos]</code>
 124.107 +     * through  <code>buf[pos-1]</code> must remain
 124.108 +     * in the buffer array (though they may be
 124.109 +     * moved to  another place in the buffer array,
 124.110 +     * with suitable adjustments to the values
 124.111 +     * of <code>count</code>,  <code>pos</code>,
 124.112 +     * and <code>markpos</code>); they may not
 124.113 +     * be discarded unless and until the difference
 124.114 +     * between <code>pos</code> and <code>markpos</code>
 124.115 +     * exceeds <code>marklimit</code>.
 124.116 +     *
 124.117 +     * @see     java.io.BufferedInputStream#mark(int)
 124.118 +     * @see     java.io.BufferedInputStream#pos
 124.119 +     */
 124.120 +    protected int markpos = -1;
 124.121 +
 124.122 +    /**
 124.123 +     * The maximum read ahead allowed after a call to the
 124.124 +     * <code>mark</code> method before subsequent calls to the
 124.125 +     * <code>reset</code> method fail.
 124.126 +     * Whenever the difference between <code>pos</code>
 124.127 +     * and <code>markpos</code> exceeds <code>marklimit</code>,
 124.128 +     * then the  mark may be dropped by setting
 124.129 +     * <code>markpos</code> to <code>-1</code>.
 124.130 +     *
 124.131 +     * @see     java.io.BufferedInputStream#mark(int)
 124.132 +     * @see     java.io.BufferedInputStream#reset()
 124.133 +     */
 124.134 +    protected int marklimit;
 124.135 +
 124.136 +    /**
 124.137 +     * Check to make sure that underlying input stream has not been
 124.138 +     * nulled out due to close; if not return it;
 124.139 +     */
 124.140 +    private InputStream getInIfOpen() throws IOException {
 124.141 +        InputStream input = in;
 124.142 +        if (input == null)
 124.143 +            throw new IOException("Stream closed");
 124.144 +        return input;
 124.145 +    }
 124.146 +
 124.147 +    /**
 124.148 +     * Check to make sure that buffer has not been nulled out due to
 124.149 +     * close; if not return it;
 124.150 +     */
 124.151 +    private byte[] getBufIfOpen() throws IOException {
 124.152 +        byte[] buffer = buf;
 124.153 +        if (buffer == null)
 124.154 +            throw new IOException("Stream closed");
 124.155 +        return buffer;
 124.156 +    }
 124.157 +
 124.158 +    /**
 124.159 +     * Creates a <code>BufferedInputStream</code>
 124.160 +     * and saves its  argument, the input stream
 124.161 +     * <code>in</code>, for later use. An internal
 124.162 +     * buffer array is created and  stored in <code>buf</code>.
 124.163 +     *
 124.164 +     * @param   in   the underlying input stream.
 124.165 +     */
 124.166 +    public BufferedInputStream(InputStream in) {
 124.167 +        this(in, defaultBufferSize);
 124.168 +    }
 124.169 +
 124.170 +    /**
 124.171 +     * Creates a <code>BufferedInputStream</code>
 124.172 +     * with the specified buffer size,
 124.173 +     * and saves its  argument, the input stream
 124.174 +     * <code>in</code>, for later use.  An internal
 124.175 +     * buffer array of length  <code>size</code>
 124.176 +     * is created and stored in <code>buf</code>.
 124.177 +     *
 124.178 +     * @param   in     the underlying input stream.
 124.179 +     * @param   size   the buffer size.
 124.180 +     * @exception IllegalArgumentException if size <= 0.
 124.181 +     */
 124.182 +    public BufferedInputStream(InputStream in, int size) {
 124.183 +        super(in);
 124.184 +        if (size <= 0) {
 124.185 +            throw new IllegalArgumentException("Buffer size <= 0");
 124.186 +        }
 124.187 +        buf = new byte[size];
 124.188 +    }
 124.189 +
 124.190 +    /**
 124.191 +     * Fills the buffer with more data, taking into account
 124.192 +     * shuffling and other tricks for dealing with marks.
 124.193 +     * Assumes that it is being called by a synchronized method.
 124.194 +     * This method also assumes that all data has already been read in,
 124.195 +     * hence pos > count.
 124.196 +     */
 124.197 +    private void fill() throws IOException {
 124.198 +        byte[] buffer = getBufIfOpen();
 124.199 +        if (markpos < 0)
 124.200 +            pos = 0;            /* no mark: throw away the buffer */
 124.201 +        else if (pos >= buffer.length)  /* no room left in buffer */
 124.202 +            if (markpos > 0) {  /* can throw away early part of the buffer */
 124.203 +                int sz = pos - markpos;
 124.204 +                System.arraycopy(buffer, markpos, buffer, 0, sz);
 124.205 +                pos = sz;
 124.206 +                markpos = 0;
 124.207 +            } else if (buffer.length >= marklimit) {
 124.208 +                markpos = -1;   /* buffer got too big, invalidate mark */
 124.209 +                pos = 0;        /* drop buffer contents */
 124.210 +            } else {            /* grow buffer */
 124.211 +                int nsz = pos * 2;
 124.212 +                if (nsz > marklimit)
 124.213 +                    nsz = marklimit;
 124.214 +                byte nbuf[] = new byte[nsz];
 124.215 +                System.arraycopy(buffer, 0, nbuf, 0, pos);
 124.216 +                buffer = nbuf;
 124.217 +            }
 124.218 +        count = pos;
 124.219 +        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
 124.220 +        if (n > 0)
 124.221 +            count = n + pos;
 124.222 +    }
 124.223 +
 124.224 +    /**
 124.225 +     * See
 124.226 +     * the general contract of the <code>read</code>
 124.227 +     * method of <code>InputStream</code>.
 124.228 +     *
 124.229 +     * @return     the next byte of data, or <code>-1</code> if the end of the
 124.230 +     *             stream is reached.
 124.231 +     * @exception  IOException  if this input stream has been closed by
 124.232 +     *                          invoking its {@link #close()} method,
 124.233 +     *                          or an I/O error occurs.
 124.234 +     * @see        java.io.FilterInputStream#in
 124.235 +     */
 124.236 +    public synchronized int read() throws IOException {
 124.237 +        if (pos >= count) {
 124.238 +            fill();
 124.239 +            if (pos >= count)
 124.240 +                return -1;
 124.241 +        }
 124.242 +        return getBufIfOpen()[pos++] & 0xff;
 124.243 +    }
 124.244 +
 124.245 +    /**
 124.246 +     * Read characters into a portion of an array, reading from the underlying
 124.247 +     * stream at most once if necessary.
 124.248 +     */
 124.249 +    private int read1(byte[] b, int off, int len) throws IOException {
 124.250 +        int avail = count - pos;
 124.251 +        if (avail <= 0) {
 124.252 +            /* If the requested length is at least as large as the buffer, and
 124.253 +               if there is no mark/reset activity, do not bother to copy the
 124.254 +               bytes into the local buffer.  In this way buffered streams will
 124.255 +               cascade harmlessly. */
 124.256 +            if (len >= getBufIfOpen().length && markpos < 0) {
 124.257 +                return getInIfOpen().read(b, off, len);
 124.258 +            }
 124.259 +            fill();
 124.260 +            avail = count - pos;
 124.261 +            if (avail <= 0) return -1;
 124.262 +        }
 124.263 +        int cnt = (avail < len) ? avail : len;
 124.264 +        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
 124.265 +        pos += cnt;
 124.266 +        return cnt;
 124.267 +    }
 124.268 +
 124.269 +    /**
 124.270 +     * Reads bytes from this byte-input stream into the specified byte array,
 124.271 +     * starting at the given offset.
 124.272 +     *
 124.273 +     * <p> This method implements the general contract of the corresponding
 124.274 +     * <code>{@link InputStream#read(byte[], int, int) read}</code> method of
 124.275 +     * the <code>{@link InputStream}</code> class.  As an additional
 124.276 +     * convenience, it attempts to read as many bytes as possible by repeatedly
 124.277 +     * invoking the <code>read</code> method of the underlying stream.  This
 124.278 +     * iterated <code>read</code> continues until one of the following
 124.279 +     * conditions becomes true: <ul>
 124.280 +     *
 124.281 +     *   <li> The specified number of bytes have been read,
 124.282 +     *
 124.283 +     *   <li> The <code>read</code> method of the underlying stream returns
 124.284 +     *   <code>-1</code>, indicating end-of-file, or
 124.285 +     *
 124.286 +     *   <li> The <code>available</code> method of the underlying stream
 124.287 +     *   returns zero, indicating that further input requests would block.
 124.288 +     *
 124.289 +     * </ul> If the first <code>read</code> on the underlying stream returns
 124.290 +     * <code>-1</code> to indicate end-of-file then this method returns
 124.291 +     * <code>-1</code>.  Otherwise this method returns the number of bytes
 124.292 +     * actually read.
 124.293 +     *
 124.294 +     * <p> Subclasses of this class are encouraged, but not required, to
 124.295 +     * attempt to read as many bytes as possible in the same fashion.
 124.296 +     *
 124.297 +     * @param      b     destination buffer.
 124.298 +     * @param      off   offset at which to start storing bytes.
 124.299 +     * @param      len   maximum number of bytes to read.
 124.300 +     * @return     the number of bytes read, or <code>-1</code> if the end of
 124.301 +     *             the stream has been reached.
 124.302 +     * @exception  IOException  if this input stream has been closed by
 124.303 +     *                          invoking its {@link #close()} method,
 124.304 +     *                          or an I/O error occurs.
 124.305 +     */
 124.306 +    public synchronized int read(byte b[], int off, int len)
 124.307 +        throws IOException
 124.308 +    {
 124.309 +        getBufIfOpen(); // Check for closed stream
 124.310 +        if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
 124.311 +            throw new IndexOutOfBoundsException();
 124.312 +        } else if (len == 0) {
 124.313 +            return 0;
 124.314 +        }
 124.315 +
 124.316 +        int n = 0;
 124.317 +        for (;;) {
 124.318 +            int nread = read1(b, off + n, len - n);
 124.319 +            if (nread <= 0)
 124.320 +                return (n == 0) ? nread : n;
 124.321 +            n += nread;
 124.322 +            if (n >= len)
 124.323 +                return n;
 124.324 +            // if not closed but no bytes available, return
 124.325 +            InputStream input = in;
 124.326 +            if (input != null && input.available() <= 0)
 124.327 +                return n;
 124.328 +        }
 124.329 +    }
 124.330 +
 124.331 +    /**
 124.332 +     * See the general contract of the <code>skip</code>
 124.333 +     * method of <code>InputStream</code>.
 124.334 +     *
 124.335 +     * @exception  IOException  if the stream does not support seek,
 124.336 +     *                          or if this input stream has been closed by
 124.337 +     *                          invoking its {@link #close()} method, or an
 124.338 +     *                          I/O error occurs.
 124.339 +     */
 124.340 +    public synchronized long skip(long n) throws IOException {
 124.341 +        getBufIfOpen(); // Check for closed stream
 124.342 +        if (n <= 0) {
 124.343 +            return 0;
 124.344 +        }
 124.345 +        long avail = count - pos;
 124.346 +
 124.347 +        if (avail <= 0) {
 124.348 +            // If no mark position set then don't keep in buffer
 124.349 +            if (markpos <0)
 124.350 +                return getInIfOpen().skip(n);
 124.351 +
 124.352 +            // Fill in buffer to save bytes for reset
 124.353 +            fill();
 124.354 +            avail = count - pos;
 124.355 +            if (avail <= 0)
 124.356 +                return 0;
 124.357 +        }
 124.358 +
 124.359 +        long skipped = (avail < n) ? avail : n;
 124.360 +        pos += skipped;
 124.361 +        return skipped;
 124.362 +    }
 124.363 +
 124.364 +    /**
 124.365 +     * Returns an estimate of the number of bytes that can be read (or
 124.366 +     * skipped over) from this input stream without blocking by the next
 124.367 +     * invocation of a method for this input stream. The next invocation might be
 124.368 +     * the same thread or another thread.  A single read or skip of this
 124.369 +     * many bytes will not block, but may read or skip fewer bytes.
 124.370 +     * <p>
 124.371 +     * This method returns the sum of the number of bytes remaining to be read in
 124.372 +     * the buffer (<code>count&nbsp;- pos</code>) and the result of calling the
 124.373 +     * {@link java.io.FilterInputStream#in in}.available().
 124.374 +     *
 124.375 +     * @return     an estimate of the number of bytes that can be read (or skipped
 124.376 +     *             over) from this input stream without blocking.
 124.377 +     * @exception  IOException  if this input stream has been closed by
 124.378 +     *                          invoking its {@link #close()} method,
 124.379 +     *                          or an I/O error occurs.
 124.380 +     */
 124.381 +    public synchronized int available() throws IOException {
 124.382 +        int n = count - pos;
 124.383 +        int avail = getInIfOpen().available();
 124.384 +        return n > (Integer.MAX_VALUE - avail)
 124.385 +                    ? Integer.MAX_VALUE
 124.386 +                    : n + avail;
 124.387 +    }
 124.388 +
 124.389 +    /**
 124.390 +     * See the general contract of the <code>mark</code>
 124.391 +     * method of <code>InputStream</code>.
 124.392 +     *
 124.393 +     * @param   readlimit   the maximum limit of bytes that can be read before
 124.394 +     *                      the mark position becomes invalid.
 124.395 +     * @see     java.io.BufferedInputStream#reset()
 124.396 +     */
 124.397 +    public synchronized void mark(int readlimit) {
 124.398 +        marklimit = readlimit;
 124.399 +        markpos = pos;
 124.400 +    }
 124.401 +
 124.402 +    /**
 124.403 +     * See the general contract of the <code>reset</code>
 124.404 +     * method of <code>InputStream</code>.
 124.405 +     * <p>
 124.406 +     * If <code>markpos</code> is <code>-1</code>
 124.407 +     * (no mark has been set or the mark has been
 124.408 +     * invalidated), an <code>IOException</code>
 124.409 +     * is thrown. Otherwise, <code>pos</code> is
 124.410 +     * set equal to <code>markpos</code>.
 124.411 +     *
 124.412 +     * @exception  IOException  if this stream has not been marked or,
 124.413 +     *                  if the mark has been invalidated, or the stream
 124.414 +     *                  has been closed by invoking its {@link #close()}
 124.415 +     *                  method, or an I/O error occurs.
 124.416 +     * @see        java.io.BufferedInputStream#mark(int)
 124.417 +     */
 124.418 +    public synchronized void reset() throws IOException {
 124.419 +        getBufIfOpen(); // Cause exception if closed
 124.420 +        if (markpos < 0)
 124.421 +            throw new IOException("Resetting to invalid mark");
 124.422 +        pos = markpos;
 124.423 +    }
 124.424 +
 124.425 +    /**
 124.426 +     * Tests if this input stream supports the <code>mark</code>
 124.427 +     * and <code>reset</code> methods. The <code>markSupported</code>
 124.428 +     * method of <code>BufferedInputStream</code> returns
 124.429 +     * <code>true</code>.
 124.430 +     *
 124.431 +     * @return  a <code>boolean</code> indicating if this stream type supports
 124.432 +     *          the <code>mark</code> and <code>reset</code> methods.
 124.433 +     * @see     java.io.InputStream#mark(int)
 124.434 +     * @see     java.io.InputStream#reset()
 124.435 +     */
 124.436 +    public boolean markSupported() {
 124.437 +        return true;
 124.438 +    }
 124.439 +
 124.440 +    /**
 124.441 +     * Closes this input stream and releases any system resources
 124.442 +     * associated with the stream.
 124.443 +     * Once the stream has been closed, further read(), available(), reset(),
 124.444 +     * or skip() invocations will throw an IOException.
 124.445 +     * Closing a previously closed stream has no effect.
 124.446 +     *
 124.447 +     * @exception  IOException  if an I/O error occurs.
 124.448 +     */
 124.449 +    public void close() throws IOException {
 124.450 +        byte[] buffer;
 124.451 +        while ( (buffer = buf) != null) {
 124.452 +            InputStream input = in;
 124.453 +            buf = null;
 124.454 +            in = null;
 124.455 +            if (input != null)
 124.456 +                input.close();
 124.457 +            return;
 124.458 +            // Else retry in case a new buf was CASed in fill()
 124.459 +        }
 124.460 +    }
 124.461 +}
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/rt/emul/compact/src/main/java/java/io/BufferedWriter.java	Wed Apr 30 15:04:10 2014 +0200
   125.3 @@ -0,0 +1,271 @@
   125.4 +/*
   125.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   125.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   125.7 + *
   125.8 + * This code is free software; you can redistribute it and/or modify it
   125.9 + * under the terms of the GNU General Public License version 2 only, as
  125.10 + * published by the Free Software Foundation.  Oracle designates this
  125.11 + * particular file as subject to the "Classpath" exception as provided
  125.12 + * by Oracle in the LICENSE file that accompanied this code.
  125.13 + *
  125.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  125.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  125.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  125.17 + * version 2 for more details (a copy is included in the LICENSE file that
  125.18 + * accompanied this code).
  125.19 + *
  125.20 + * You should have received a copy of the GNU General Public License version
  125.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  125.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  125.23 + *
  125.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  125.25 + * or visit www.oracle.com if you need additional information or have any
  125.26 + * questions.
  125.27 + */
  125.28 +
  125.29 +package java.io;
  125.30 +
  125.31 +
  125.32 +/**
  125.33 + * Writes text to a character-output stream, buffering characters so as to
  125.34 + * provide for the efficient writing of single characters, arrays, and strings.
  125.35 + *
  125.36 + * <p> The buffer size may be specified, or the default size may be accepted.
  125.37 + * The default is large enough for most purposes.
  125.38 + *
  125.39 + * <p> A newLine() method is provided, which uses the platform's own notion of
  125.40 + * line separator as defined by the system property <tt>line.separator</tt>.
  125.41 + * Not all platforms use the newline character ('\n') to terminate lines.
  125.42 + * Calling this method to terminate each output line is therefore preferred to
  125.43 + * writing a newline character directly.
  125.44 + *
  125.45 + * <p> In general, a Writer sends its output immediately to the underlying
  125.46 + * character or byte stream.  Unless prompt output is required, it is advisable
  125.47 + * to wrap a BufferedWriter around any Writer whose write() operations may be
  125.48 + * costly, such as FileWriters and OutputStreamWriters.  For example,
  125.49 + *
  125.50 + * <pre>
  125.51 + * PrintWriter out
  125.52 + *   = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
  125.53 + * </pre>
  125.54 + *
  125.55 + * will buffer the PrintWriter's output to the file.  Without buffering, each
  125.56 + * invocation of a print() method would cause characters to be converted into
  125.57 + * bytes that would then be written immediately to the file, which can be very
  125.58 + * inefficient.
  125.59 + *
  125.60 + * @see PrintWriter
  125.61 + * @see FileWriter
  125.62 + * @see OutputStreamWriter
  125.63 + * @see java.nio.file.Files#newBufferedWriter
  125.64 + *
  125.65 + * @author      Mark Reinhold
  125.66 + * @since       JDK1.1
  125.67 + */
  125.68 +
  125.69 +public class BufferedWriter extends Writer {
  125.70 +
  125.71 +    private Writer out;
  125.72 +
  125.73 +    private char cb[];
  125.74 +    private int nChars, nextChar;
  125.75 +
  125.76 +    private static int defaultCharBufferSize = 8192;
  125.77 +
  125.78 +    /**
  125.79 +     * Line separator string.  This is the value of the line.separator
  125.80 +     * property at the moment that the stream was created.
  125.81 +     */
  125.82 +    private String lineSeparator;
  125.83 +
  125.84 +    /**
  125.85 +     * Creates a buffered character-output stream that uses a default-sized
  125.86 +     * output buffer.
  125.87 +     *
  125.88 +     * @param  out  A Writer
  125.89 +     */
  125.90 +    public BufferedWriter(Writer out) {
  125.91 +        this(out, defaultCharBufferSize);
  125.92 +    }
  125.93 +
  125.94 +    /**
  125.95 +     * Creates a new buffered character-output stream that uses an output
  125.96 +     * buffer of the given size.
  125.97 +     *
  125.98 +     * @param  out  A Writer
  125.99 +     * @param  sz   Output-buffer size, a positive integer
 125.100 +     *
 125.101 +     * @exception  IllegalArgumentException  If sz is <= 0
 125.102 +     */
 125.103 +    public BufferedWriter(Writer out, int sz) {
 125.104 +        super(out);
 125.105 +        if (sz <= 0)
 125.106 +            throw new IllegalArgumentException("Buffer size <= 0");
 125.107 +        this.out = out;
 125.108 +        cb = new char[sz];
 125.109 +        nChars = sz;
 125.110 +        nextChar = 0;
 125.111 +
 125.112 +        lineSeparator = "\n";
 125.113 +    }
 125.114 +
 125.115 +    /** Checks to make sure that the stream has not been closed */
 125.116 +    private void ensureOpen() throws IOException {
 125.117 +        if (out == null)
 125.118 +            throw new IOException("Stream closed");
 125.119 +    }
 125.120 +
 125.121 +    /**
 125.122 +     * Flushes the output buffer to the underlying character stream, without
 125.123 +     * flushing the stream itself.  This method is non-private only so that it
 125.124 +     * may be invoked by PrintStream.
 125.125 +     */
 125.126 +    void flushBuffer() throws IOException {
 125.127 +        synchronized (lock) {
 125.128 +            ensureOpen();
 125.129 +            if (nextChar == 0)
 125.130 +                return;
 125.131 +            out.write(cb, 0, nextChar);
 125.132 +            nextChar = 0;
 125.133 +        }
 125.134 +    }
 125.135 +
 125.136 +    /**
 125.137 +     * Writes a single character.
 125.138 +     *
 125.139 +     * @exception  IOException  If an I/O error occurs
 125.140 +     */
 125.141 +    public void write(int c) throws IOException {
 125.142 +        synchronized (lock) {
 125.143 +            ensureOpen();
 125.144 +            if (nextChar >= nChars)
 125.145 +                flushBuffer();
 125.146 +            cb[nextChar++] = (char) c;
 125.147 +        }
 125.148 +    }
 125.149 +
 125.150 +    /**
 125.151 +     * Our own little min method, to avoid loading java.lang.Math if we've run
 125.152 +     * out of file descriptors and we're trying to print a stack trace.
 125.153 +     */
 125.154 +    private int min(int a, int b) {
 125.155 +        if (a < b) return a;
 125.156 +        return b;
 125.157 +    }
 125.158 +
 125.159 +    /**
 125.160 +     * Writes a portion of an array of characters.
 125.161 +     *
 125.162 +     * <p> Ordinarily this method stores characters from the given array into
 125.163 +     * this stream's buffer, flushing the buffer to the underlying stream as
 125.164 +     * needed.  If the requested length is at least as large as the buffer,
 125.165 +     * however, then this method will flush the buffer and write the characters
 125.166 +     * directly to the underlying stream.  Thus redundant
 125.167 +     * <code>BufferedWriter</code>s will not copy data unnecessarily.
 125.168 +     *
 125.169 +     * @param  cbuf  A character array
 125.170 +     * @param  off   Offset from which to start reading characters
 125.171 +     * @param  len   Number of characters to write
 125.172 +     *
 125.173 +     * @exception  IOException  If an I/O error occurs
 125.174 +     */
 125.175 +    public void write(char cbuf[], int off, int len) throws IOException {
 125.176 +        synchronized (lock) {
 125.177 +            ensureOpen();
 125.178 +            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
 125.179 +                ((off + len) > cbuf.length) || ((off + len) < 0)) {
 125.180 +                throw new IndexOutOfBoundsException();
 125.181 +            } else if (len == 0) {
 125.182 +                return;
 125.183 +            }
 125.184 +
 125.185 +            if (len >= nChars) {
 125.186 +                /* If the request length exceeds the size of the output buffer,
 125.187 +                   flush the buffer and then write the data directly.  In this
 125.188 +                   way buffered streams will cascade harmlessly. */
 125.189 +                flushBuffer();
 125.190 +                out.write(cbuf, off, len);
 125.191 +                return;
 125.192 +            }
 125.193 +
 125.194 +            int b = off, t = off + len;
 125.195 +            while (b < t) {
 125.196 +                int d = min(nChars - nextChar, t - b);
 125.197 +                System.arraycopy(cbuf, b, cb, nextChar, d);
 125.198 +                b += d;
 125.199 +                nextChar += d;
 125.200 +                if (nextChar >= nChars)
 125.201 +                    flushBuffer();
 125.202 +            }
 125.203 +        }
 125.204 +    }
 125.205 +
 125.206 +    /**
 125.207 +     * Writes a portion of a String.
 125.208 +     *
 125.209 +     * <p> If the value of the <tt>len</tt> parameter is negative then no
 125.210 +     * characters are written.  This is contrary to the specification of this
 125.211 +     * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int)
 125.212 +     * superclass}, which requires that an {@link IndexOutOfBoundsException} be
 125.213 +     * thrown.
 125.214 +     *
 125.215 +     * @param  s     String to be written
 125.216 +     * @param  off   Offset from which to start reading characters
 125.217 +     * @param  len   Number of characters to be written
 125.218 +     *
 125.219 +     * @exception  IOException  If an I/O error occurs
 125.220 +     */
 125.221 +    public void write(String s, int off, int len) throws IOException {
 125.222 +        synchronized (lock) {
 125.223 +            ensureOpen();
 125.224 +
 125.225 +            int b = off, t = off + len;
 125.226 +            while (b < t) {
 125.227 +                int d = min(nChars - nextChar, t - b);
 125.228 +                s.getChars(b, b + d, cb, nextChar);
 125.229 +                b += d;
 125.230 +                nextChar += d;
 125.231 +                if (nextChar >= nChars)
 125.232 +                    flushBuffer();
 125.233 +            }
 125.234 +        }
 125.235 +    }
 125.236 +
 125.237 +    /**
 125.238 +     * Writes a line separator.  The line separator string is defined by the
 125.239 +     * system property <tt>line.separator</tt>, and is not necessarily a single
 125.240 +     * newline ('\n') character.
 125.241 +     *
 125.242 +     * @exception  IOException  If an I/O error occurs
 125.243 +     */
 125.244 +    public void newLine() throws IOException {
 125.245 +        write(lineSeparator);
 125.246 +    }
 125.247 +
 125.248 +    /**
 125.249 +     * Flushes the stream.
 125.250 +     *
 125.251 +     * @exception  IOException  If an I/O error occurs
 125.252 +     */
 125.253 +    public void flush() throws IOException {
 125.254 +        synchronized (lock) {
 125.255 +            flushBuffer();
 125.256 +            out.flush();
 125.257 +        }
 125.258 +    }
 125.259 +
 125.260 +    public void close() throws IOException {
 125.261 +        synchronized (lock) {
 125.262 +            if (out == null) {
 125.263 +                return;
 125.264 +            }
 125.265 +            try {
 125.266 +                flushBuffer();
 125.267 +            } finally {
 125.268 +                out.close();
 125.269 +                out = null;
 125.270 +                cb = null;
 125.271 +            }
 125.272 +        }
 125.273 +    }
 125.274 +}
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/rt/emul/compact/src/main/java/java/io/File.java	Wed Apr 30 15:04:10 2014 +0200
   126.3 @@ -0,0 +1,1927 @@
   126.4 +/*
   126.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
   126.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   126.7 + *
   126.8 + * This code is free software; you can redistribute it and/or modify it
   126.9 + * under the terms of the GNU General Public License version 2 only, as
  126.10 + * published by the Free Software Foundation.  Oracle designates this
  126.11 + * particular file as subject to the "Classpath" exception as provided
  126.12 + * by Oracle in the LICENSE file that accompanied this code.
  126.13 + *
  126.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  126.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  126.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  126.17 + * version 2 for more details (a copy is included in the LICENSE file that
  126.18 + * accompanied this code).
  126.19 + *
  126.20 + * You should have received a copy of the GNU General Public License version
  126.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  126.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  126.23 + *
  126.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  126.25 + * or visit www.oracle.com if you need additional information or have any
  126.26 + * questions.
  126.27 + */
  126.28 +
  126.29 +package java.io;
  126.30 +
  126.31 +import java.net.URI;
  126.32 +import java.net.URL;
  126.33 +import java.net.MalformedURLException;
  126.34 +import java.net.URISyntaxException;
  126.35 +
  126.36 +/**
  126.37 + * An abstract representation of file and directory pathnames.
  126.38 + *
  126.39 + * <p> User interfaces and operating systems use system-dependent <em>pathname
  126.40 + * strings</em> to name files and directories.  This class presents an
  126.41 + * abstract, system-independent view of hierarchical pathnames.  An
  126.42 + * <em>abstract pathname</em> has two components:
  126.43 + *
  126.44 + * <ol>
  126.45 + * <li> An optional system-dependent <em>prefix</em> string,
  126.46 + *      such as a disk-drive specifier, <code>"/"</code>&nbsp;for the UNIX root
  126.47 + *      directory, or <code>"\\\\"</code>&nbsp;for a Microsoft Windows UNC pathname, and
  126.48 + * <li> A sequence of zero or more string <em>names</em>.
  126.49 + * </ol>
  126.50 + *
  126.51 + * The first name in an abstract pathname may be a directory name or, in the
  126.52 + * case of Microsoft Windows UNC pathnames, a hostname.  Each subsequent name
  126.53 + * in an abstract pathname denotes a directory; the last name may denote
  126.54 + * either a directory or a file.  The <em>empty</em> abstract pathname has no
  126.55 + * prefix and an empty name sequence.
  126.56 + *
  126.57 + * <p> The conversion of a pathname string to or from an abstract pathname is
  126.58 + * inherently system-dependent.  When an abstract pathname is converted into a
  126.59 + * pathname string, each name is separated from the next by a single copy of
  126.60 + * the default <em>separator character</em>.  The default name-separator
  126.61 + * character is defined by the system property <code>file.separator</code>, and
  126.62 + * is made available in the public static fields <code>{@link
  126.63 + * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
  126.64 + * When a pathname string is converted into an abstract pathname, the names
  126.65 + * within it may be separated by the default name-separator character or by any
  126.66 + * other name-separator character that is supported by the underlying system.
  126.67 + *
  126.68 + * <p> A pathname, whether abstract or in string form, may be either
  126.69 + * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
  126.70 + * that no other information is required in order to locate the file that it
  126.71 + * denotes.  A relative pathname, in contrast, must be interpreted in terms of
  126.72 + * information taken from some other pathname.  By default the classes in the
  126.73 + * <code>java.io</code> package always resolve relative pathnames against the
  126.74 + * current user directory.  This directory is named by the system property
  126.75 + * <code>user.dir</code>, and is typically the directory in which the Java
  126.76 + * virtual machine was invoked.
  126.77 + *
  126.78 + * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
  126.79 + * the {@link #getParent} method of this class and consists of the pathname's
  126.80 + * prefix and each name in the pathname's name sequence except for the last.
  126.81 + * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
  126.82 + * object with an absolute abstract pathname which begins with the directory's
  126.83 + * absolute pathname.  For example, the directory denoted by the abstract
  126.84 + * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
  126.85 + * pathname <tt>"/usr/local/bin"</tt>.
  126.86 + *
  126.87 + * <p> The prefix concept is used to handle root directories on UNIX platforms,
  126.88 + * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
  126.89 + * as follows:
  126.90 + *
  126.91 + * <ul>
  126.92 + *
  126.93 + * <li> For UNIX platforms, the prefix of an absolute pathname is always
  126.94 + * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
  126.95 + * denoting the root directory has the prefix <code>"/"</code> and an empty
  126.96 + * name sequence.
  126.97 + *
  126.98 + * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
  126.99 + * specifier consists of the drive letter followed by <code>":"</code> and
 126.100 + * possibly followed by <code>"\\"</code> if the pathname is absolute.  The
 126.101 + * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
 126.102 + * name are the first two names in the name sequence.  A relative pathname that
 126.103 + * does not specify a drive has no prefix.
 126.104 + *
 126.105 + * </ul>
 126.106 + *
 126.107 + * <p> Instances of this class may or may not denote an actual file-system
 126.108 + * object such as a file or a directory.  If it does denote such an object
 126.109 + * then that object resides in a <i>partition</i>.  A partition is an
 126.110 + * operating system-specific portion of storage for a file system.  A single
 126.111 + * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
 126.112 + * contain multiple partitions.  The object, if any, will reside on the
 126.113 + * partition <a name="partName">named</a> by some ancestor of the absolute
 126.114 + * form of this pathname.
 126.115 + *
 126.116 + * <p> A file system may implement restrictions to certain operations on the
 126.117 + * actual file-system object, such as reading, writing, and executing.  These
 126.118 + * restrictions are collectively known as <i>access permissions</i>.  The file
 126.119 + * system may have multiple sets of access permissions on a single object.
 126.120 + * For example, one set may apply to the object's <i>owner</i>, and another
 126.121 + * may apply to all other users.  The access permissions on an object may
 126.122 + * cause some methods in this class to fail.
 126.123 + *
 126.124 + * <p> Instances of the <code>File</code> class are immutable; that is, once
 126.125 + * created, the abstract pathname represented by a <code>File</code> object
 126.126 + * will never change.
 126.127 + *
 126.128 + * <h4>Interoperability with {@code java.nio.file} package</h4>
 126.129 + *
 126.130 + * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
 126.131 + * package defines interfaces and classes for the Java virtual machine to access
 126.132 + * files, file attributes, and file systems. This API may be used to overcome
 126.133 + * many of the limitations of the {@code java.io.File} class.
 126.134 + * The {@link #toPath toPath} method may be used to obtain a {@link
 126.135 + * Path} that uses the abstract path represented by a {@code File} object to
 126.136 + * locate a file. The resulting {@code Path} may be used with the {@link
 126.137 + * java.nio.file.Files} class to provide more efficient and extensive access to
 126.138 + * additional file operations, file attributes, and I/O exceptions to help
 126.139 + * diagnose errors when an operation on a file fails.
 126.140 + *
 126.141 + * @author  unascribed
 126.142 + * @since   JDK1.0
 126.143 + */
 126.144 +
 126.145 +public class File
 126.146 +    implements Serializable, Comparable<File>
 126.147 +{
 126.148 +
 126.149 +    /**
 126.150 +     * The FileSystem object representing the platform's local file system.
 126.151 +     */
 126.152 +    static private FileSystem fs = new FileSystem();
 126.153 +    private static class FileSystem {
 126.154 +
 126.155 +        private char getSeparator() {
 126.156 +            return '/';
 126.157 +        }
 126.158 +
 126.159 +        private String resolve(String path, String child) {
 126.160 +            return path + '/' + child;
 126.161 +        }
 126.162 +
 126.163 +        private String normalize(String pathname) {
 126.164 +            return pathname;
 126.165 +        }
 126.166 +
 126.167 +        private int prefixLength(String path) {
 126.168 +            return 0;
 126.169 +        }
 126.170 +
 126.171 +        private String getDefaultParent() {
 126.172 +            return "/";
 126.173 +        }
 126.174 +
 126.175 +        private String fromURIPath(String p) {
 126.176 +            return p;
 126.177 +        }
 126.178 +
 126.179 +        private boolean isAbsolute(File aThis) {
 126.180 +            return aThis.getPath().startsWith("/");
 126.181 +        }
 126.182 +
 126.183 +        private int compare(File one, File two) {
 126.184 +            return one.getPath().compareTo(two.getPath());
 126.185 +        }
 126.186 +
 126.187 +        private int hashCode(File aThis) {
 126.188 +            return aThis.getPath().hashCode();
 126.189 +        }
 126.190 +
 126.191 +        private char getPathSeparator() {
 126.192 +            return ':';
 126.193 +        }
 126.194 +        
 126.195 +    }
 126.196 +
 126.197 +    /**
 126.198 +     * This abstract pathname's normalized pathname string.  A normalized
 126.199 +     * pathname string uses the default name-separator character and does not
 126.200 +     * contain any duplicate or redundant separators.
 126.201 +     *
 126.202 +     * @serial
 126.203 +     */
 126.204 +    private String path;
 126.205 +
 126.206 +    /**
 126.207 +     * The length of this abstract pathname's prefix, or zero if it has no
 126.208 +     * prefix.
 126.209 +     */
 126.210 +    private transient int prefixLength;
 126.211 +
 126.212 +    /**
 126.213 +     * Returns the length of this abstract pathname's prefix.
 126.214 +     * For use by FileSystem classes.
 126.215 +     */
 126.216 +    int getPrefixLength() {
 126.217 +        return prefixLength;
 126.218 +    }
 126.219 +
 126.220 +    /**
 126.221 +     * The system-dependent default name-separator character.  This field is
 126.222 +     * initialized to contain the first character of the value of the system
 126.223 +     * property <code>file.separator</code>.  On UNIX systems the value of this
 126.224 +     * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
 126.225 +     *
 126.226 +     * @see     java.lang.System#getProperty(java.lang.String)
 126.227 +     */
 126.228 +    public static final char separatorChar = fs.getSeparator();
 126.229 +
 126.230 +    /**
 126.231 +     * The system-dependent default name-separator character, represented as a
 126.232 +     * string for convenience.  This string contains a single character, namely
 126.233 +     * <code>{@link #separatorChar}</code>.
 126.234 +     */
 126.235 +    public static final String separator = "" + separatorChar;
 126.236 +
 126.237 +    /**
 126.238 +     * The system-dependent path-separator character.  This field is
 126.239 +     * initialized to contain the first character of the value of the system
 126.240 +     * property <code>path.separator</code>.  This character is used to
 126.241 +     * separate filenames in a sequence of files given as a <em>path list</em>.
 126.242 +     * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
 126.243 +     * is <code>';'</code>.
 126.244 +     *
 126.245 +     * @see     java.lang.System#getProperty(java.lang.String)
 126.246 +     */
 126.247 +    public static final char pathSeparatorChar = fs.getPathSeparator();
 126.248 +
 126.249 +    /**
 126.250 +     * The system-dependent path-separator character, represented as a string
 126.251 +     * for convenience.  This string contains a single character, namely
 126.252 +     * <code>{@link #pathSeparatorChar}</code>.
 126.253 +     */
 126.254 +    public static final String pathSeparator = "" + pathSeparatorChar;
 126.255 +
 126.256 +
 126.257 +    /* -- Constructors -- */
 126.258 +
 126.259 +    /**
 126.260 +     * Internal constructor for already-normalized pathname strings.
 126.261 +     */
 126.262 +    private File(String pathname, int prefixLength) {
 126.263 +        this.path = pathname;
 126.264 +        this.prefixLength = prefixLength;
 126.265 +    }
 126.266 +
 126.267 +    /**
 126.268 +     * Internal constructor for already-normalized pathname strings.
 126.269 +     * The parameter order is used to disambiguate this method from the
 126.270 +     * public(File, String) constructor.
 126.271 +     */
 126.272 +    private File(String child, File parent) {
 126.273 +        assert parent.path != null;
 126.274 +        assert (!parent.path.equals(""));
 126.275 +        this.path = fs.resolve(parent.path, child);
 126.276 +        this.prefixLength = parent.prefixLength;
 126.277 +    }
 126.278 +
 126.279 +    /**
 126.280 +     * Creates a new <code>File</code> instance by converting the given
 126.281 +     * pathname string into an abstract pathname.  If the given string is
 126.282 +     * the empty string, then the result is the empty abstract pathname.
 126.283 +     *
 126.284 +     * @param   pathname  A pathname string
 126.285 +     * @throws  NullPointerException
 126.286 +     *          If the <code>pathname</code> argument is <code>null</code>
 126.287 +     */
 126.288 +    public File(String pathname) {
 126.289 +        if (pathname == null) {
 126.290 +            throw new NullPointerException();
 126.291 +        }
 126.292 +        this.path = fs.normalize(pathname);
 126.293 +        this.prefixLength = fs.prefixLength(this.path);
 126.294 +    }
 126.295 +
 126.296 +    /* Note: The two-argument File constructors do not interpret an empty
 126.297 +       parent abstract pathname as the current user directory.  An empty parent
 126.298 +       instead causes the child to be resolved against the system-dependent
 126.299 +       directory defined by the FileSystem.getDefaultParent method.  On Unix
 126.300 +       this default is "/", while on Microsoft Windows it is "\\".  This is required for
 126.301 +       compatibility with the original behavior of this class. */
 126.302 +
 126.303 +    /**
 126.304 +     * Creates a new <code>File</code> instance from a parent pathname string
 126.305 +     * and a child pathname string.
 126.306 +     *
 126.307 +     * <p> If <code>parent</code> is <code>null</code> then the new
 126.308 +     * <code>File</code> instance is created as if by invoking the
 126.309 +     * single-argument <code>File</code> constructor on the given
 126.310 +     * <code>child</code> pathname string.
 126.311 +     *
 126.312 +     * <p> Otherwise the <code>parent</code> pathname string is taken to denote
 126.313 +     * a directory, and the <code>child</code> pathname string is taken to
 126.314 +     * denote either a directory or a file.  If the <code>child</code> pathname
 126.315 +     * string is absolute then it is converted into a relative pathname in a
 126.316 +     * system-dependent way.  If <code>parent</code> is the empty string then
 126.317 +     * the new <code>File</code> instance is created by converting
 126.318 +     * <code>child</code> into an abstract pathname and resolving the result
 126.319 +     * against a system-dependent default directory.  Otherwise each pathname
 126.320 +     * string is converted into an abstract pathname and the child abstract
 126.321 +     * pathname is resolved against the parent.
 126.322 +     *
 126.323 +     * @param   parent  The parent pathname string
 126.324 +     * @param   child   The child pathname string
 126.325 +     * @throws  NullPointerException
 126.326 +     *          If <code>child</code> is <code>null</code>
 126.327 +     */
 126.328 +    public File(String parent, String child) {
 126.329 +        if (child == null) {
 126.330 +            throw new NullPointerException();
 126.331 +        }
 126.332 +        if (parent != null) {
 126.333 +            if (parent.equals("")) {
 126.334 +                this.path = fs.resolve(fs.getDefaultParent(),
 126.335 +                                       fs.normalize(child));
 126.336 +            } else {
 126.337 +                this.path = fs.resolve(fs.normalize(parent),
 126.338 +                                       fs.normalize(child));
 126.339 +            }
 126.340 +        } else {
 126.341 +            this.path = fs.normalize(child);
 126.342 +        }
 126.343 +        this.prefixLength = fs.prefixLength(this.path);
 126.344 +    }
 126.345 +
 126.346 +    /**
 126.347 +     * Creates a new <code>File</code> instance from a parent abstract
 126.348 +     * pathname and a child pathname string.
 126.349 +     *
 126.350 +     * <p> If <code>parent</code> is <code>null</code> then the new
 126.351 +     * <code>File</code> instance is created as if by invoking the
 126.352 +     * single-argument <code>File</code> constructor on the given
 126.353 +     * <code>child</code> pathname string.
 126.354 +     *
 126.355 +     * <p> Otherwise the <code>parent</code> abstract pathname is taken to
 126.356 +     * denote a directory, and the <code>child</code> pathname string is taken
 126.357 +     * to denote either a directory or a file.  If the <code>child</code>
 126.358 +     * pathname string is absolute then it is converted into a relative
 126.359 +     * pathname in a system-dependent way.  If <code>parent</code> is the empty
 126.360 +     * abstract pathname then the new <code>File</code> instance is created by
 126.361 +     * converting <code>child</code> into an abstract pathname and resolving
 126.362 +     * the result against a system-dependent default directory.  Otherwise each
 126.363 +     * pathname string is converted into an abstract pathname and the child
 126.364 +     * abstract pathname is resolved against the parent.
 126.365 +     *
 126.366 +     * @param   parent  The parent abstract pathname
 126.367 +     * @param   child   The child pathname string
 126.368 +     * @throws  NullPointerException
 126.369 +     *          If <code>child</code> is <code>null</code>
 126.370 +     */
 126.371 +    public File(File parent, String child) {
 126.372 +        if (child == null) {
 126.373 +            throw new NullPointerException();
 126.374 +        }
 126.375 +        if (parent != null) {
 126.376 +            if (parent.path.equals("")) {
 126.377 +                this.path = fs.resolve(fs.getDefaultParent(),
 126.378 +                                       fs.normalize(child));
 126.379 +            } else {
 126.380 +                this.path = fs.resolve(parent.path,
 126.381 +                                       fs.normalize(child));
 126.382 +            }
 126.383 +        } else {
 126.384 +            this.path = fs.normalize(child);
 126.385 +        }
 126.386 +        this.prefixLength = fs.prefixLength(this.path);
 126.387 +    }
 126.388 +
 126.389 +    /**
 126.390 +     * Creates a new <tt>File</tt> instance by converting the given
 126.391 +     * <tt>file:</tt> URI into an abstract pathname.
 126.392 +     *
 126.393 +     * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
 126.394 +     * the transformation performed by this constructor is also
 126.395 +     * system-dependent.
 126.396 +     *
 126.397 +     * <p> For a given abstract pathname <i>f</i> it is guaranteed that
 126.398 +     *
 126.399 +     * <blockquote><tt>
 126.400 +     * new File(</tt><i>&nbsp;f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
 126.401 +     * </tt></blockquote>
 126.402 +     *
 126.403 +     * so long as the original abstract pathname, the URI, and the new abstract
 126.404 +     * pathname are all created in (possibly different invocations of) the same
 126.405 +     * Java virtual machine.  This relationship typically does not hold,
 126.406 +     * however, when a <tt>file:</tt> URI that is created in a virtual machine
 126.407 +     * on one operating system is converted into an abstract pathname in a
 126.408 +     * virtual machine on a different operating system.
 126.409 +     *
 126.410 +     * @param  uri
 126.411 +     *         An absolute, hierarchical URI with a scheme equal to
 126.412 +     *         <tt>"file"</tt>, a non-empty path component, and undefined
 126.413 +     *         authority, query, and fragment components
 126.414 +     *
 126.415 +     * @throws  NullPointerException
 126.416 +     *          If <tt>uri</tt> is <tt>null</tt>
 126.417 +     *
 126.418 +     * @throws  IllegalArgumentException
 126.419 +     *          If the preconditions on the parameter do not hold
 126.420 +     *
 126.421 +     * @see #toURI()
 126.422 +     * @see java.net.URI
 126.423 +     * @since 1.4
 126.424 +     */
 126.425 +    public File(URI uri) {
 126.426 +
 126.427 +        // Check our many preconditions
 126.428 +        if (!uri.isAbsolute())
 126.429 +            throw new IllegalArgumentException("URI is not absolute");
 126.430 +        if (uri.isOpaque())
 126.431 +            throw new IllegalArgumentException("URI is not hierarchical");
 126.432 +        String scheme = uri.getScheme();
 126.433 +        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
 126.434 +            throw new IllegalArgumentException("URI scheme is not \"file\"");
 126.435 +        if (uri.getAuthority() != null)
 126.436 +            throw new IllegalArgumentException("URI has an authority component");
 126.437 +        if (uri.getFragment() != null)
 126.438 +            throw new IllegalArgumentException("URI has a fragment component");
 126.439 +        if (uri.getQuery() != null)
 126.440 +            throw new IllegalArgumentException("URI has a query component");
 126.441 +        String p = uri.getPath();
 126.442 +        if (p.equals(""))
 126.443 +            throw new IllegalArgumentException("URI path component is empty");
 126.444 +
 126.445 +        // Okay, now initialize
 126.446 +        p = fs.fromURIPath(p);
 126.447 +        if (File.separatorChar != '/')
 126.448 +            p = p.replace('/', File.separatorChar);
 126.449 +        this.path = fs.normalize(p);
 126.450 +        this.prefixLength = fs.prefixLength(this.path);
 126.451 +    }
 126.452 +
 126.453 +
 126.454 +    /* -- Path-component accessors -- */
 126.455 +
 126.456 +    /**
 126.457 +     * Returns the name of the file or directory denoted by this abstract
 126.458 +     * pathname.  This is just the last name in the pathname's name
 126.459 +     * sequence.  If the pathname's name sequence is empty, then the empty
 126.460 +     * string is returned.
 126.461 +     *
 126.462 +     * @return  The name of the file or directory denoted by this abstract
 126.463 +     *          pathname, or the empty string if this pathname's name sequence
 126.464 +     *          is empty
 126.465 +     */
 126.466 +    public String getName() {
 126.467 +        int index = path.lastIndexOf(separatorChar);
 126.468 +        if (index < prefixLength) return path.substring(prefixLength);
 126.469 +        return path.substring(index + 1);
 126.470 +    }
 126.471 +
 126.472 +    /**
 126.473 +     * Returns the pathname string of this abstract pathname's parent, or
 126.474 +     * <code>null</code> if this pathname does not name a parent directory.
 126.475 +     *
 126.476 +     * <p> The <em>parent</em> of an abstract pathname consists of the
 126.477 +     * pathname's prefix, if any, and each name in the pathname's name
 126.478 +     * sequence except for the last.  If the name sequence is empty then
 126.479 +     * the pathname does not name a parent directory.
 126.480 +     *
 126.481 +     * @return  The pathname string of the parent directory named by this
 126.482 +     *          abstract pathname, or <code>null</code> if this pathname
 126.483 +     *          does not name a parent
 126.484 +     */
 126.485 +    public String getParent() {
 126.486 +        int index = path.lastIndexOf(separatorChar);
 126.487 +        if (index < prefixLength) {
 126.488 +            if ((prefixLength > 0) && (path.length() > prefixLength))
 126.489 +                return path.substring(0, prefixLength);
 126.490 +            return null;
 126.491 +        }
 126.492 +        return path.substring(0, index);
 126.493 +    }
 126.494 +
 126.495 +    /**
 126.496 +     * Returns the abstract pathname of this abstract pathname's parent,
 126.497 +     * or <code>null</code> if this pathname does not name a parent
 126.498 +     * directory.
 126.499 +     *
 126.500 +     * <p> The <em>parent</em> of an abstract pathname consists of the
 126.501 +     * pathname's prefix, if any, and each name in the pathname's name
 126.502 +     * sequence except for the last.  If the name sequence is empty then
 126.503 +     * the pathname does not name a parent directory.
 126.504 +     *
 126.505 +     * @return  The abstract pathname of the parent directory named by this
 126.506 +     *          abstract pathname, or <code>null</code> if this pathname
 126.507 +     *          does not name a parent
 126.508 +     *
 126.509 +     * @since 1.2
 126.510 +     */
 126.511 +    public File getParentFile() {
 126.512 +        String p = this.getParent();
 126.513 +        if (p == null) return null;
 126.514 +        return new File(p, this.prefixLength);
 126.515 +    }
 126.516 +
 126.517 +    /**
 126.518 +     * Converts this abstract pathname into a pathname string.  The resulting
 126.519 +     * string uses the {@link #separator default name-separator character} to
 126.520 +     * separate the names in the name sequence.
 126.521 +     *
 126.522 +     * @return  The string form of this abstract pathname
 126.523 +     */
 126.524 +    public String getPath() {
 126.525 +        return path;
 126.526 +    }
 126.527 +
 126.528 +
 126.529 +    /* -- Path operations -- */
 126.530 +
 126.531 +    /**
 126.532 +     * Tests whether this abstract pathname is absolute.  The definition of
 126.533 +     * absolute pathname is system dependent.  On UNIX systems, a pathname is
 126.534 +     * absolute if its prefix is <code>"/"</code>.  On Microsoft Windows systems, a
 126.535 +     * pathname is absolute if its prefix is a drive specifier followed by
 126.536 +     * <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
 126.537 +     *
 126.538 +     * @return  <code>true</code> if this abstract pathname is absolute,
 126.539 +     *          <code>false</code> otherwise
 126.540 +     */
 126.541 +    public boolean isAbsolute() {
 126.542 +        return fs.isAbsolute(this);
 126.543 +    }
 126.544 +
 126.545 +    /**
 126.546 +     * Returns the absolute pathname string of this abstract pathname.
 126.547 +     *
 126.548 +     * <p> If this abstract pathname is already absolute, then the pathname
 126.549 +     * string is simply returned as if by the <code>{@link #getPath}</code>
 126.550 +     * method.  If this abstract pathname is the empty abstract pathname then
 126.551 +     * the pathname string of the current user directory, which is named by the
 126.552 +     * system property <code>user.dir</code>, is returned.  Otherwise this
 126.553 +     * pathname is resolved in a system-dependent way.  On UNIX systems, a
 126.554 +     * relative pathname is made absolute by resolving it against the current
 126.555 +     * user directory.  On Microsoft Windows systems, a relative pathname is made absolute
 126.556 +     * by resolving it against the current directory of the drive named by the
 126.557 +     * pathname, if any; if not, it is resolved against the current user
 126.558 +     * directory.
 126.559 +     *
 126.560 +     * @return  The absolute pathname string denoting the same file or
 126.561 +     *          directory as this abstract pathname
 126.562 +     *
 126.563 +     * @throws  SecurityException
 126.564 +     *          If a required system property value cannot be accessed.
 126.565 +     *
 126.566 +     * @see     java.io.File#isAbsolute()
 126.567 +     */
 126.568 +    public String getAbsolutePath() {
 126.569 +        throw new SecurityException();
 126.570 +    }
 126.571 +
 126.572 +    /**
 126.573 +     * Returns the absolute form of this abstract pathname.  Equivalent to
 126.574 +     * <code>new&nbsp;File(this.{@link #getAbsolutePath})</code>.
 126.575 +     *
 126.576 +     * @return  The absolute abstract pathname denoting the same file or
 126.577 +     *          directory as this abstract pathname
 126.578 +     *
 126.579 +     * @throws  SecurityException
 126.580 +     *          If a required system property value cannot be accessed.
 126.581 +     *
 126.582 +     * @since 1.2
 126.583 +     */
 126.584 +    public File getAbsoluteFile() {
 126.585 +        String absPath = getAbsolutePath();
 126.586 +        return new File(absPath, fs.prefixLength(absPath));
 126.587 +    }
 126.588 +
 126.589 +    /**
 126.590 +     * Returns the canonical pathname string of this abstract pathname.
 126.591 +     *
 126.592 +     * <p> A canonical pathname is both absolute and unique.  The precise
 126.593 +     * definition of canonical form is system-dependent.  This method first
 126.594 +     * converts this pathname to absolute form if necessary, as if by invoking the
 126.595 +     * {@link #getAbsolutePath} method, and then maps it to its unique form in a
 126.596 +     * system-dependent way.  This typically involves removing redundant names
 126.597 +     * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
 126.598 +     * symbolic links (on UNIX platforms), and converting drive letters to a
 126.599 +     * standard case (on Microsoft Windows platforms).
 126.600 +     *
 126.601 +     * <p> Every pathname that denotes an existing file or directory has a
 126.602 +     * unique canonical form.  Every pathname that denotes a nonexistent file
 126.603 +     * or directory also has a unique canonical form.  The canonical form of
 126.604 +     * the pathname of a nonexistent file or directory may be different from
 126.605 +     * the canonical form of the same pathname after the file or directory is
 126.606 +     * created.  Similarly, the canonical form of the pathname of an existing
 126.607 +     * file or directory may be different from the canonical form of the same
 126.608 +     * pathname after the file or directory is deleted.
 126.609 +     *
 126.610 +     * @return  The canonical pathname string denoting the same file or
 126.611 +     *          directory as this abstract pathname
 126.612 +     *
 126.613 +     * @throws  IOException
 126.614 +     *          If an I/O error occurs, which is possible because the
 126.615 +     *          construction of the canonical pathname may require
 126.616 +     *          filesystem queries
 126.617 +     *
 126.618 +     * @throws  SecurityException
 126.619 +     *          If a required system property value cannot be accessed, or
 126.620 +     *          if a security manager exists and its <code>{@link
 126.621 +     *          java.lang.SecurityManager#checkRead}</code> method denies
 126.622 +     *          read access to the file
 126.623 +     *
 126.624 +     * @since   JDK1.1
 126.625 +     * @see     Path#toRealPath
 126.626 +     */
 126.627 +    public String getCanonicalPath() throws IOException {
 126.628 +        throw new SecurityException();
 126.629 +    }
 126.630 +
 126.631 +    /**
 126.632 +     * Returns the canonical form of this abstract pathname.  Equivalent to
 126.633 +     * <code>new&nbsp;File(this.{@link #getCanonicalPath})</code>.
 126.634 +     *
 126.635 +     * @return  The canonical pathname string denoting the same file or
 126.636 +     *          directory as this abstract pathname
 126.637 +     *
 126.638 +     * @throws  IOException
 126.639 +     *          If an I/O error occurs, which is possible because the
 126.640 +     *          construction of the canonical pathname may require
 126.641 +     *          filesystem queries
 126.642 +     *
 126.643 +     * @throws  SecurityException
 126.644 +     *          If a required system property value cannot be accessed, or
 126.645 +     *          if a security manager exists and its <code>{@link
 126.646 +     *          java.lang.SecurityManager#checkRead}</code> method denies
 126.647 +     *          read access to the file
 126.648 +     *
 126.649 +     * @since 1.2
 126.650 +     * @see     Path#toRealPath
 126.651 +     */
 126.652 +    public File getCanonicalFile() throws IOException {
 126.653 +        String canonPath = getCanonicalPath();
 126.654 +        return new File(canonPath, fs.prefixLength(canonPath));
 126.655 +    }
 126.656 +
 126.657 +    private static String slashify(String path, boolean isDirectory) {
 126.658 +        String p = path;
 126.659 +        if (File.separatorChar != '/')
 126.660 +            p = p.replace(File.separatorChar, '/');
 126.661 +        if (!p.startsWith("/"))
 126.662 +            p = "/" + p;
 126.663 +        if (!p.endsWith("/") && isDirectory)
 126.664 +            p = p + "/";
 126.665 +        return p;
 126.666 +    }
 126.667 +
 126.668 +    /**
 126.669 +     * Converts this abstract pathname into a <code>file:</code> URL.  The
 126.670 +     * exact form of the URL is system-dependent.  If it can be determined that
 126.671 +     * the file denoted by this abstract pathname is a directory, then the
 126.672 +     * resulting URL will end with a slash.
 126.673 +     *
 126.674 +     * @return  A URL object representing the equivalent file URL
 126.675 +     *
 126.676 +     * @throws  MalformedURLException
 126.677 +     *          If the path cannot be parsed as a URL
 126.678 +     *
 126.679 +     * @see     #toURI()
 126.680 +     * @see     java.net.URI
 126.681 +     * @see     java.net.URI#toURL()
 126.682 +     * @see     java.net.URL
 126.683 +     * @since   1.2
 126.684 +     *
 126.685 +     * @deprecated This method does not automatically escape characters that
 126.686 +     * are illegal in URLs.  It is recommended that new code convert an
 126.687 +     * abstract pathname into a URL by first converting it into a URI, via the
 126.688 +     * {@link #toURI() toURI} method, and then converting the URI into a URL
 126.689 +     * via the {@link java.net.URI#toURL() URI.toURL} method.
 126.690 +     */
 126.691 +    @Deprecated
 126.692 +    public URL toURL() throws MalformedURLException {
 126.693 +        return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
 126.694 +    }
 126.695 +
 126.696 +    /**
 126.697 +     * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
 126.698 +     *
 126.699 +     * <p> The exact form of the URI is system-dependent.  If it can be
 126.700 +     * determined that the file denoted by this abstract pathname is a
 126.701 +     * directory, then the resulting URI will end with a slash.
 126.702 +     *
 126.703 +     * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
 126.704 +     *
 126.705 +     * <blockquote><tt>
 126.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}())
 126.707 +     * </tt></blockquote>
 126.708 +     *
 126.709 +     * so long as the original abstract pathname, the URI, and the new abstract
 126.710 +     * pathname are all created in (possibly different invocations of) the same
 126.711 +     * Java virtual machine.  Due to the system-dependent nature of abstract
 126.712 +     * pathnames, however, this relationship typically does not hold when a
 126.713 +     * <tt>file:</tt> URI that is created in a virtual machine on one operating
 126.714 +     * system is converted into an abstract pathname in a virtual machine on a
 126.715 +     * different operating system.
 126.716 +     *
 126.717 +     * <p> Note that when this abstract pathname represents a UNC pathname then
 126.718 +     * all components of the UNC (including the server name component) are encoded
 126.719 +     * in the {@code URI} path. The authority component is undefined, meaning
 126.720 +     * that it is represented as {@code null}. The {@link Path} class defines the
 126.721 +     * {@link Path#toUri toUri} method to encode the server name in the authority
 126.722 +     * component of the resulting {@code URI}. The {@link #toPath toPath} method
 126.723 +     * may be used to obtain a {@code Path} representing this abstract pathname.
 126.724 +     *
 126.725 +     * @return  An absolute, hierarchical URI with a scheme equal to
 126.726 +     *          <tt>"file"</tt>, a path representing this abstract pathname,
 126.727 +     *          and undefined authority, query, and fragment components
 126.728 +     * @throws SecurityException If a required system property value cannot
 126.729 +     * be accessed.
 126.730 +     *
 126.731 +     * @see #File(java.net.URI)
 126.732 +     * @see java.net.URI
 126.733 +     * @see java.net.URI#toURL()
 126.734 +     * @since 1.4
 126.735 +     */
 126.736 +    public URI toURI() {
 126.737 +        try {
 126.738 +            File f = getAbsoluteFile();
 126.739 +            String sp = slashify(f.getPath(), f.isDirectory());
 126.740 +            if (sp.startsWith("//"))
 126.741 +                sp = "//" + sp;
 126.742 +            return new URI("file", null, sp, null);
 126.743 +        } catch (URISyntaxException x) {
 126.744 +            throw new Error(x);         // Can't happen
 126.745 +        }
 126.746 +    }
 126.747 +
 126.748 +
 126.749 +    /* -- Attribute accessors -- */
 126.750 +
 126.751 +    /**
 126.752 +     * Tests whether the application can read the file denoted by this
 126.753 +     * abstract pathname.
 126.754 +     *
 126.755 +     * @return  <code>true</code> if and only if the file specified by this
 126.756 +     *          abstract pathname exists <em>and</em> can be read by the
 126.757 +     *          application; <code>false</code> otherwise
 126.758 +     *
 126.759 +     * @throws  SecurityException
 126.760 +     *          If a security manager exists and its <code>{@link
 126.761 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.762 +     *          method denies read access to the file
 126.763 +     */
 126.764 +    public boolean canRead() {
 126.765 +        throw new SecurityException();
 126.766 +    }
 126.767 +
 126.768 +    /**
 126.769 +     * Tests whether the application can modify the file denoted by this
 126.770 +     * abstract pathname.
 126.771 +     *
 126.772 +     * @return  <code>true</code> if and only if the file system actually
 126.773 +     *          contains a file denoted by this abstract pathname <em>and</em>
 126.774 +     *          the application is allowed to write to the file;
 126.775 +     *          <code>false</code> otherwise.
 126.776 +     *
 126.777 +     * @throws  SecurityException
 126.778 +     *          If a security manager exists and its <code>{@link
 126.779 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
 126.780 +     *          method denies write access to the file
 126.781 +     */
 126.782 +    public boolean canWrite() {
 126.783 +        throw new SecurityException();
 126.784 +    }
 126.785 +
 126.786 +    /**
 126.787 +     * Tests whether the file or directory denoted by this abstract pathname
 126.788 +     * exists.
 126.789 +     *
 126.790 +     * @return  <code>true</code> if and only if the file or directory denoted
 126.791 +     *          by this abstract pathname exists; <code>false</code> otherwise
 126.792 +     *
 126.793 +     * @throws  SecurityException
 126.794 +     *          If a security manager exists and its <code>{@link
 126.795 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.796 +     *          method denies read access to the file or directory
 126.797 +     */
 126.798 +    public boolean exists() {
 126.799 +        throw new SecurityException();
 126.800 +    }
 126.801 +
 126.802 +    /**
 126.803 +     * Tests whether the file denoted by this abstract pathname is a
 126.804 +     * directory.
 126.805 +     *
 126.806 +     * <p> Where it is required to distinguish an I/O exception from the case
 126.807 +     * that the file is not a directory, or where several attributes of the
 126.808 +     * same file are required at the same time, then the {@link
 126.809 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 126.810 +     * Files.readAttributes} method may be used.
 126.811 +     *
 126.812 +     * @return <code>true</code> if and only if the file denoted by this
 126.813 +     *          abstract pathname exists <em>and</em> is a directory;
 126.814 +     *          <code>false</code> otherwise
 126.815 +     *
 126.816 +     * @throws  SecurityException
 126.817 +     *          If a security manager exists and its <code>{@link
 126.818 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.819 +     *          method denies read access to the file
 126.820 +     */
 126.821 +    public boolean isDirectory() {
 126.822 +        throw new SecurityException();
 126.823 +    }
 126.824 +
 126.825 +    /**
 126.826 +     * Tests whether the file denoted by this abstract pathname is a normal
 126.827 +     * file.  A file is <em>normal</em> if it is not a directory and, in
 126.828 +     * addition, satisfies other system-dependent criteria.  Any non-directory
 126.829 +     * file created by a Java application is guaranteed to be a normal file.
 126.830 +     *
 126.831 +     * <p> Where it is required to distinguish an I/O exception from the case
 126.832 +     * that the file is not a normal file, or where several attributes of the
 126.833 +     * same file are required at the same time, then the {@link
 126.834 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 126.835 +     * Files.readAttributes} method may be used.
 126.836 +     *
 126.837 +     * @return  <code>true</code> if and only if the file denoted by this
 126.838 +     *          abstract pathname exists <em>and</em> is a normal file;
 126.839 +     *          <code>false</code> otherwise
 126.840 +     *
 126.841 +     * @throws  SecurityException
 126.842 +     *          If a security manager exists and its <code>{@link
 126.843 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.844 +     *          method denies read access to the file
 126.845 +     */
 126.846 +    public boolean isFile() {
 126.847 +        throw new SecurityException();
 126.848 +    }
 126.849 +
 126.850 +    /**
 126.851 +     * Tests whether the file named by this abstract pathname is a hidden
 126.852 +     * file.  The exact definition of <em>hidden</em> is system-dependent.  On
 126.853 +     * UNIX systems, a file is considered to be hidden if its name begins with
 126.854 +     * a period character (<code>'.'</code>).  On Microsoft Windows systems, a file is
 126.855 +     * considered to be hidden if it has been marked as such in the filesystem.
 126.856 +     *
 126.857 +     * @return  <code>true</code> if and only if the file denoted by this
 126.858 +     *          abstract pathname is hidden according to the conventions of the
 126.859 +     *          underlying platform
 126.860 +     *
 126.861 +     * @throws  SecurityException
 126.862 +     *          If a security manager exists and its <code>{@link
 126.863 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.864 +     *          method denies read access to the file
 126.865 +     *
 126.866 +     * @since 1.2
 126.867 +     */
 126.868 +    public boolean isHidden() {
 126.869 +        throw new SecurityException();
 126.870 +    }
 126.871 +
 126.872 +    /**
 126.873 +     * Returns the time that the file denoted by this abstract pathname was
 126.874 +     * last modified.
 126.875 +     *
 126.876 +     * <p> Where it is required to distinguish an I/O exception from the case
 126.877 +     * where {@code 0L} is returned, or where several attributes of the
 126.878 +     * same file are required at the same time, or where the time of last
 126.879 +     * access or the creation time are required, then the {@link
 126.880 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 126.881 +     * Files.readAttributes} method may be used.
 126.882 +     *
 126.883 +     * @return  A <code>long</code> value representing the time the file was
 126.884 +     *          last modified, measured in milliseconds since the epoch
 126.885 +     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
 126.886 +     *          file does not exist or if an I/O error occurs
 126.887 +     *
 126.888 +     * @throws  SecurityException
 126.889 +     *          If a security manager exists and its <code>{@link
 126.890 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.891 +     *          method denies read access to the file
 126.892 +     */
 126.893 +    public long lastModified() {
 126.894 +        throw new SecurityException();
 126.895 +    }
 126.896 +
 126.897 +    /**
 126.898 +     * Returns the length of the file denoted by this abstract pathname.
 126.899 +     * The return value is unspecified if this pathname denotes a directory.
 126.900 +     *
 126.901 +     * <p> Where it is required to distinguish an I/O exception from the case
 126.902 +     * that {@code 0L} is returned, or where several attributes of the same file
 126.903 +     * are required at the same time, then the {@link
 126.904 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 126.905 +     * Files.readAttributes} method may be used.
 126.906 +     *
 126.907 +     * @return  The length, in bytes, of the file denoted by this abstract
 126.908 +     *          pathname, or <code>0L</code> if the file does not exist.  Some
 126.909 +     *          operating systems may return <code>0L</code> for pathnames
 126.910 +     *          denoting system-dependent entities such as devices or pipes.
 126.911 +     *
 126.912 +     * @throws  SecurityException
 126.913 +     *          If a security manager exists and its <code>{@link
 126.914 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 126.915 +     *          method denies read access to the file
 126.916 +     */
 126.917 +    public long length() {
 126.918 +        throw new SecurityException();
 126.919 +    }
 126.920 +
 126.921 +
 126.922 +    /* -- File operations -- */
 126.923 +
 126.924 +    /**
 126.925 +     * Atomically creates a new, empty file named by this abstract pathname if
 126.926 +     * and only if a file with this name does not yet exist.  The check for the
 126.927 +     * existence of the file and the creation of the file if it does not exist
 126.928 +     * are a single operation that is atomic with respect to all other
 126.929 +     * filesystem activities that might affect the file.
 126.930 +     * <P>
 126.931 +     * Note: this method should <i>not</i> be used for file-locking, as
 126.932 +     * the resulting protocol cannot be made to work reliably. The
 126.933 +     * {@link java.nio.channels.FileLock FileLock}
 126.934 +     * facility should be used instead.
 126.935 +     *
 126.936 +     * @return  <code>true</code> if the named file does not exist and was
 126.937 +     *          successfully created; <code>false</code> if the named file
 126.938 +     *          already exists
 126.939 +     *
 126.940 +     * @throws  IOException
 126.941 +     *          If an I/O error occurred
 126.942 +     *
 126.943 +     * @throws  SecurityException
 126.944 +     *          If a security manager exists and its <code>{@link
 126.945 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
 126.946 +     *          method denies write access to the file
 126.947 +     *
 126.948 +     * @since 1.2
 126.949 +     */
 126.950 +    public boolean createNewFile() throws IOException {
 126.951 +        throw new SecurityException();
 126.952 +    }
 126.953 +
 126.954 +    /**
 126.955 +     * Deletes the file or directory denoted by this abstract pathname.  If
 126.956 +     * this pathname denotes a directory, then the directory must be empty in
 126.957 +     * order to be deleted.
 126.958 +     *
 126.959 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
 126.960 +     * java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException}
 126.961 +     * when a file cannot be deleted. This is useful for error reporting and to
 126.962 +     * diagnose why a file cannot be deleted.
 126.963 +     *
 126.964 +     * @return  <code>true</code> if and only if the file or directory is
 126.965 +     *          successfully deleted; <code>false</code> otherwise
 126.966 +     *
 126.967 +     * @throws  SecurityException
 126.968 +     *          If a security manager exists and its <code>{@link
 126.969 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
 126.970 +     *          delete access to the file
 126.971 +     */
 126.972 +    public boolean delete() {
 126.973 +        throw new SecurityException();
 126.974 +    }
 126.975 +
 126.976 +    /**
 126.977 +     * Requests that the file or directory denoted by this abstract
 126.978 +     * pathname be deleted when the virtual machine terminates.
 126.979 +     * Files (or directories) are deleted in the reverse order that
 126.980 +     * they are registered. Invoking this method to delete a file or
 126.981 +     * directory that is already registered for deletion has no effect.
 126.982 +     * Deletion will be attempted only for normal termination of the
 126.983 +     * virtual machine, as defined by the Java Language Specification.
 126.984 +     *
 126.985 +     * <p> Once deletion has been requested, it is not possible to cancel the
 126.986 +     * request.  This method should therefore be used with care.
 126.987 +     *
 126.988 +     * <P>
 126.989 +     * Note: this method should <i>not</i> be used for file-locking, as
 126.990 +     * the resulting protocol cannot be made to work reliably. The
 126.991 +     * {@link java.nio.channels.FileLock FileLock}
 126.992 +     * facility should be used instead.
 126.993 +     *
 126.994 +     * @throws  SecurityException
 126.995 +     *          If a security manager exists and its <code>{@link
 126.996 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
 126.997 +     *          delete access to the file
 126.998 +     *
 126.999 +     * @see #delete
126.1000 +     *
126.1001 +     * @since 1.2
126.1002 +     */
126.1003 +    public void deleteOnExit() {
126.1004 +        throw new SecurityException();
126.1005 +    }
126.1006 +
126.1007 +    /**
126.1008 +     * Returns an array of strings naming the files and directories in the
126.1009 +     * directory denoted by this abstract pathname.
126.1010 +     *
126.1011 +     * <p> If this abstract pathname does not denote a directory, then this
126.1012 +     * method returns {@code null}.  Otherwise an array of strings is
126.1013 +     * returned, one for each file or directory in the directory.  Names
126.1014 +     * denoting the directory itself and the directory's parent directory are
126.1015 +     * not included in the result.  Each string is a file name rather than a
126.1016 +     * complete path.
126.1017 +     *
126.1018 +     * <p> There is no guarantee that the name strings in the resulting array
126.1019 +     * will appear in any specific order; they are not, in particular,
126.1020 +     * guaranteed to appear in alphabetical order.
126.1021 +     *
126.1022 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
126.1023 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to
126.1024 +     * open a directory and iterate over the names of the files in the directory.
126.1025 +     * This may use less resources when working with very large directories, and
126.1026 +     * may be more responsive when working with remote directories.
126.1027 +     *
126.1028 +     * @return  An array of strings naming the files and directories in the
126.1029 +     *          directory denoted by this abstract pathname.  The array will be
126.1030 +     *          empty if the directory is empty.  Returns {@code null} if
126.1031 +     *          this abstract pathname does not denote a directory, or if an
126.1032 +     *          I/O error occurs.
126.1033 +     *
126.1034 +     * @throws  SecurityException
126.1035 +     *          If a security manager exists and its {@link
126.1036 +     *          SecurityManager#checkRead(String)} method denies read access to
126.1037 +     *          the directory
126.1038 +     */
126.1039 +    public String[] list() {
126.1040 +        throw new SecurityException();
126.1041 +    }
126.1042 +
126.1043 +    /**
126.1044 +     * Returns an array of strings naming the files and directories in the
126.1045 +     * directory denoted by this abstract pathname that satisfy the specified
126.1046 +     * filter.  The behavior of this method is the same as that of the
126.1047 +     * {@link #list()} method, except that the strings in the returned array
126.1048 +     * must satisfy the filter.  If the given {@code filter} is {@code null}
126.1049 +     * then all names are accepted.  Otherwise, a name satisfies the filter if
126.1050 +     * and only if the value {@code true} results when the {@link
126.1051 +     * FilenameFilter#accept FilenameFilter.accept(File,&nbsp;String)} method
126.1052 +     * of the filter is invoked on this abstract pathname and the name of a
126.1053 +     * file or directory in the directory that it denotes.
126.1054 +     *
126.1055 +     * @param  filter
126.1056 +     *         A filename filter
126.1057 +     *
126.1058 +     * @return  An array of strings naming the files and directories in the
126.1059 +     *          directory denoted by this abstract pathname that were accepted
126.1060 +     *          by the given {@code filter}.  The array will be empty if the
126.1061 +     *          directory is empty or if no names were accepted by the filter.
126.1062 +     *          Returns {@code null} if this abstract pathname does not denote
126.1063 +     *          a directory, or if an I/O error occurs.
126.1064 +     *
126.1065 +     * @throws  SecurityException
126.1066 +     *          If a security manager exists and its {@link
126.1067 +     *          SecurityManager#checkRead(String)} method denies read access to
126.1068 +     *          the directory
126.1069 +     *
126.1070 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
126.1071 +     */
126.1072 +    public String[] list(FilenameFilter filter) {
126.1073 +        throw new SecurityException();
126.1074 +    }
126.1075 +
126.1076 +    /**
126.1077 +     * Returns an array of abstract pathnames denoting the files in the
126.1078 +     * directory denoted by this abstract pathname.
126.1079 +     *
126.1080 +     * <p> If this abstract pathname does not denote a directory, then this
126.1081 +     * method returns {@code null}.  Otherwise an array of {@code File} objects
126.1082 +     * is returned, one for each file or directory in the directory.  Pathnames
126.1083 +     * denoting the directory itself and the directory's parent directory are
126.1084 +     * not included in the result.  Each resulting abstract pathname is
126.1085 +     * constructed from this abstract pathname using the {@link #File(File,
126.1086 +     * String) File(File,&nbsp;String)} constructor.  Therefore if this
126.1087 +     * pathname is absolute then each resulting pathname is absolute; if this
126.1088 +     * pathname is relative then each resulting pathname will be relative to
126.1089 +     * the same directory.
126.1090 +     *
126.1091 +     * <p> There is no guarantee that the name strings in the resulting array
126.1092 +     * will appear in any specific order; they are not, in particular,
126.1093 +     * guaranteed to appear in alphabetical order.
126.1094 +     *
126.1095 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
126.1096 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method
126.1097 +     * to open a directory and iterate over the names of the files in the
126.1098 +     * directory. This may use less resources when working with very large
126.1099 +     * directories.
126.1100 +     *
126.1101 +     * @return  An array of abstract pathnames denoting the files and
126.1102 +     *          directories in the directory denoted by this abstract pathname.
126.1103 +     *          The array will be empty if the directory is empty.  Returns
126.1104 +     *          {@code null} if this abstract pathname does not denote a
126.1105 +     *          directory, or if an I/O error occurs.
126.1106 +     *
126.1107 +     * @throws  SecurityException
126.1108 +     *          If a security manager exists and its {@link
126.1109 +     *          SecurityManager#checkRead(String)} method denies read access to
126.1110 +     *          the directory
126.1111 +     *
126.1112 +     * @since  1.2
126.1113 +     */
126.1114 +    public File[] listFiles() {
126.1115 +        throw new SecurityException();
126.1116 +    }
126.1117 +
126.1118 +    /**
126.1119 +     * Returns an array of abstract pathnames denoting the files and
126.1120 +     * directories in the directory denoted by this abstract pathname that
126.1121 +     * satisfy the specified filter.  The behavior of this method is the same
126.1122 +     * as that of the {@link #listFiles()} method, except that the pathnames in
126.1123 +     * the returned array must satisfy the filter.  If the given {@code filter}
126.1124 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
126.1125 +     * satisfies the filter if and only if the value {@code true} results when
126.1126 +     * the {@link FilenameFilter#accept
126.1127 +     * FilenameFilter.accept(File,&nbsp;String)} method of the filter is
126.1128 +     * invoked on this abstract pathname and the name of a file or directory in
126.1129 +     * the directory that it denotes.
126.1130 +     *
126.1131 +     * @param  filter
126.1132 +     *         A filename filter
126.1133 +     *
126.1134 +     * @return  An array of abstract pathnames denoting the files and
126.1135 +     *          directories in the directory denoted by this abstract pathname.
126.1136 +     *          The array will be empty if the directory is empty.  Returns
126.1137 +     *          {@code null} if this abstract pathname does not denote a
126.1138 +     *          directory, or if an I/O error occurs.
126.1139 +     *
126.1140 +     * @throws  SecurityException
126.1141 +     *          If a security manager exists and its {@link
126.1142 +     *          SecurityManager#checkRead(String)} method denies read access to
126.1143 +     *          the directory
126.1144 +     *
126.1145 +     * @since  1.2
126.1146 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
126.1147 +     */
126.1148 +    public File[] listFiles(FilenameFilter filter) {
126.1149 +        throw new SecurityException();
126.1150 +    }
126.1151 +
126.1152 +    /**
126.1153 +     * Returns an array of abstract pathnames denoting the files and
126.1154 +     * directories in the directory denoted by this abstract pathname that
126.1155 +     * satisfy the specified filter.  The behavior of this method is the same
126.1156 +     * as that of the {@link #listFiles()} method, except that the pathnames in
126.1157 +     * the returned array must satisfy the filter.  If the given {@code filter}
126.1158 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
126.1159 +     * satisfies the filter if and only if the value {@code true} results when
126.1160 +     * the {@link FileFilter#accept FileFilter.accept(File)} method of the
126.1161 +     * filter is invoked on the pathname.
126.1162 +     *
126.1163 +     * @param  filter
126.1164 +     *         A file filter
126.1165 +     *
126.1166 +     * @return  An array of abstract pathnames denoting the files and
126.1167 +     *          directories in the directory denoted by this abstract pathname.
126.1168 +     *          The array will be empty if the directory is empty.  Returns
126.1169 +     *          {@code null} if this abstract pathname does not denote a
126.1170 +     *          directory, or if an I/O error occurs.
126.1171 +     *
126.1172 +     * @throws  SecurityException
126.1173 +     *          If a security manager exists and its {@link
126.1174 +     *          SecurityManager#checkRead(String)} method denies read access to
126.1175 +     *          the directory
126.1176 +     *
126.1177 +     * @since  1.2
126.1178 +     * @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
126.1179 +     */
126.1180 +    public File[] listFiles(FileFilter filter) {
126.1181 +        throw new SecurityException();
126.1182 +    }
126.1183 +
126.1184 +    /**
126.1185 +     * Creates the directory named by this abstract pathname.
126.1186 +     *
126.1187 +     * @return  <code>true</code> if and only if the directory was
126.1188 +     *          created; <code>false</code> otherwise
126.1189 +     *
126.1190 +     * @throws  SecurityException
126.1191 +     *          If a security manager exists and its <code>{@link
126.1192 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1193 +     *          method does not permit the named directory to be created
126.1194 +     */
126.1195 +    public boolean mkdir() {
126.1196 +        throw new SecurityException();
126.1197 +    }
126.1198 +
126.1199 +    /**
126.1200 +     * Creates the directory named by this abstract pathname, including any
126.1201 +     * necessary but nonexistent parent directories.  Note that if this
126.1202 +     * operation fails it may have succeeded in creating some of the necessary
126.1203 +     * parent directories.
126.1204 +     *
126.1205 +     * @return  <code>true</code> if and only if the directory was created,
126.1206 +     *          along with all necessary parent directories; <code>false</code>
126.1207 +     *          otherwise
126.1208 +     *
126.1209 +     * @throws  SecurityException
126.1210 +     *          If a security manager exists and its <code>{@link
126.1211 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
126.1212 +     *          method does not permit verification of the existence of the
126.1213 +     *          named directory and all necessary parent directories; or if
126.1214 +     *          the <code>{@link
126.1215 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1216 +     *          method does not permit the named directory and all necessary
126.1217 +     *          parent directories to be created
126.1218 +     */
126.1219 +    public boolean mkdirs() {
126.1220 +        throw new SecurityException();
126.1221 +    }
126.1222 +
126.1223 +    /**
126.1224 +     * Renames the file denoted by this abstract pathname.
126.1225 +     *
126.1226 +     * <p> Many aspects of the behavior of this method are inherently
126.1227 +     * platform-dependent: The rename operation might not be able to move a
126.1228 +     * file from one filesystem to another, it might not be atomic, and it
126.1229 +     * might not succeed if a file with the destination abstract pathname
126.1230 +     * already exists.  The return value should always be checked to make sure
126.1231 +     * that the rename operation was successful.
126.1232 +     *
126.1233 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
126.1234 +     * java.nio.file.Files#move move} method to move or rename a file in a
126.1235 +     * platform independent manner.
126.1236 +     *
126.1237 +     * @param  dest  The new abstract pathname for the named file
126.1238 +     *
126.1239 +     * @return  <code>true</code> if and only if the renaming succeeded;
126.1240 +     *          <code>false</code> otherwise
126.1241 +     *
126.1242 +     * @throws  SecurityException
126.1243 +     *          If a security manager exists and its <code>{@link
126.1244 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1245 +     *          method denies write access to either the old or new pathnames
126.1246 +     *
126.1247 +     * @throws  NullPointerException
126.1248 +     *          If parameter <code>dest</code> is <code>null</code>
126.1249 +     */
126.1250 +    public boolean renameTo(File dest) {
126.1251 +        throw new SecurityException();
126.1252 +    }
126.1253 +
126.1254 +    /**
126.1255 +     * Sets the last-modified time of the file or directory named by this
126.1256 +     * abstract pathname.
126.1257 +     *
126.1258 +     * <p> All platforms support file-modification times to the nearest second,
126.1259 +     * but some provide more precision.  The argument will be truncated to fit
126.1260 +     * the supported precision.  If the operation succeeds and no intervening
126.1261 +     * operations on the file take place, then the next invocation of the
126.1262 +     * <code>{@link #lastModified}</code> method will return the (possibly
126.1263 +     * truncated) <code>time</code> argument that was passed to this method.
126.1264 +     *
126.1265 +     * @param  time  The new last-modified time, measured in milliseconds since
126.1266 +     *               the epoch (00:00:00 GMT, January 1, 1970)
126.1267 +     *
126.1268 +     * @return <code>true</code> if and only if the operation succeeded;
126.1269 +     *          <code>false</code> otherwise
126.1270 +     *
126.1271 +     * @throws  IllegalArgumentException  If the argument is negative
126.1272 +     *
126.1273 +     * @throws  SecurityException
126.1274 +     *          If a security manager exists and its <code>{@link
126.1275 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1276 +     *          method denies write access to the named file
126.1277 +     *
126.1278 +     * @since 1.2
126.1279 +     */
126.1280 +    public boolean setLastModified(long time) {
126.1281 +        throw new SecurityException();
126.1282 +    }
126.1283 +
126.1284 +    /**
126.1285 +     * Marks the file or directory named by this abstract pathname so that
126.1286 +     * only read operations are allowed.  After invoking this method the file
126.1287 +     * or directory is guaranteed not to change until it is either deleted or
126.1288 +     * marked to allow write access.  Whether or not a read-only file or
126.1289 +     * directory may be deleted depends upon the underlying system.
126.1290 +     *
126.1291 +     * @return <code>true</code> if and only if the operation succeeded;
126.1292 +     *          <code>false</code> otherwise
126.1293 +     *
126.1294 +     * @throws  SecurityException
126.1295 +     *          If a security manager exists and its <code>{@link
126.1296 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1297 +     *          method denies write access to the named file
126.1298 +     *
126.1299 +     * @since 1.2
126.1300 +     */
126.1301 +    public boolean setReadOnly() {
126.1302 +        throw new SecurityException();
126.1303 +    }
126.1304 +
126.1305 +    /**
126.1306 +     * Sets the owner's or everybody's write permission for this abstract
126.1307 +     * pathname.
126.1308 +     *
126.1309 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
126.1310 +     * file attributes including file permissions. This may be used when finer
126.1311 +     * manipulation of file permissions is required.
126.1312 +     *
126.1313 +     * @param   writable
126.1314 +     *          If <code>true</code>, sets the access permission to allow write
126.1315 +     *          operations; if <code>false</code> to disallow write operations
126.1316 +     *
126.1317 +     * @param   ownerOnly
126.1318 +     *          If <code>true</code>, the write permission applies only to the
126.1319 +     *          owner's write permission; otherwise, it applies to everybody.  If
126.1320 +     *          the underlying file system can not distinguish the owner's write
126.1321 +     *          permission from that of others, then the permission will apply to
126.1322 +     *          everybody, regardless of this value.
126.1323 +     *
126.1324 +     * @return  <code>true</code> if and only if the operation succeeded. The
126.1325 +     *          operation will fail if the user does not have permission to change
126.1326 +     *          the access permissions of this abstract pathname.
126.1327 +     *
126.1328 +     * @throws  SecurityException
126.1329 +     *          If a security manager exists and its <code>{@link
126.1330 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1331 +     *          method denies write access to the named file
126.1332 +     *
126.1333 +     * @since 1.6
126.1334 +     */
126.1335 +    public boolean setWritable(boolean writable, boolean ownerOnly) {
126.1336 +        throw new SecurityException();
126.1337 +    }
126.1338 +
126.1339 +    /**
126.1340 +     * A convenience method to set the owner's write permission for this abstract
126.1341 +     * pathname.
126.1342 +     *
126.1343 +     * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt>
126.1344 +     * behaves in exactly the same way as the invocation
126.1345 +     *
126.1346 +     * <pre>
126.1347 +     *     file.setWritable(arg, true) </pre>
126.1348 +     *
126.1349 +     * @param   writable
126.1350 +     *          If <code>true</code>, sets the access permission to allow write
126.1351 +     *          operations; if <code>false</code> to disallow write operations
126.1352 +     *
126.1353 +     * @return  <code>true</code> if and only if the operation succeeded.  The
126.1354 +     *          operation will fail if the user does not have permission to
126.1355 +     *          change the access permissions of this abstract pathname.
126.1356 +     *
126.1357 +     * @throws  SecurityException
126.1358 +     *          If a security manager exists and its <code>{@link
126.1359 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1360 +     *          method denies write access to the file
126.1361 +     *
126.1362 +     * @since 1.6
126.1363 +     */
126.1364 +    public boolean setWritable(boolean writable) {
126.1365 +        return setWritable(writable, true);
126.1366 +    }
126.1367 +
126.1368 +    /**
126.1369 +     * Sets the owner's or everybody's read permission for this abstract
126.1370 +     * pathname.
126.1371 +     *
126.1372 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
126.1373 +     * file attributes including file permissions. This may be used when finer
126.1374 +     * manipulation of file permissions is required.
126.1375 +     *
126.1376 +     * @param   readable
126.1377 +     *          If <code>true</code>, sets the access permission to allow read
126.1378 +     *          operations; if <code>false</code> to disallow read operations
126.1379 +     *
126.1380 +     * @param   ownerOnly
126.1381 +     *          If <code>true</code>, the read permission applies only to the
126.1382 +     *          owner's read permission; otherwise, it applies to everybody.  If
126.1383 +     *          the underlying file system can not distinguish the owner's read
126.1384 +     *          permission from that of others, then the permission will apply to
126.1385 +     *          everybody, regardless of this value.
126.1386 +     *
126.1387 +     * @return  <code>true</code> if and only if the operation succeeded.  The
126.1388 +     *          operation will fail if the user does not have permission to
126.1389 +     *          change the access permissions of this abstract pathname.  If
126.1390 +     *          <code>readable</code> is <code>false</code> and the underlying
126.1391 +     *          file system does not implement a read permission, then the
126.1392 +     *          operation will fail.
126.1393 +     *
126.1394 +     * @throws  SecurityException
126.1395 +     *          If a security manager exists and its <code>{@link
126.1396 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1397 +     *          method denies write access to the file
126.1398 +     *
126.1399 +     * @since 1.6
126.1400 +     */
126.1401 +    public boolean setReadable(boolean readable, boolean ownerOnly) {
126.1402 +        throw new SecurityException();
126.1403 +    }
126.1404 +
126.1405 +    /**
126.1406 +     * A convenience method to set the owner's read permission for this abstract
126.1407 +     * pathname.
126.1408 +     *
126.1409 +     * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
126.1410 +     * behaves in exactly the same way as the invocation
126.1411 +     *
126.1412 +     * <pre>
126.1413 +     *     file.setReadable(arg, true) </pre>
126.1414 +     *
126.1415 +     * @param  readable
126.1416 +     *          If <code>true</code>, sets the access permission to allow read
126.1417 +     *          operations; if <code>false</code> to disallow read operations
126.1418 +     *
126.1419 +     * @return  <code>true</code> if and only if the operation succeeded.  The
126.1420 +     *          operation will fail if the user does not have permission to
126.1421 +     *          change the access permissions of this abstract pathname.  If
126.1422 +     *          <code>readable</code> is <code>false</code> and the underlying
126.1423 +     *          file system does not implement a read permission, then the
126.1424 +     *          operation will fail.
126.1425 +     *
126.1426 +     * @throws  SecurityException
126.1427 +     *          If a security manager exists and its <code>{@link
126.1428 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1429 +     *          method denies write access to the file
126.1430 +     *
126.1431 +     * @since 1.6
126.1432 +     */
126.1433 +    public boolean setReadable(boolean readable) {
126.1434 +        return setReadable(readable, true);
126.1435 +    }
126.1436 +
126.1437 +    /**
126.1438 +     * Sets the owner's or everybody's execute permission for this abstract
126.1439 +     * pathname.
126.1440 +     *
126.1441 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
126.1442 +     * file attributes including file permissions. This may be used when finer
126.1443 +     * manipulation of file permissions is required.
126.1444 +     *
126.1445 +     * @param   executable
126.1446 +     *          If <code>true</code>, sets the access permission to allow execute
126.1447 +     *          operations; if <code>false</code> to disallow execute operations
126.1448 +     *
126.1449 +     * @param   ownerOnly
126.1450 +     *          If <code>true</code>, the execute permission applies only to the
126.1451 +     *          owner's execute permission; otherwise, it applies to everybody.
126.1452 +     *          If the underlying file system can not distinguish the owner's
126.1453 +     *          execute permission from that of others, then the permission will
126.1454 +     *          apply to everybody, regardless of this value.
126.1455 +     *
126.1456 +     * @return  <code>true</code> if and only if the operation succeeded.  The
126.1457 +     *          operation will fail if the user does not have permission to
126.1458 +     *          change the access permissions of this abstract pathname.  If
126.1459 +     *          <code>executable</code> is <code>false</code> and the underlying
126.1460 +     *          file system does not implement an execute permission, then the
126.1461 +     *          operation will fail.
126.1462 +     *
126.1463 +     * @throws  SecurityException
126.1464 +     *          If a security manager exists and its <code>{@link
126.1465 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1466 +     *          method denies write access to the file
126.1467 +     *
126.1468 +     * @since 1.6
126.1469 +     */
126.1470 +    public boolean setExecutable(boolean executable, boolean ownerOnly) {
126.1471 +        throw new SecurityException();
126.1472 +    }
126.1473 +
126.1474 +    /**
126.1475 +     * A convenience method to set the owner's execute permission for this abstract
126.1476 +     * pathname.
126.1477 +     *
126.1478 +     * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
126.1479 +     * behaves in exactly the same way as the invocation
126.1480 +     *
126.1481 +     * <pre>
126.1482 +     *     file.setExecutable(arg, true) </pre>
126.1483 +     *
126.1484 +     * @param   executable
126.1485 +     *          If <code>true</code>, sets the access permission to allow execute
126.1486 +     *          operations; if <code>false</code> to disallow execute operations
126.1487 +     *
126.1488 +     * @return   <code>true</code> if and only if the operation succeeded.  The
126.1489 +     *           operation will fail if the user does not have permission to
126.1490 +     *           change the access permissions of this abstract pathname.  If
126.1491 +     *           <code>executable</code> is <code>false</code> and the underlying
126.1492 +     *           file system does not implement an excute permission, then the
126.1493 +     *           operation will fail.
126.1494 +     *
126.1495 +     * @throws  SecurityException
126.1496 +     *          If a security manager exists and its <code>{@link
126.1497 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1498 +     *          method denies write access to the file
126.1499 +     *
126.1500 +     * @since 1.6
126.1501 +     */
126.1502 +    public boolean setExecutable(boolean executable) {
126.1503 +        return setExecutable(executable, true);
126.1504 +    }
126.1505 +
126.1506 +    /**
126.1507 +     * Tests whether the application can execute the file denoted by this
126.1508 +     * abstract pathname.
126.1509 +     *
126.1510 +     * @return  <code>true</code> if and only if the abstract pathname exists
126.1511 +     *          <em>and</em> the application is allowed to execute the file
126.1512 +     *
126.1513 +     * @throws  SecurityException
126.1514 +     *          If a security manager exists and its <code>{@link
126.1515 +     *          java.lang.SecurityManager#checkExec(java.lang.String)}</code>
126.1516 +     *          method denies execute access to the file
126.1517 +     *
126.1518 +     * @since 1.6
126.1519 +     */
126.1520 +    public boolean canExecute() {
126.1521 +        throw new SecurityException();
126.1522 +    }
126.1523 +
126.1524 +
126.1525 +    /* -- Filesystem interface -- */
126.1526 +
126.1527 +    /**
126.1528 +     * List the available filesystem roots.
126.1529 +     *
126.1530 +     * <p> A particular Java platform may support zero or more
126.1531 +     * hierarchically-organized file systems.  Each file system has a
126.1532 +     * {@code root} directory from which all other files in that file system
126.1533 +     * can be reached.  Windows platforms, for example, have a root directory
126.1534 +     * for each active drive; UNIX platforms have a single root directory,
126.1535 +     * namely {@code "/"}.  The set of available filesystem roots is affected
126.1536 +     * by various system-level operations such as the insertion or ejection of
126.1537 +     * removable media and the disconnecting or unmounting of physical or
126.1538 +     * virtual disk drives.
126.1539 +     *
126.1540 +     * <p> This method returns an array of {@code File} objects that denote the
126.1541 +     * root directories of the available filesystem roots.  It is guaranteed
126.1542 +     * that the canonical pathname of any file physically present on the local
126.1543 +     * machine will begin with one of the roots returned by this method.
126.1544 +     *
126.1545 +     * <p> The canonical pathname of a file that resides on some other machine
126.1546 +     * and is accessed via a remote-filesystem protocol such as SMB or NFS may
126.1547 +     * or may not begin with one of the roots returned by this method.  If the
126.1548 +     * pathname of a remote file is syntactically indistinguishable from the
126.1549 +     * pathname of a local file then it will begin with one of the roots
126.1550 +     * returned by this method.  Thus, for example, {@code File} objects
126.1551 +     * denoting the root directories of the mapped network drives of a Windows
126.1552 +     * platform will be returned by this method, while {@code File} objects
126.1553 +     * containing UNC pathnames will not be returned by this method.
126.1554 +     *
126.1555 +     * <p> Unlike most methods in this class, this method does not throw
126.1556 +     * security exceptions.  If a security manager exists and its {@link
126.1557 +     * SecurityManager#checkRead(String)} method denies read access to a
126.1558 +     * particular root directory, then that directory will not appear in the
126.1559 +     * result.
126.1560 +     *
126.1561 +     * @return  An array of {@code File} objects denoting the available
126.1562 +     *          filesystem roots, or {@code null} if the set of roots could not
126.1563 +     *          be determined.  The array will be empty if there are no
126.1564 +     *          filesystem roots.
126.1565 +     *
126.1566 +     * @since  1.2
126.1567 +     * @see java.nio.file.FileStore
126.1568 +     */
126.1569 +    public static File[] listRoots() {
126.1570 +        throw new SecurityException();
126.1571 +    }
126.1572 +
126.1573 +
126.1574 +    /* -- Disk usage -- */
126.1575 +
126.1576 +    /**
126.1577 +     * Returns the size of the partition <a href="#partName">named</a> by this
126.1578 +     * abstract pathname.
126.1579 +     *
126.1580 +     * @return  The size, in bytes, of the partition or <tt>0L</tt> if this
126.1581 +     *          abstract pathname does not name a partition
126.1582 +     *
126.1583 +     * @throws  SecurityException
126.1584 +     *          If a security manager has been installed and it denies
126.1585 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
126.1586 +     *          or its {@link SecurityManager#checkRead(String)} method denies
126.1587 +     *          read access to the file named by this abstract pathname
126.1588 +     *
126.1589 +     * @since  1.6
126.1590 +     */
126.1591 +    public long getTotalSpace() {
126.1592 +        throw new SecurityException();
126.1593 +    }
126.1594 +
126.1595 +    /**
126.1596 +     * Returns the number of unallocated bytes in the partition <a
126.1597 +     * href="#partName">named</a> by this abstract path name.
126.1598 +     *
126.1599 +     * <p> The returned number of unallocated bytes is a hint, but not
126.1600 +     * a guarantee, that it is possible to use most or any of these
126.1601 +     * bytes.  The number of unallocated bytes is most likely to be
126.1602 +     * accurate immediately after this call.  It is likely to be made
126.1603 +     * inaccurate by any external I/O operations including those made
126.1604 +     * on the system outside of this virtual machine.  This method
126.1605 +     * makes no guarantee that write operations to this file system
126.1606 +     * will succeed.
126.1607 +     *
126.1608 +     * @return  The number of unallocated bytes on the partition <tt>0L</tt>
126.1609 +     *          if the abstract pathname does not name a partition.  This
126.1610 +     *          value will be less than or equal to the total file system size
126.1611 +     *          returned by {@link #getTotalSpace}.
126.1612 +     *
126.1613 +     * @throws  SecurityException
126.1614 +     *          If a security manager has been installed and it denies
126.1615 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
126.1616 +     *          or its {@link SecurityManager#checkRead(String)} method denies
126.1617 +     *          read access to the file named by this abstract pathname
126.1618 +     *
126.1619 +     * @since  1.6
126.1620 +     */
126.1621 +    public long getFreeSpace() {
126.1622 +        throw new SecurityException();
126.1623 +    }
126.1624 +
126.1625 +    /**
126.1626 +     * Returns the number of bytes available to this virtual machine on the
126.1627 +     * partition <a href="#partName">named</a> by this abstract pathname.  When
126.1628 +     * possible, this method checks for write permissions and other operating
126.1629 +     * system restrictions and will therefore usually provide a more accurate
126.1630 +     * estimate of how much new data can actually be written than {@link
126.1631 +     * #getFreeSpace}.
126.1632 +     *
126.1633 +     * <p> The returned number of available bytes is a hint, but not a
126.1634 +     * guarantee, that it is possible to use most or any of these bytes.  The
126.1635 +     * number of unallocated bytes is most likely to be accurate immediately
126.1636 +     * after this call.  It is likely to be made inaccurate by any external
126.1637 +     * I/O operations including those made on the system outside of this
126.1638 +     * virtual machine.  This method makes no guarantee that write operations
126.1639 +     * to this file system will succeed.
126.1640 +     *
126.1641 +     * @return  The number of available bytes on the partition or <tt>0L</tt>
126.1642 +     *          if the abstract pathname does not name a partition.  On
126.1643 +     *          systems where this information is not available, this method
126.1644 +     *          will be equivalent to a call to {@link #getFreeSpace}.
126.1645 +     *
126.1646 +     * @throws  SecurityException
126.1647 +     *          If a security manager has been installed and it denies
126.1648 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
126.1649 +     *          or its {@link SecurityManager#checkRead(String)} method denies
126.1650 +     *          read access to the file named by this abstract pathname
126.1651 +     *
126.1652 +     * @since  1.6
126.1653 +     */
126.1654 +    public long getUsableSpace() {
126.1655 +        throw new SecurityException();
126.1656 +    }
126.1657 +
126.1658 +    /* -- Temporary files -- */
126.1659 +
126.1660 +
126.1661 +    /**
126.1662 +     * <p> Creates a new empty file in the specified directory, using the
126.1663 +     * given prefix and suffix strings to generate its name.  If this method
126.1664 +     * returns successfully then it is guaranteed that:
126.1665 +     *
126.1666 +     * <ol>
126.1667 +     * <li> The file denoted by the returned abstract pathname did not exist
126.1668 +     *      before this method was invoked, and
126.1669 +     * <li> Neither this method nor any of its variants will return the same
126.1670 +     *      abstract pathname again in the current invocation of the virtual
126.1671 +     *      machine.
126.1672 +     * </ol>
126.1673 +     *
126.1674 +     * This method provides only part of a temporary-file facility.  To arrange
126.1675 +     * for a file created by this method to be deleted automatically, use the
126.1676 +     * <code>{@link #deleteOnExit}</code> method.
126.1677 +     *
126.1678 +     * <p> The <code>prefix</code> argument must be at least three characters
126.1679 +     * long.  It is recommended that the prefix be a short, meaningful string
126.1680 +     * such as <code>"hjb"</code> or <code>"mail"</code>.  The
126.1681 +     * <code>suffix</code> argument may be <code>null</code>, in which case the
126.1682 +     * suffix <code>".tmp"</code> will be used.
126.1683 +     *
126.1684 +     * <p> To create the new file, the prefix and the suffix may first be
126.1685 +     * adjusted to fit the limitations of the underlying platform.  If the
126.1686 +     * prefix is too long then it will be truncated, but its first three
126.1687 +     * characters will always be preserved.  If the suffix is too long then it
126.1688 +     * too will be truncated, but if it begins with a period character
126.1689 +     * (<code>'.'</code>) then the period and the first three characters
126.1690 +     * following it will always be preserved.  Once these adjustments have been
126.1691 +     * made the name of the new file will be generated by concatenating the
126.1692 +     * prefix, five or more internally-generated characters, and the suffix.
126.1693 +     *
126.1694 +     * <p> If the <code>directory</code> argument is <code>null</code> then the
126.1695 +     * system-dependent default temporary-file directory will be used.  The
126.1696 +     * default temporary-file directory is specified by the system property
126.1697 +     * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
126.1698 +     * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
126.1699 +     * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>.  A different
126.1700 +     * value may be given to this system property when the Java virtual machine
126.1701 +     * is invoked, but programmatic changes to this property are not guaranteed
126.1702 +     * to have any effect upon the temporary directory used by this method.
126.1703 +     *
126.1704 +     * @param  prefix     The prefix string to be used in generating the file's
126.1705 +     *                    name; must be at least three characters long
126.1706 +     *
126.1707 +     * @param  suffix     The suffix string to be used in generating the file's
126.1708 +     *                    name; may be <code>null</code>, in which case the
126.1709 +     *                    suffix <code>".tmp"</code> will be used
126.1710 +     *
126.1711 +     * @param  directory  The directory in which the file is to be created, or
126.1712 +     *                    <code>null</code> if the default temporary-file
126.1713 +     *                    directory is to be used
126.1714 +     *
126.1715 +     * @return  An abstract pathname denoting a newly-created empty file
126.1716 +     *
126.1717 +     * @throws  IllegalArgumentException
126.1718 +     *          If the <code>prefix</code> argument contains fewer than three
126.1719 +     *          characters
126.1720 +     *
126.1721 +     * @throws  IOException  If a file could not be created
126.1722 +     *
126.1723 +     * @throws  SecurityException
126.1724 +     *          If a security manager exists and its <code>{@link
126.1725 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1726 +     *          method does not allow a file to be created
126.1727 +     *
126.1728 +     * @since 1.2
126.1729 +     */
126.1730 +    public static File createTempFile(String prefix, String suffix,
126.1731 +                                      File directory)
126.1732 +        throws IOException
126.1733 +    {
126.1734 +        throw new SecurityException();
126.1735 +    }
126.1736 +
126.1737 +    /**
126.1738 +     * Creates an empty file in the default temporary-file directory, using
126.1739 +     * the given prefix and suffix to generate its name. Invoking this method
126.1740 +     * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
126.1741 +     * java.lang.String, java.io.File)
126.1742 +     * createTempFile(prefix,&nbsp;suffix,&nbsp;null)}</code>.
126.1743 +     *
126.1744 +     * <p> The {@link
126.1745 +     * java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[])
126.1746 +     * Files.createTempFile} method provides an alternative method to create an
126.1747 +     * empty file in the temporary-file directory. Files created by that method
126.1748 +     * may have more restrictive access permissions to files created by this
126.1749 +     * method and so may be more suited to security-sensitive applications.
126.1750 +     *
126.1751 +     * @param  prefix     The prefix string to be used in generating the file's
126.1752 +     *                    name; must be at least three characters long
126.1753 +     *
126.1754 +     * @param  suffix     The suffix string to be used in generating the file's
126.1755 +     *                    name; may be <code>null</code>, in which case the
126.1756 +     *                    suffix <code>".tmp"</code> will be used
126.1757 +     *
126.1758 +     * @return  An abstract pathname denoting a newly-created empty file
126.1759 +     *
126.1760 +     * @throws  IllegalArgumentException
126.1761 +     *          If the <code>prefix</code> argument contains fewer than three
126.1762 +     *          characters
126.1763 +     *
126.1764 +     * @throws  IOException  If a file could not be created
126.1765 +     *
126.1766 +     * @throws  SecurityException
126.1767 +     *          If a security manager exists and its <code>{@link
126.1768 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
126.1769 +     *          method does not allow a file to be created
126.1770 +     *
126.1771 +     * @since 1.2
126.1772 +     * @see java.nio.file.Files#createTempDirectory(String,FileAttribute[])
126.1773 +     */
126.1774 +    public static File createTempFile(String prefix, String suffix)
126.1775 +        throws IOException
126.1776 +    {
126.1777 +        return createTempFile(prefix, suffix, null);
126.1778 +    }
126.1779 +
126.1780 +    /* -- Basic infrastructure -- */
126.1781 +
126.1782 +    /**
126.1783 +     * Compares two abstract pathnames lexicographically.  The ordering
126.1784 +     * defined by this method depends upon the underlying system.  On UNIX
126.1785 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
126.1786 +     * systems it is not.
126.1787 +     *
126.1788 +     * @param   pathname  The abstract pathname to be compared to this abstract
126.1789 +     *                    pathname
126.1790 +     *
126.1791 +     * @return  Zero if the argument is equal to this abstract pathname, a
126.1792 +     *          value less than zero if this abstract pathname is
126.1793 +     *          lexicographically less than the argument, or a value greater
126.1794 +     *          than zero if this abstract pathname is lexicographically
126.1795 +     *          greater than the argument
126.1796 +     *
126.1797 +     * @since   1.2
126.1798 +     */
126.1799 +    public int compareTo(File pathname) {
126.1800 +        return fs.compare(this, pathname);
126.1801 +    }
126.1802 +
126.1803 +    /**
126.1804 +     * Tests this abstract pathname for equality with the given object.
126.1805 +     * Returns <code>true</code> if and only if the argument is not
126.1806 +     * <code>null</code> and is an abstract pathname that denotes the same file
126.1807 +     * or directory as this abstract pathname.  Whether or not two abstract
126.1808 +     * pathnames are equal depends upon the underlying system.  On UNIX
126.1809 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
126.1810 +     * systems it is not.
126.1811 +     *
126.1812 +     * @param   obj   The object to be compared with this abstract pathname
126.1813 +     *
126.1814 +     * @return  <code>true</code> if and only if the objects are the same;
126.1815 +     *          <code>false</code> otherwise
126.1816 +     */
126.1817 +    public boolean equals(Object obj) {
126.1818 +        if ((obj != null) && (obj instanceof File)) {
126.1819 +            return compareTo((File)obj) == 0;
126.1820 +        }
126.1821 +        return false;
126.1822 +    }
126.1823 +
126.1824 +    /**
126.1825 +     * Computes a hash code for this abstract pathname.  Because equality of
126.1826 +     * abstract pathnames is inherently system-dependent, so is the computation
126.1827 +     * of their hash codes.  On UNIX systems, the hash code of an abstract
126.1828 +     * pathname is equal to the exclusive <em>or</em> of the hash code
126.1829 +     * of its pathname string and the decimal value
126.1830 +     * <code>1234321</code>.  On Microsoft Windows systems, the hash
126.1831 +     * code is equal to the exclusive <em>or</em> of the hash code of
126.1832 +     * its pathname string converted to lower case and the decimal
126.1833 +     * value <code>1234321</code>.  Locale is not taken into account on
126.1834 +     * lowercasing the pathname string.
126.1835 +     *
126.1836 +     * @return  A hash code for this abstract pathname
126.1837 +     */
126.1838 +    public int hashCode() {
126.1839 +        return fs.hashCode(this);
126.1840 +    }
126.1841 +
126.1842 +    /**
126.1843 +     * Returns the pathname string of this abstract pathname.  This is just the
126.1844 +     * string returned by the <code>{@link #getPath}</code> method.
126.1845 +     *
126.1846 +     * @return  The string form of this abstract pathname
126.1847 +     */
126.1848 +    public String toString() {
126.1849 +        return getPath();
126.1850 +    }
126.1851 +
126.1852 +    /**
126.1853 +     * WriteObject is called to save this filename.
126.1854 +     * The separator character is saved also so it can be replaced
126.1855 +     * in case the path is reconstituted on a different host type.
126.1856 +     * <p>
126.1857 +     * @serialData  Default fields followed by separator character.
126.1858 +     */
126.1859 +    private synchronized void writeObject(java.io.ObjectOutputStream s)
126.1860 +        throws IOException
126.1861 +    {
126.1862 +        s.defaultWriteObject();
126.1863 +        s.writeChar(this.separatorChar); // Add the separator character
126.1864 +    }
126.1865 +
126.1866 +    /**
126.1867 +     * readObject is called to restore this filename.
126.1868 +     * The original separator character is read.  If it is different
126.1869 +     * than the separator character on this system, then the old separator
126.1870 +     * is replaced by the local separator.
126.1871 +     */
126.1872 +    private synchronized void readObject(java.io.ObjectInputStream s)
126.1873 +         throws IOException, ClassNotFoundException
126.1874 +    {
126.1875 +        ObjectInputStream.GetField fields = s.readFields();
126.1876 +        String pathField = (String)fields.get("path", null);
126.1877 +        char sep = s.readChar(); // read the previous separator char
126.1878 +        if (sep != separatorChar)
126.1879 +            pathField = pathField.replace(sep, separatorChar);
126.1880 +        this.path = fs.normalize(pathField);
126.1881 +        this.prefixLength = fs.prefixLength(this.path);
126.1882 +    }
126.1883 +
126.1884 +    /** use serialVersionUID from JDK 1.0.2 for interoperability */
126.1885 +    private static final long serialVersionUID = 301077366599181567L;
126.1886 +
126.1887 +    // -- Integration with java.nio.file --
126.1888 +/*
126.1889 +    private volatile transient Path filePath;
126.1890 +
126.1891 +    /**
126.1892 +     * Returns a {@link Path java.nio.file.Path} object constructed from the
126.1893 +     * this abstract path. The resulting {@code Path} is associated with the
126.1894 +     * {@link java.nio.file.FileSystems#getDefault default-filesystem}.
126.1895 +     *
126.1896 +     * <p> The first invocation of this method works as if invoking it were
126.1897 +     * equivalent to evaluating the expression:
126.1898 +     * <blockquote><pre>
126.1899 +     * {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link
126.1900 +     * java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}());
126.1901 +     * </pre></blockquote>
126.1902 +     * Subsequent invocations of this method return the same {@code Path}.
126.1903 +     *
126.1904 +     * <p> If this abstract pathname is the empty abstract pathname then this
126.1905 +     * method returns a {@code Path} that may be used to access the current
126.1906 +     * user directory.
126.1907 +     *
126.1908 +     * @return  a {@code Path} constructed from this abstract path
126.1909 +     *
126.1910 +     * @throws  java.nio.file.InvalidPathException
126.1911 +     *          if a {@code Path} object cannot be constructed from the abstract
126.1912 +     *          path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
126.1913 +     *
126.1914 +     * @since   1.7
126.1915 +     * @see Path#toFile
126.1916 +     */
126.1917 +//    public Path toPath() {
126.1918 +//        Path result = filePath;
126.1919 +//        if (result == null) {
126.1920 +//            synchronized (this) {
126.1921 +//                result = filePath;
126.1922 +//                if (result == null) {
126.1923 +//                    result = FileSystems.getDefault().getPath(path);
126.1924 +//                    filePath = result;
126.1925 +//                }
126.1926 +//            }
126.1927 +//        }
126.1928 +//        return result;
126.1929 +//    }
126.1930 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/rt/emul/compact/src/main/java/java/io/FileDescriptor.java	Wed Apr 30 15:04:10 2014 +0200
   127.3 @@ -0,0 +1,146 @@
   127.4 +/*
   127.5 + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
   127.6 + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
   127.7 + *
   127.8 + *
   127.9 + *
  127.10 + *
  127.11 + *
  127.12 + *
  127.13 + *
  127.14 + *
  127.15 + *
  127.16 + *
  127.17 + *
  127.18 + *
  127.19 + *
  127.20 + *
  127.21 + *
  127.22 + *
  127.23 + *
  127.24 + *
  127.25 + *
  127.26 + *
  127.27 + */
  127.28 +
  127.29 +package java.io;
  127.30 +
  127.31 +import java.util.concurrent.atomic.AtomicInteger;
  127.32 +
  127.33 +/**
  127.34 + * Instances of the file descriptor class serve as an opaque handle
  127.35 + * to the underlying machine-specific structure representing an open
  127.36 + * file, an open socket, or another source or sink of bytes. The
  127.37 + * main practical use for a file descriptor is to create a
  127.38 + * <code>FileInputStream</code> or <code>FileOutputStream</code> to
  127.39 + * contain it.
  127.40 + * <p>
  127.41 + * Applications should not create their own file descriptors.
  127.42 + *
  127.43 + * @author  Pavani Diwanji
  127.44 + * @see     java.io.FileInputStream
  127.45 + * @see     java.io.FileOutputStream
  127.46 + * @since   JDK1.0
  127.47 + */
  127.48 +public final class FileDescriptor {
  127.49 +
  127.50 +    private int fd;
  127.51 +
  127.52 +    /**
  127.53 +     * A counter for tracking the FIS/FOS/RAF instances that
  127.54 +     * use this FileDescriptor. The FIS/FOS.finalize() will not release
  127.55 +     * the FileDescriptor if it is still under user by a stream.
  127.56 +     */
  127.57 +    private AtomicInteger useCount;
  127.58 +
  127.59 +    /**
  127.60 +     * Constructs an (invalid) FileDescriptor
  127.61 +     * object.
  127.62 +     */
  127.63 +    public /**/ FileDescriptor() {
  127.64 +        fd = -1;
  127.65 +        useCount = new AtomicInteger();
  127.66 +    }
  127.67 +
  127.68 +    private /* */ FileDescriptor(int fd) {
  127.69 +        this.fd = fd;
  127.70 +        useCount = new AtomicInteger();
  127.71 +    }
  127.72 +
  127.73 +    /**
  127.74 +     * A handle to the standard input stream. Usually, this file
  127.75 +     * descriptor is not used directly, but rather via the input stream
  127.76 +     * known as <code>System.in</code>.
  127.77 +     *
  127.78 +     * @see     java.lang.System#in
  127.79 +     */
  127.80 +    public static final FileDescriptor in = new FileDescriptor(0);
  127.81 +
  127.82 +    /**
  127.83 +     * A handle to the standard output stream. Usually, this file
  127.84 +     * descriptor is not used directly, but rather via the output stream
  127.85 +     * known as <code>System.out</code>.
  127.86 +     * @see     java.lang.System#out
  127.87 +     */
  127.88 +    public static final FileDescriptor out = new FileDescriptor(1);
  127.89 +
  127.90 +    /**
  127.91 +     * A handle to the standard error stream. Usually, this file
  127.92 +     * descriptor is not used directly, but rather via the output stream
  127.93 +     * known as <code>System.err</code>.
  127.94 +     *
  127.95 +     * @see     java.lang.System#err
  127.96 +     */
  127.97 +    public static final FileDescriptor err = new FileDescriptor(2);
  127.98 +
  127.99 +    /**
 127.100 +     * Tests if this file descriptor object is valid.
 127.101 +     *
 127.102 +     * @return  <code>true</code> if the file descriptor object represents a
 127.103 +     *          valid, open file, socket, or other active I/O connection;
 127.104 +     *          <code>false</code> otherwise.
 127.105 +     */
 127.106 +    public boolean valid() {
 127.107 +        return fd != -1;
 127.108 +    }
 127.109 +
 127.110 +    /**
 127.111 +     * Force all system buffers to synchronize with the underlying
 127.112 +     * device.  This method returns after all modified data and
 127.113 +     * attributes of this FileDescriptor have been written to the
 127.114 +     * relevant device(s).  In particular, if this FileDescriptor
 127.115 +     * refers to a physical storage medium, such as a file in a file
 127.116 +     * system, sync will not return until all in-memory modified copies
 127.117 +     * of buffers associated with this FileDescriptor have been
 127.118 +     * written to the physical medium.
 127.119 +     *
 127.120 +     * sync is meant to be used by code that requires physical
 127.121 +     * storage (such as a file) to be in a known state  For
 127.122 +     * example, a class that provided a simple transaction facility
 127.123 +     * might use sync to ensure that all changes to a file caused
 127.124 +     * by a given transaction were recorded on a storage medium.
 127.125 +     *
 127.126 +     * sync only affects buffers downstream of this FileDescriptor.  If
 127.127 +     * any in-memory buffering is being done by the application (for
 127.128 +     * example, by a BufferedOutputStream object), those buffers must
 127.129 +     * be flushed into the FileDescriptor (for example, by invoking
 127.130 +     * OutputStream.flush) before that data will be affected by sync.
 127.131 +     *
 127.132 +     * @exception SyncFailedException
 127.133 +     *        Thrown when the buffers cannot be flushed,
 127.134 +     *        or because the system cannot guarantee that all the
 127.135 +     *        buffers have been synchronized with physical media.
 127.136 +     * @since     JDK1.1
 127.137 +     */
 127.138 +    public native void sync() throws SyncFailedException;
 127.139 +
 127.140 +    // package private methods used by FIS, FOS and RAF
 127.141 +
 127.142 +    int incrementAndGetUseCount() {
 127.143 +        return useCount.incrementAndGet();
 127.144 +    }
 127.145 +
 127.146 +    int decrementAndGetUseCount() {
 127.147 +        return useCount.decrementAndGet();
 127.148 +    }
 127.149 +}
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/rt/emul/compact/src/main/java/java/io/FileFilter.java	Wed Apr 30 15:04:10 2014 +0200
   128.3 @@ -0,0 +1,50 @@
   128.4 +/*
   128.5 + * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
   128.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   128.7 + *
   128.8 + * This code is free software; you can redistribute it and/or modify it
   128.9 + * under the terms of the GNU General Public License version 2 only, as
  128.10 + * published by the Free Software Foundation.  Oracle designates this
  128.11 + * particular file as subject to the "Classpath" exception as provided
  128.12 + * by Oracle in the LICENSE file that accompanied this code.
  128.13 + *
  128.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  128.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  128.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  128.17 + * version 2 for more details (a copy is included in the LICENSE file that
  128.18 + * accompanied this code).
  128.19 + *
  128.20 + * You should have received a copy of the GNU General Public License version
  128.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  128.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  128.23 + *
  128.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  128.25 + * or visit www.oracle.com if you need additional information or have any
  128.26 + * questions.
  128.27 + */
  128.28 +
  128.29 +package java.io;
  128.30 +
  128.31 +
  128.32 +/**
  128.33 + * A filter for abstract pathnames.
  128.34 + *
  128.35 + * <p> Instances of this interface may be passed to the <code>{@link
  128.36 + * File#listFiles(java.io.FileFilter) listFiles(FileFilter)}</code> method
  128.37 + * of the <code>{@link java.io.File}</code> class.
  128.38 + *
  128.39 + * @since 1.2
  128.40 + */
  128.41 +public interface FileFilter {
  128.42 +
  128.43 +    /**
  128.44 +     * Tests whether or not the specified abstract pathname should be
  128.45 +     * included in a pathname list.
  128.46 +     *
  128.47 +     * @param  pathname  The abstract pathname to be tested
  128.48 +     * @return  <code>true</code> if and only if <code>pathname</code>
  128.49 +     *          should be included
  128.50 +     */
  128.51 +    boolean accept(File pathname);
  128.52 +
  128.53 +}
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/rt/emul/compact/src/main/java/java/io/FileInputStream.java	Wed Apr 30 15:04:10 2014 +0200
   129.3 @@ -0,0 +1,382 @@
   129.4 +/*
   129.5 + * Copyright (c) 1994, 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 +/**
  129.34 + * A <code>FileInputStream</code> obtains input bytes
  129.35 + * from a file in a file system. What files
  129.36 + * are  available depends on the host environment.
  129.37 + *
  129.38 + * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
  129.39 + * such as image data. For reading streams of characters, consider using
  129.40 + * <code>FileReader</code>.
  129.41 + *
  129.42 + * @author  Arthur van Hoff
  129.43 + * @see     java.io.File
  129.44 + * @see     java.io.FileDescriptor
  129.45 + * @see     java.io.FileOutputStream
  129.46 + * @see     java.nio.file.Files#newInputStream
  129.47 + * @since   JDK1.0
  129.48 + */
  129.49 +public
  129.50 +class FileInputStream extends InputStream
  129.51 +{
  129.52 +    /* File Descriptor - handle to the open file */
  129.53 +    private final FileDescriptor fd;
  129.54 +
  129.55 +//    private FileChannel channel = null;
  129.56 +
  129.57 +    private final Object closeLock = new Object();
  129.58 +    private volatile boolean closed = false;
  129.59 +
  129.60 +    private static final ThreadLocal<Boolean> runningFinalize =
  129.61 +        new ThreadLocal<>();
  129.62 +
  129.63 +    private static boolean isRunningFinalize() {
  129.64 +        Boolean val;
  129.65 +        if ((val = runningFinalize.get()) != null)
  129.66 +            return val.booleanValue();
  129.67 +        return false;
  129.68 +    }
  129.69 +
  129.70 +    /**
  129.71 +     * Creates a <code>FileInputStream</code> by
  129.72 +     * opening a connection to an actual file,
  129.73 +     * the file named by the path name <code>name</code>
  129.74 +     * in the file system.  A new <code>FileDescriptor</code>
  129.75 +     * object is created to represent this file
  129.76 +     * connection.
  129.77 +     * <p>
  129.78 +     * First, if there is a security
  129.79 +     * manager, its <code>checkRead</code> method
  129.80 +     * is called with the <code>name</code> argument
  129.81 +     * as its argument.
  129.82 +     * <p>
  129.83 +     * If the named file does not exist, is a directory rather than a regular
  129.84 +     * file, or for some other reason cannot be opened for reading then a
  129.85 +     * <code>FileNotFoundException</code> is thrown.
  129.86 +     *
  129.87 +     * @param      name   the system-dependent file name.
  129.88 +     * @exception  FileNotFoundException  if the file does not exist,
  129.89 +     *                   is a directory rather than a regular file,
  129.90 +     *                   or for some other reason cannot be opened for
  129.91 +     *                   reading.
  129.92 +     * @exception  SecurityException      if a security manager exists and its
  129.93 +     *               <code>checkRead</code> method denies read access
  129.94 +     *               to the file.
  129.95 +     * @see        java.lang.SecurityManager#checkRead(java.lang.String)
  129.96 +     */
  129.97 +    public FileInputStream(String name) throws FileNotFoundException {
  129.98 +        this(name != null ? new File(name) : null);
  129.99 +    }
 129.100 +
 129.101 +    /**
 129.102 +     * Creates a <code>FileInputStream</code> by
 129.103 +     * opening a connection to an actual file,
 129.104 +     * the file named by the <code>File</code>
 129.105 +     * object <code>file</code> in the file system.
 129.106 +     * A new <code>FileDescriptor</code> object
 129.107 +     * is created to represent this file connection.
 129.108 +     * <p>
 129.109 +     * First, if there is a security manager,
 129.110 +     * its <code>checkRead</code> method  is called
 129.111 +     * with the path represented by the <code>file</code>
 129.112 +     * argument as its argument.
 129.113 +     * <p>
 129.114 +     * If the named file does not exist, is a directory rather than a regular
 129.115 +     * file, or for some other reason cannot be opened for reading then a
 129.116 +     * <code>FileNotFoundException</code> is thrown.
 129.117 +     *
 129.118 +     * @param      file   the file to be opened for reading.
 129.119 +     * @exception  FileNotFoundException  if the file does not exist,
 129.120 +     *                   is a directory rather than a regular file,
 129.121 +     *                   or for some other reason cannot be opened for
 129.122 +     *                   reading.
 129.123 +     * @exception  SecurityException      if a security manager exists and its
 129.124 +     *               <code>checkRead</code> method denies read access to the file.
 129.125 +     * @see        java.io.File#getPath()
 129.126 +     * @see        java.lang.SecurityManager#checkRead(java.lang.String)
 129.127 +     */
 129.128 +    public FileInputStream(File file) throws FileNotFoundException {
 129.129 +        throw new SecurityException();
 129.130 +    }
 129.131 +
 129.132 +    /**
 129.133 +     * Creates a <code>FileInputStream</code> by using the file descriptor
 129.134 +     * <code>fdObj</code>, which represents an existing connection to an
 129.135 +     * actual file in the file system.
 129.136 +     * <p>
 129.137 +     * If there is a security manager, its <code>checkRead</code> method is
 129.138 +     * called with the file descriptor <code>fdObj</code> as its argument to
 129.139 +     * see if it's ok to read the file descriptor. If read access is denied
 129.140 +     * to the file descriptor a <code>SecurityException</code> is thrown.
 129.141 +     * <p>
 129.142 +     * If <code>fdObj</code> is null then a <code>NullPointerException</code>
 129.143 +     * is thrown.
 129.144 +     * <p>
 129.145 +     * This constructor does not throw an exception if <code>fdObj</code>
 129.146 +     * is {@link java.io.FileDescriptor#valid() invalid}.
 129.147 +     * However, if the methods are invoked on the resulting stream to attempt
 129.148 +     * I/O on the stream, an <code>IOException</code> is thrown.
 129.149 +     *
 129.150 +     * @param      fdObj   the file descriptor to be opened for reading.
 129.151 +     * @throws     SecurityException      if a security manager exists and its
 129.152 +     *                 <code>checkRead</code> method denies read access to the
 129.153 +     *                 file descriptor.
 129.154 +     * @see        SecurityManager#checkRead(java.io.FileDescriptor)
 129.155 +     */
 129.156 +    public FileInputStream(FileDescriptor fdObj) {
 129.157 +        throw new SecurityException();
 129.158 +    }
 129.159 +
 129.160 +    /**
 129.161 +     * Opens the specified file for reading.
 129.162 +     * @param name the name of the file
 129.163 +     */
 129.164 +    private native void open(String name) throws FileNotFoundException;
 129.165 +
 129.166 +    /**
 129.167 +     * Reads a byte of data from this input stream. This method blocks
 129.168 +     * if no input is yet available.
 129.169 +     *
 129.170 +     * @return     the next byte of data, or <code>-1</code> if the end of the
 129.171 +     *             file is reached.
 129.172 +     * @exception  IOException  if an I/O error occurs.
 129.173 +     */
 129.174 +    public native int read() throws IOException;
 129.175 +
 129.176 +    /**
 129.177 +     * Reads a subarray as a sequence of bytes.
 129.178 +     * @param b the data to be written
 129.179 +     * @param off the start offset in the data
 129.180 +     * @param len the number of bytes that are written
 129.181 +     * @exception IOException If an I/O error has occurred.
 129.182 +     */
 129.183 +    private native int readBytes(byte b[], int off, int len) throws IOException;
 129.184 +
 129.185 +    /**
 129.186 +     * Reads up to <code>b.length</code> bytes of data from this input
 129.187 +     * stream into an array of bytes. This method blocks until some input
 129.188 +     * is available.
 129.189 +     *
 129.190 +     * @param      b   the buffer into which the data is read.
 129.191 +     * @return     the total number of bytes read into the buffer, or
 129.192 +     *             <code>-1</code> if there is no more data because the end of
 129.193 +     *             the file has been reached.
 129.194 +     * @exception  IOException  if an I/O error occurs.
 129.195 +     */
 129.196 +    public int read(byte b[]) throws IOException {
 129.197 +        return readBytes(b, 0, b.length);
 129.198 +    }
 129.199 +
 129.200 +    /**
 129.201 +     * Reads up to <code>len</code> bytes of data from this input stream
 129.202 +     * into an array of bytes. If <code>len</code> is not zero, the method
 129.203 +     * blocks until some input is available; otherwise, no
 129.204 +     * bytes are read and <code>0</code> is returned.
 129.205 +     *
 129.206 +     * @param      b     the buffer into which the data is read.
 129.207 +     * @param      off   the start offset in the destination array <code>b</code>
 129.208 +     * @param      len   the maximum number of bytes read.
 129.209 +     * @return     the total number of bytes read into the buffer, or
 129.210 +     *             <code>-1</code> if there is no more data because the end of
 129.211 +     *             the file has been reached.
 129.212 +     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
 129.213 +     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
 129.214 +     * <code>len</code> is negative, or <code>len</code> is greater than
 129.215 +     * <code>b.length - off</code>
 129.216 +     * @exception  IOException  if an I/O error occurs.
 129.217 +     */
 129.218 +    public int read(byte b[], int off, int len) throws IOException {
 129.219 +        return readBytes(b, off, len);
 129.220 +    }
 129.221 +
 129.222 +    /**
 129.223 +     * Skips over and discards <code>n</code> bytes of data from the
 129.224 +     * input stream.
 129.225 +     *
 129.226 +     * <p>The <code>skip</code> method may, for a variety of
 129.227 +     * reasons, end up skipping over some smaller number of bytes,
 129.228 +     * possibly <code>0</code>. If <code>n</code> is negative, an
 129.229 +     * <code>IOException</code> is thrown, even though the <code>skip</code>
 129.230 +     * method of the {@link InputStream} superclass does nothing in this case.
 129.231 +     * The actual number of bytes skipped is returned.
 129.232 +     *
 129.233 +     * <p>This method may skip more bytes than are remaining in the backing
 129.234 +     * file. This produces no exception and the number of bytes skipped
 129.235 +     * may include some number of bytes that were beyond the EOF of the
 129.236 +     * backing file. Attempting to read from the stream after skipping past
 129.237 +     * the end will result in -1 indicating the end of the file.
 129.238 +     *
 129.239 +     * @param      n   the number of bytes to be skipped.
 129.240 +     * @return     the actual number of bytes skipped.
 129.241 +     * @exception  IOException  if n is negative, if the stream does not
 129.242 +     *             support seek, or if an I/O error occurs.
 129.243 +     */
 129.244 +    public native long skip(long n) throws IOException;
 129.245 +
 129.246 +    /**
 129.247 +     * Returns an estimate of the number of remaining bytes that can be read (or
 129.248 +     * skipped over) from this input stream without blocking by the next
 129.249 +     * invocation of a method for this input stream. The next invocation might be
 129.250 +     * the same thread or another thread.  A single read or skip of this
 129.251 +     * many bytes will not block, but may read or skip fewer bytes.
 129.252 +     *
 129.253 +     * <p> In some cases, a non-blocking read (or skip) may appear to be
 129.254 +     * blocked when it is merely slow, for example when reading large
 129.255 +     * files over slow networks.
 129.256 +     *
 129.257 +     * @return     an estimate of the number of remaining bytes that can be read
 129.258 +     *             (or skipped over) from this input stream without blocking.
 129.259 +     * @exception  IOException  if this file input stream has been closed by calling
 129.260 +     *             {@code close} or an I/O error occurs.
 129.261 +     */
 129.262 +    public native int available() throws IOException;
 129.263 +
 129.264 +    /**
 129.265 +     * Closes this file input stream and releases any system resources
 129.266 +     * associated with the stream.
 129.267 +     *
 129.268 +     * <p> If this stream has an associated channel then the channel is closed
 129.269 +     * as well.
 129.270 +     *
 129.271 +     * @exception  IOException  if an I/O error occurs.
 129.272 +     *
 129.273 +     * @revised 1.4
 129.274 +     * @spec JSR-51
 129.275 +     */
 129.276 +    public void close() throws IOException {
 129.277 +        synchronized (closeLock) {
 129.278 +            if (closed) {
 129.279 +                return;
 129.280 +            }
 129.281 +            closed = true;
 129.282 +        }
 129.283 +//        if (channel != null) {
 129.284 +//            /*
 129.285 +//             * Decrement the FD use count associated with the channel
 129.286 +//             * The use count is incremented whenever a new channel
 129.287 +//             * is obtained from this stream.
 129.288 +//             */
 129.289 +//           fd.decrementAndGetUseCount();
 129.290 +//           channel.close();
 129.291 +//        }
 129.292 +
 129.293 +        /*
 129.294 +         * Decrement the FD use count associated with this stream
 129.295 +         */
 129.296 +        int useCount = fd.decrementAndGetUseCount();
 129.297 +
 129.298 +        /*
 129.299 +         * If FileDescriptor is still in use by another stream, the finalizer
 129.300 +         * will not close it.
 129.301 +         */
 129.302 +        if ((useCount <= 0) || !isRunningFinalize()) {
 129.303 +            close0();
 129.304 +        }
 129.305 +    }
 129.306 +
 129.307 +    /**
 129.308 +     * Returns the <code>FileDescriptor</code>
 129.309 +     * object  that represents the connection to
 129.310 +     * the actual file in the file system being
 129.311 +     * used by this <code>FileInputStream</code>.
 129.312 +     *
 129.313 +     * @return     the file descriptor object associated with this stream.
 129.314 +     * @exception  IOException  if an I/O error occurs.
 129.315 +     * @see        java.io.FileDescriptor
 129.316 +     */
 129.317 +    public final FileDescriptor getFD() throws IOException {
 129.318 +        if (fd != null) return fd;
 129.319 +        throw new IOException();
 129.320 +    }
 129.321 +
 129.322 +    /**
 129.323 +     * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 129.324 +     * object associated with this file input stream.
 129.325 +     *
 129.326 +     * <p> The initial {@link java.nio.channels.FileChannel#position()
 129.327 +     * </code>position<code>} of the returned channel will be equal to the
 129.328 +     * number of bytes read from the file so far.  Reading bytes from this
 129.329 +     * stream will increment the channel's position.  Changing the channel's
 129.330 +     * position, either explicitly or by reading, will change this stream's
 129.331 +     * file position.
 129.332 +     *
 129.333 +     * @return  the file channel associated with this file input stream
 129.334 +     *
 129.335 +     * @since 1.4
 129.336 +     * @spec JSR-51
 129.337 +     */
 129.338 +//    public FileChannel getChannel() {
 129.339 +//        synchronized (this) {
 129.340 +//            if (channel == null) {
 129.341 +//                channel = FileChannelImpl.open(fd, true, false, this);
 129.342 +//
 129.343 +//                /*
 129.344 +//                 * Increment fd's use count. Invoking the channel's close()
 129.345 +//                 * method will result in decrementing the use count set for
 129.346 +//                 * the channel.
 129.347 +//                 */
 129.348 +//                fd.incrementAndGetUseCount();
 129.349 +//            }
 129.350 +//            return channel;
 129.351 +//        }
 129.352 +//    }
 129.353 +
 129.354 +    private static native void initIDs();
 129.355 +
 129.356 +    private native void close0() throws IOException;
 129.357 +
 129.358 +    static {
 129.359 +        initIDs();
 129.360 +    }
 129.361 +
 129.362 +    /**
 129.363 +     * Ensures that the <code>close</code> method of this file input stream is
 129.364 +     * called when there are no more references to it.
 129.365 +     *
 129.366 +     * @exception  IOException  if an I/O error occurs.
 129.367 +     * @see        java.io.FileInputStream#close()
 129.368 +     */
 129.369 +    protected void finalize() throws IOException {
 129.370 +        if ((fd != null) &&  (fd != FileDescriptor.in)) {
 129.371 +
 129.372 +            /*
 129.373 +             * Finalizer should not release the FileDescriptor if another
 129.374 +             * stream is still using it. If the user directly invokes
 129.375 +             * close() then the FileDescriptor is also released.
 129.376 +             */
 129.377 +            runningFinalize.set(Boolean.TRUE);
 129.378 +            try {
 129.379 +                close();
 129.380 +            } finally {
 129.381 +                runningFinalize.set(Boolean.FALSE);
 129.382 +            }
 129.383 +        }
 129.384 +    }
 129.385 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/rt/emul/compact/src/main/java/java/io/FileNotFoundException.java	Wed Apr 30 15:04:10 2014 +0200
   130.3 @@ -0,0 +1,82 @@
   130.4 +/*
   130.5 + * Copyright (c) 1994, 2008, 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 +
  130.32 +/**
  130.33 + * Signals that an attempt to open the file denoted by a specified pathname
  130.34 + * has failed.
  130.35 + *
  130.36 + * <p> This exception will be thrown by the {@link FileInputStream}, {@link
  130.37 + * FileOutputStream}, and {@link RandomAccessFile} constructors when a file
  130.38 + * with the specified pathname does not exist.  It will also be thrown by these
  130.39 + * constructors if the file does exist but for some reason is inaccessible, for
  130.40 + * example when an attempt is made to open a read-only file for writing.
  130.41 + *
  130.42 + * @author  unascribed
  130.43 + * @since   JDK1.0
  130.44 + */
  130.45 +
  130.46 +public class FileNotFoundException extends IOException {
  130.47 +    private static final long serialVersionUID = -897856973823710492L;
  130.48 +
  130.49 +    /**
  130.50 +     * Constructs a <code>FileNotFoundException</code> with
  130.51 +     * <code>null</code> as its error detail message.
  130.52 +     */
  130.53 +    public FileNotFoundException() {
  130.54 +        super();
  130.55 +    }
  130.56 +
  130.57 +    /**
  130.58 +     * Constructs a <code>FileNotFoundException</code> with the
  130.59 +     * specified detail message. The string <code>s</code> can be
  130.60 +     * retrieved later by the
  130.61 +     * <code>{@link java.lang.Throwable#getMessage}</code>
  130.62 +     * method of class <code>java.lang.Throwable</code>.
  130.63 +     *
  130.64 +     * @param   s   the detail message.
  130.65 +     */
  130.66 +    public FileNotFoundException(String s) {
  130.67 +        super(s);
  130.68 +    }
  130.69 +
  130.70 +    /**
  130.71 +     * Constructs a <code>FileNotFoundException</code> with a detail message
  130.72 +     * consisting of the given pathname string followed by the given reason
  130.73 +     * string.  If the <code>reason</code> argument is <code>null</code> then
  130.74 +     * it will be omitted.  This private constructor is invoked only by native
  130.75 +     * I/O methods.
  130.76 +     *
  130.77 +     * @since 1.2
  130.78 +     */
  130.79 +    private FileNotFoundException(String path, String reason) {
  130.80 +        super(path + ((reason == null)
  130.81 +                      ? ""
  130.82 +                      : " (" + reason + ")"));
  130.83 +    }
  130.84 +
  130.85 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/rt/emul/compact/src/main/java/java/io/FileOutputStream.java	Wed Apr 30 15:04:10 2014 +0200
   131.3 @@ -0,0 +1,422 @@
   131.4 +/*
   131.5 + * Copyright (c) 1994, 2011, 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 +/**
  131.34 + * A file output stream is an output stream for writing data to a
  131.35 + * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
  131.36 + * a file is available or may be created depends upon the underlying
  131.37 + * platform.  Some platforms, in particular, allow a file to be opened
  131.38 + * for writing by only one <tt>FileOutputStream</tt> (or other
  131.39 + * file-writing object) at a time.  In such situations the constructors in
  131.40 + * this class will fail if the file involved is already open.
  131.41 + *
  131.42 + * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
  131.43 + * such as image data. For writing streams of characters, consider using
  131.44 + * <code>FileWriter</code>.
  131.45 + *
  131.46 + * @author  Arthur van Hoff
  131.47 + * @see     java.io.File
  131.48 + * @see     java.io.FileDescriptor
  131.49 + * @see     java.io.FileInputStream
  131.50 + * @see     java.nio.file.Files#newOutputStream
  131.51 + * @since   JDK1.0
  131.52 + */
  131.53 +public
  131.54 +class FileOutputStream extends OutputStream
  131.55 +{
  131.56 +    /**
  131.57 +     * The system dependent file descriptor.
  131.58 +     */
  131.59 +    private final FileDescriptor fd;
  131.60 +
  131.61 +    /**
  131.62 +     * True if the file is opened for append.
  131.63 +     */
  131.64 +    private final boolean append;
  131.65 +
  131.66 +    /**
  131.67 +     * The associated channel, initalized lazily.
  131.68 +     */
  131.69 +//    private FileChannel channel;
  131.70 +
  131.71 +    private final Object closeLock = new Object();
  131.72 +    private volatile boolean closed = false;
  131.73 +    private static final ThreadLocal<Boolean> runningFinalize =
  131.74 +        new ThreadLocal<>();
  131.75 +
  131.76 +    private static boolean isRunningFinalize() {
  131.77 +        Boolean val;
  131.78 +        if ((val = runningFinalize.get()) != null)
  131.79 +            return val.booleanValue();
  131.80 +        return false;
  131.81 +    }
  131.82 +
  131.83 +    /**
  131.84 +     * Creates a file output stream to write to the file with the
  131.85 +     * specified name. A new <code>FileDescriptor</code> object is
  131.86 +     * created to represent this file connection.
  131.87 +     * <p>
  131.88 +     * First, if there is a security manager, its <code>checkWrite</code>
  131.89 +     * method is called with <code>name</code> as its argument.
  131.90 +     * <p>
  131.91 +     * If the file exists but is a directory rather than a regular file, does
  131.92 +     * not exist but cannot be created, or cannot be opened for any other
  131.93 +     * reason then a <code>FileNotFoundException</code> is thrown.
  131.94 +     *
  131.95 +     * @param      name   the system-dependent filename
  131.96 +     * @exception  FileNotFoundException  if the file exists but is a directory
  131.97 +     *                   rather than a regular file, does not exist but cannot
  131.98 +     *                   be created, or cannot be opened for any other reason
  131.99 +     * @exception  SecurityException  if a security manager exists and its
 131.100 +     *               <code>checkWrite</code> method denies write access
 131.101 +     *               to the file.
 131.102 +     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 131.103 +     */
 131.104 +    public FileOutputStream(String name) throws FileNotFoundException {
 131.105 +        this(name != null ? new File(name) : null, false);
 131.106 +    }
 131.107 +
 131.108 +    /**
 131.109 +     * Creates a file output stream to write to the file with the specified
 131.110 +     * name.  If the second argument is <code>true</code>, then
 131.111 +     * bytes will be written to the end of the file rather than the beginning.
 131.112 +     * A new <code>FileDescriptor</code> object is created to represent this
 131.113 +     * file connection.
 131.114 +     * <p>
 131.115 +     * First, if there is a security manager, its <code>checkWrite</code>
 131.116 +     * method is called with <code>name</code> as its argument.
 131.117 +     * <p>
 131.118 +     * If the file exists but is a directory rather than a regular file, does
 131.119 +     * not exist but cannot be created, or cannot be opened for any other
 131.120 +     * reason then a <code>FileNotFoundException</code> is thrown.
 131.121 +     *
 131.122 +     * @param     name        the system-dependent file name
 131.123 +     * @param     append      if <code>true</code>, then bytes will be written
 131.124 +     *                   to the end of the file rather than the beginning
 131.125 +     * @exception  FileNotFoundException  if the file exists but is a directory
 131.126 +     *                   rather than a regular file, does not exist but cannot
 131.127 +     *                   be created, or cannot be opened for any other reason.
 131.128 +     * @exception  SecurityException  if a security manager exists and its
 131.129 +     *               <code>checkWrite</code> method denies write access
 131.130 +     *               to the file.
 131.131 +     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 131.132 +     * @since     JDK1.1
 131.133 +     */
 131.134 +    public FileOutputStream(String name, boolean append)
 131.135 +        throws FileNotFoundException
 131.136 +    {
 131.137 +        this(name != null ? new File(name) : null, append);
 131.138 +    }
 131.139 +
 131.140 +    /**
 131.141 +     * Creates a file output stream to write to the file represented by
 131.142 +     * the specified <code>File</code> object. A new
 131.143 +     * <code>FileDescriptor</code> object is created to represent this
 131.144 +     * file connection.
 131.145 +     * <p>
 131.146 +     * First, if there is a security manager, its <code>checkWrite</code>
 131.147 +     * method is called with the path represented by the <code>file</code>
 131.148 +     * argument as its argument.
 131.149 +     * <p>
 131.150 +     * If the file exists but is a directory rather than a regular file, does
 131.151 +     * not exist but cannot be created, or cannot be opened for any other
 131.152 +     * reason then a <code>FileNotFoundException</code> is thrown.
 131.153 +     *
 131.154 +     * @param      file               the file to be opened for writing.
 131.155 +     * @exception  FileNotFoundException  if the file exists but is a directory
 131.156 +     *                   rather than a regular file, does not exist but cannot
 131.157 +     *                   be created, or cannot be opened for any other reason
 131.158 +     * @exception  SecurityException  if a security manager exists and its
 131.159 +     *               <code>checkWrite</code> method denies write access
 131.160 +     *               to the file.
 131.161 +     * @see        java.io.File#getPath()
 131.162 +     * @see        java.lang.SecurityException
 131.163 +     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 131.164 +     */
 131.165 +    public FileOutputStream(File file) throws FileNotFoundException {
 131.166 +        this(file, false);
 131.167 +    }
 131.168 +
 131.169 +    /**
 131.170 +     * Creates a file output stream to write to the file represented by
 131.171 +     * the specified <code>File</code> object. If the second argument is
 131.172 +     * <code>true</code>, then bytes will be written to the end of the file
 131.173 +     * rather than the beginning. A new <code>FileDescriptor</code> object is
 131.174 +     * created to represent this file connection.
 131.175 +     * <p>
 131.176 +     * First, if there is a security manager, its <code>checkWrite</code>
 131.177 +     * method is called with the path represented by the <code>file</code>
 131.178 +     * argument as its argument.
 131.179 +     * <p>
 131.180 +     * If the file exists but is a directory rather than a regular file, does
 131.181 +     * not exist but cannot be created, or cannot be opened for any other
 131.182 +     * reason then a <code>FileNotFoundException</code> is thrown.
 131.183 +     *
 131.184 +     * @param      file               the file to be opened for writing.
 131.185 +     * @param     append      if <code>true</code>, then bytes will be written
 131.186 +     *                   to the end of the file rather than the beginning
 131.187 +     * @exception  FileNotFoundException  if the file exists but is a directory
 131.188 +     *                   rather than a regular file, does not exist but cannot
 131.189 +     *                   be created, or cannot be opened for any other reason
 131.190 +     * @exception  SecurityException  if a security manager exists and its
 131.191 +     *               <code>checkWrite</code> method denies write access
 131.192 +     *               to the file.
 131.193 +     * @see        java.io.File#getPath()
 131.194 +     * @see        java.lang.SecurityException
 131.195 +     * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 131.196 +     * @since 1.4
 131.197 +     */
 131.198 +    public FileOutputStream(File file, boolean append)
 131.199 +        throws FileNotFoundException
 131.200 +    {
 131.201 +        throw new SecurityException();
 131.202 +    }
 131.203 +
 131.204 +    /**
 131.205 +     * Creates a file output stream to write to the specified file
 131.206 +     * descriptor, which represents an existing connection to an actual
 131.207 +     * file in the file system.
 131.208 +     * <p>
 131.209 +     * First, if there is a security manager, its <code>checkWrite</code>
 131.210 +     * method is called with the file descriptor <code>fdObj</code>
 131.211 +     * argument as its argument.
 131.212 +     * <p>
 131.213 +     * If <code>fdObj</code> is null then a <code>NullPointerException</code>
 131.214 +     * is thrown.
 131.215 +     * <p>
 131.216 +     * This constructor does not throw an exception if <code>fdObj</code>
 131.217 +     * is {@link java.io.FileDescriptor#valid() invalid}.
 131.218 +     * However, if the methods are invoked on the resulting stream to attempt
 131.219 +     * I/O on the stream, an <code>IOException</code> is thrown.
 131.220 +     *
 131.221 +     * @param      fdObj   the file descriptor to be opened for writing
 131.222 +     * @exception  SecurityException  if a security manager exists and its
 131.223 +     *               <code>checkWrite</code> method denies
 131.224 +     *               write access to the file descriptor
 131.225 +     * @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
 131.226 +     */
 131.227 +    public FileOutputStream(FileDescriptor fdObj) {
 131.228 +        throw new SecurityException();
 131.229 +    }
 131.230 +
 131.231 +    /**
 131.232 +     * Opens a file, with the specified name, for overwriting or appending.
 131.233 +     * @param name name of file to be opened
 131.234 +     * @param append whether the file is to be opened in append mode
 131.235 +     */
 131.236 +    private native void open(String name, boolean append)
 131.237 +        throws FileNotFoundException;
 131.238 +
 131.239 +    /**
 131.240 +     * Writes the specified byte to this file output stream.
 131.241 +     *
 131.242 +     * @param   b   the byte to be written.
 131.243 +     * @param   append   {@code true} if the write operation first
 131.244 +     *     advances the position to the end of file
 131.245 +     */
 131.246 +    private native void write(int b, boolean append) throws IOException;
 131.247 +
 131.248 +    /**
 131.249 +     * Writes the specified byte to this file output stream. Implements
 131.250 +     * the <code>write</code> method of <code>OutputStream</code>.
 131.251 +     *
 131.252 +     * @param      b   the byte to be written.
 131.253 +     * @exception  IOException  if an I/O error occurs.
 131.254 +     */
 131.255 +    public void write(int b) throws IOException {
 131.256 +        write(b, append);
 131.257 +    }
 131.258 +
 131.259 +    /**
 131.260 +     * Writes a sub array as a sequence of bytes.
 131.261 +     * @param b the data to be written
 131.262 +     * @param off the start offset in the data
 131.263 +     * @param len the number of bytes that are written
 131.264 +     * @param append {@code true} to first advance the position to the
 131.265 +     *     end of file
 131.266 +     * @exception IOException If an I/O error has occurred.
 131.267 +     */
 131.268 +    private native void writeBytes(byte b[], int off, int len, boolean append)
 131.269 +        throws IOException;
 131.270 +
 131.271 +    /**
 131.272 +     * Writes <code>b.length</code> bytes from the specified byte array
 131.273 +     * to this file output stream.
 131.274 +     *
 131.275 +     * @param      b   the data.
 131.276 +     * @exception  IOException  if an I/O error occurs.
 131.277 +     */
 131.278 +    public void write(byte b[]) throws IOException {
 131.279 +        writeBytes(b, 0, b.length, append);
 131.280 +    }
 131.281 +
 131.282 +    /**
 131.283 +     * Writes <code>len</code> bytes from the specified byte array
 131.284 +     * starting at offset <code>off</code> to this file output stream.
 131.285 +     *
 131.286 +     * @param      b     the data.
 131.287 +     * @param      off   the start offset in the data.
 131.288 +     * @param      len   the number of bytes to write.
 131.289 +     * @exception  IOException  if an I/O error occurs.
 131.290 +     */
 131.291 +    public void write(byte b[], int off, int len) throws IOException {
 131.292 +        writeBytes(b, off, len, append);
 131.293 +    }
 131.294 +
 131.295 +    /**
 131.296 +     * Closes this file output stream and releases any system resources
 131.297 +     * associated with this stream. This file output stream may no longer
 131.298 +     * be used for writing bytes.
 131.299 +     *
 131.300 +     * <p> If this stream has an associated channel then the channel is closed
 131.301 +     * as well.
 131.302 +     *
 131.303 +     * @exception  IOException  if an I/O error occurs.
 131.304 +     *
 131.305 +     * @revised 1.4
 131.306 +     * @spec JSR-51
 131.307 +     */
 131.308 +    public void close() throws IOException {
 131.309 +        synchronized (closeLock) {
 131.310 +            if (closed) {
 131.311 +                return;
 131.312 +            }
 131.313 +            closed = true;
 131.314 +        }
 131.315 +//
 131.316 +//        if (channel != null) {
 131.317 +//            /*
 131.318 +//             * Decrement FD use count associated with the channel
 131.319 +//             * The use count is incremented whenever a new channel
 131.320 +//             * is obtained from this stream.
 131.321 +//             */
 131.322 +//            fd.decrementAndGetUseCount();
 131.323 +//            channel.close();
 131.324 +//        }
 131.325 +
 131.326 +        /*
 131.327 +         * Decrement FD use count associated with this stream
 131.328 +         */
 131.329 +        int useCount = fd.decrementAndGetUseCount();
 131.330 +
 131.331 +        /*
 131.332 +         * If FileDescriptor is still in use by another stream, the finalizer
 131.333 +         * will not close it.
 131.334 +         */
 131.335 +        if ((useCount <= 0) || !isRunningFinalize()) {
 131.336 +            close0();
 131.337 +        }
 131.338 +    }
 131.339 +
 131.340 +    /**
 131.341 +     * Returns the file descriptor associated with this stream.
 131.342 +     *
 131.343 +     * @return  the <code>FileDescriptor</code> object that represents
 131.344 +     *          the connection to the file in the file system being used
 131.345 +     *          by this <code>FileOutputStream</code> object.
 131.346 +     *
 131.347 +     * @exception  IOException  if an I/O error occurs.
 131.348 +     * @see        java.io.FileDescriptor
 131.349 +     */
 131.350 +     public final FileDescriptor getFD()  throws IOException {
 131.351 +        if (fd != null) return fd;
 131.352 +        throw new IOException();
 131.353 +     }
 131.354 +
 131.355 +    /**
 131.356 +     * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 131.357 +     * object associated with this file output stream. </p>
 131.358 +     *
 131.359 +     * <p> The initial {@link java.nio.channels.FileChannel#position()
 131.360 +     * </code>position<code>} of the returned channel will be equal to the
 131.361 +     * number of bytes written to the file so far unless this stream is in
 131.362 +     * append mode, in which case it will be equal to the size of the file.
 131.363 +     * Writing bytes to this stream will increment the channel's position
 131.364 +     * accordingly.  Changing the channel's position, either explicitly or by
 131.365 +     * writing, will change this stream's file position.
 131.366 +     *
 131.367 +     * @return  the file channel associated with this file output stream
 131.368 +     *
 131.369 +     * @since 1.4
 131.370 +     * @spec JSR-51
 131.371 +     */
 131.372 +//    public FileChannel getChannel() {
 131.373 +//        synchronized (this) {
 131.374 +//            if (channel == null) {
 131.375 +//                channel = FileChannelImpl.open(fd, false, true, append, this);
 131.376 +//
 131.377 +//                /*
 131.378 +//                 * Increment fd's use count. Invoking the channel's close()
 131.379 +//                 * method will result in decrementing the use count set for
 131.380 +//                 * the channel.
 131.381 +//                 */
 131.382 +//                fd.incrementAndGetUseCount();
 131.383 +//            }
 131.384 +//            return channel;
 131.385 +//        }
 131.386 +//    }
 131.387 +
 131.388 +    /**
 131.389 +     * Cleans up the connection to the file, and ensures that the
 131.390 +     * <code>close</code> method of this file output stream is
 131.391 +     * called when there are no more references to this stream.
 131.392 +     *
 131.393 +     * @exception  IOException  if an I/O error occurs.
 131.394 +     * @see        java.io.FileInputStream#close()
 131.395 +     */
 131.396 +    protected void finalize() throws IOException {
 131.397 +        if (fd != null) {
 131.398 +            if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
 131.399 +                flush();
 131.400 +            } else {
 131.401 +
 131.402 +                /*
 131.403 +                 * Finalizer should not release the FileDescriptor if another
 131.404 +                 * stream is still using it. If the user directly invokes
 131.405 +                 * close() then the FileDescriptor is also released.
 131.406 +                 */
 131.407 +                runningFinalize.set(Boolean.TRUE);
 131.408 +                try {
 131.409 +                    close();
 131.410 +                } finally {
 131.411 +                    runningFinalize.set(Boolean.FALSE);
 131.412 +                }
 131.413 +            }
 131.414 +        }
 131.415 +    }
 131.416 +
 131.417 +    private native void close0() throws IOException;
 131.418 +
 131.419 +    private static native void initIDs();
 131.420 +
 131.421 +    static {
 131.422 +        initIDs();
 131.423 +    }
 131.424 +
 131.425 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/rt/emul/compact/src/main/java/java/io/FileReader.java	Wed Apr 30 15:04:10 2014 +0200
   132.3 @@ -0,0 +1,85 @@
   132.4 +/*
   132.5 + * Copyright (c) 1996, 2001, 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 + * Convenience class for reading character files.  The constructors of this
  132.34 + * class assume that the default character encoding and the default byte-buffer
  132.35 + * size are appropriate.  To specify these values yourself, construct an
  132.36 + * InputStreamReader on a FileInputStream.
  132.37 + *
  132.38 + * <p><code>FileReader</code> is meant for reading streams of characters.
  132.39 + * For reading streams of raw bytes, consider using a
  132.40 + * <code>FileInputStream</code>.
  132.41 + *
  132.42 + * @see InputStreamReader
  132.43 + * @see FileInputStream
  132.44 + *
  132.45 + * @author      Mark Reinhold
  132.46 + * @since       JDK1.1
  132.47 + */
  132.48 +public class FileReader extends InputStreamReader {
  132.49 +
  132.50 +   /**
  132.51 +    * Creates a new <tt>FileReader</tt>, given the name of the
  132.52 +    * file to read from.
  132.53 +    *
  132.54 +    * @param fileName the name of the file to read from
  132.55 +    * @exception  FileNotFoundException  if the named file does not exist,
  132.56 +    *                   is a directory rather than a regular file,
  132.57 +    *                   or for some other reason cannot be opened for
  132.58 +    *                   reading.
  132.59 +    */
  132.60 +    public FileReader(String fileName) throws FileNotFoundException {
  132.61 +        super(new FileInputStream(fileName));
  132.62 +    }
  132.63 +
  132.64 +   /**
  132.65 +    * Creates a new <tt>FileReader</tt>, given the <tt>File</tt>
  132.66 +    * to read from.
  132.67 +    *
  132.68 +    * @param file the <tt>File</tt> to read from
  132.69 +    * @exception  FileNotFoundException  if the file does not exist,
  132.70 +    *                   is a directory rather than a regular file,
  132.71 +    *                   or for some other reason cannot be opened for
  132.72 +    *                   reading.
  132.73 +    */
  132.74 +    public FileReader(File file) throws FileNotFoundException {
  132.75 +        super(new FileInputStream(file));
  132.76 +    }
  132.77 +
  132.78 +   /**
  132.79 +    * Creates a new <tt>FileReader</tt>, given the
  132.80 +    * <tt>FileDescriptor</tt> to read from.
  132.81 +    *
  132.82 +    * @param fd the FileDescriptor to read from
  132.83 +    */
  132.84 +    public FileReader(FileDescriptor fd) {
  132.85 +        super(new FileInputStream(fd));
  132.86 +    }
  132.87 +
  132.88 +}
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/rt/emul/compact/src/main/java/java/io/FileWriter.java	Wed Apr 30 15:04:10 2014 +0200
   133.3 @@ -0,0 +1,119 @@
   133.4 +/*
   133.5 + * Copyright (c) 1996, 2001, 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 +/**
  133.33 + * Convenience class for writing character files.  The constructors of this
  133.34 + * class assume that the default character encoding and the default byte-buffer
  133.35 + * size are acceptable.  To specify these values yourself, construct an
  133.36 + * OutputStreamWriter on a FileOutputStream.
  133.37 + *
  133.38 + * <p>Whether or not a file is available or may be created depends upon the
  133.39 + * underlying platform.  Some platforms, in particular, allow a file to be
  133.40 + * opened for writing by only one <tt>FileWriter</tt> (or other file-writing
  133.41 + * object) at a time.  In such situations the constructors in this class
  133.42 + * will fail if the file involved is already open.
  133.43 + *
  133.44 + * <p><code>FileWriter</code> is meant for writing streams of characters.
  133.45 + * For writing streams of raw bytes, consider using a
  133.46 + * <code>FileOutputStream</code>.
  133.47 + *
  133.48 + * @see OutputStreamWriter
  133.49 + * @see FileOutputStream
  133.50 + *
  133.51 + * @author      Mark Reinhold
  133.52 + * @since       JDK1.1
  133.53 + */
  133.54 +
  133.55 +public class FileWriter extends OutputStreamWriter {
  133.56 +
  133.57 +    /**
  133.58 +     * Constructs a FileWriter object given a file name.
  133.59 +     *
  133.60 +     * @param fileName  String The system-dependent filename.
  133.61 +     * @throws IOException  if the named file exists but is a directory rather
  133.62 +     *                  than a regular file, does not exist but cannot be
  133.63 +     *                  created, or cannot be opened for any other reason
  133.64 +     */
  133.65 +    public FileWriter(String fileName) throws IOException {
  133.66 +        super(new FileOutputStream(fileName));
  133.67 +    }
  133.68 +
  133.69 +    /**
  133.70 +     * Constructs a FileWriter object given a file name with a boolean
  133.71 +     * indicating whether or not to append the data written.
  133.72 +     *
  133.73 +     * @param fileName  String The system-dependent filename.
  133.74 +     * @param append    boolean if <code>true</code>, then data will be written
  133.75 +     *                  to the end of the file rather than the beginning.
  133.76 +     * @throws IOException  if the named file exists but is a directory rather
  133.77 +     *                  than a regular file, does not exist but cannot be
  133.78 +     *                  created, or cannot be opened for any other reason
  133.79 +     */
  133.80 +    public FileWriter(String fileName, boolean append) throws IOException {
  133.81 +        super(new FileOutputStream(fileName, append));
  133.82 +    }
  133.83 +
  133.84 +    /**
  133.85 +     * Constructs a FileWriter object given a File object.
  133.86 +     *
  133.87 +     * @param file  a File object to write to.
  133.88 +     * @throws IOException  if the file exists but is a directory rather than
  133.89 +     *                  a regular file, does not exist but cannot be created,
  133.90 +     *                  or cannot be opened for any other reason
  133.91 +     */
  133.92 +    public FileWriter(File file) throws IOException {
  133.93 +        super(new FileOutputStream(file));
  133.94 +    }
  133.95 +
  133.96 +    /**
  133.97 +     * Constructs a FileWriter object given a File object. If the second
  133.98 +     * argument is <code>true</code>, then bytes will be written to the end
  133.99 +     * of the file rather than the beginning.
 133.100 +     *
 133.101 +     * @param file  a File object to write to
 133.102 +     * @param     append    if <code>true</code>, then bytes will be written
 133.103 +     *                      to the end of the file rather than the beginning
 133.104 +     * @throws IOException  if the file exists but is a directory rather than
 133.105 +     *                  a regular file, does not exist but cannot be created,
 133.106 +     *                  or cannot be opened for any other reason
 133.107 +     * @since 1.4
 133.108 +     */
 133.109 +    public FileWriter(File file, boolean append) throws IOException {
 133.110 +        super(new FileOutputStream(file, append));
 133.111 +    }
 133.112 +
 133.113 +    /**
 133.114 +     * Constructs a FileWriter object associated with a file descriptor.
 133.115 +     *
 133.116 +     * @param fd  FileDescriptor object to write to.
 133.117 +     */
 133.118 +    public FileWriter(FileDescriptor fd) {
 133.119 +        super(new FileOutputStream(fd));
 133.120 +    }
 133.121 +
 133.122 +}
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/rt/emul/compact/src/main/java/java/io/FilenameFilter.java	Wed Apr 30 15:04:10 2014 +0200
   134.3 @@ -0,0 +1,53 @@
   134.4 +/*
   134.5 + * Copyright (c) 1994, 1998, 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 + * Instances of classes that implement this interface are used to
  134.33 + * filter filenames. These instances are used to filter directory
  134.34 + * listings in the <code>list</code> method of class
  134.35 + * <code>File</code>, and by the Abstract Window Toolkit's file
  134.36 + * dialog component.
  134.37 + *
  134.38 + * @author  Arthur van Hoff
  134.39 + * @author  Jonathan Payne
  134.40 + * @see     java.awt.FileDialog#setFilenameFilter(java.io.FilenameFilter)
  134.41 + * @see     java.io.File
  134.42 + * @see     java.io.File#list(java.io.FilenameFilter)
  134.43 + * @since   JDK1.0
  134.44 + */
  134.45 +public
  134.46 +interface FilenameFilter {
  134.47 +    /**
  134.48 +     * Tests if a specified file should be included in a file list.
  134.49 +     *
  134.50 +     * @param   dir    the directory in which the file was found.
  134.51 +     * @param   name   the name of the file.
  134.52 +     * @return  <code>true</code> if and only if the name should be
  134.53 +     * included in the file list; <code>false</code> otherwise.
  134.54 +     */
  134.55 +    boolean accept(File dir, String name);
  134.56 +}
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/rt/emul/compact/src/main/java/java/io/FilterReader.java	Wed Apr 30 15:04:10 2014 +0200
   135.3 @@ -0,0 +1,124 @@
   135.4 +/*
   135.5 + * Copyright (c) 1996, 2005, 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 +/**
  135.33 + * Abstract class for reading filtered character streams.
  135.34 + * The abstract class <code>FilterReader</code> itself
  135.35 + * provides default methods that pass all requests to
  135.36 + * the contained stream. Subclasses of <code>FilterReader</code>
  135.37 + * should override some of these methods and may also provide
  135.38 + * additional methods and fields.
  135.39 + *
  135.40 + * @author      Mark Reinhold
  135.41 + * @since       JDK1.1
  135.42 + */
  135.43 +
  135.44 +public abstract class FilterReader extends Reader {
  135.45 +
  135.46 +    /**
  135.47 +     * The underlying character-input stream.
  135.48 +     */
  135.49 +    protected Reader in;
  135.50 +
  135.51 +    /**
  135.52 +     * Creates a new filtered reader.
  135.53 +     *
  135.54 +     * @param in  a Reader object providing the underlying stream.
  135.55 +     * @throws NullPointerException if <code>in</code> is <code>null</code>
  135.56 +     */
  135.57 +    protected FilterReader(Reader in) {
  135.58 +        super(in);
  135.59 +        this.in = in;
  135.60 +    }
  135.61 +
  135.62 +    /**
  135.63 +     * Reads a single character.
  135.64 +     *
  135.65 +     * @exception  IOException  If an I/O error occurs
  135.66 +     */
  135.67 +    public int read() throws IOException {
  135.68 +        return in.read();
  135.69 +    }
  135.70 +
  135.71 +    /**
  135.72 +     * Reads characters into a portion of an array.
  135.73 +     *
  135.74 +     * @exception  IOException  If an I/O error occurs
  135.75 +     */
  135.76 +    public int read(char cbuf[], int off, int len) throws IOException {
  135.77 +        return in.read(cbuf, off, len);
  135.78 +    }
  135.79 +
  135.80 +    /**
  135.81 +     * Skips characters.
  135.82 +     *
  135.83 +     * @exception  IOException  If an I/O error occurs
  135.84 +     */
  135.85 +    public long skip(long n) throws IOException {
  135.86 +        return in.skip(n);
  135.87 +    }
  135.88 +
  135.89 +    /**
  135.90 +     * Tells whether this stream is ready to be read.
  135.91 +     *
  135.92 +     * @exception  IOException  If an I/O error occurs
  135.93 +     */
  135.94 +    public boolean ready() throws IOException {
  135.95 +        return in.ready();
  135.96 +    }
  135.97 +
  135.98 +    /**
  135.99 +     * Tells whether this stream supports the mark() operation.
 135.100 +     */
 135.101 +    public boolean markSupported() {
 135.102 +        return in.markSupported();
 135.103 +    }
 135.104 +
 135.105 +    /**
 135.106 +     * Marks the present position in the stream.
 135.107 +     *
 135.108 +     * @exception  IOException  If an I/O error occurs
 135.109 +     */
 135.110 +    public void mark(int readAheadLimit) throws IOException {
 135.111 +        in.mark(readAheadLimit);
 135.112 +    }
 135.113 +
 135.114 +    /**
 135.115 +     * Resets the stream.
 135.116 +     *
 135.117 +     * @exception  IOException  If an I/O error occurs
 135.118 +     */
 135.119 +    public void reset() throws IOException {
 135.120 +        in.reset();
 135.121 +    }
 135.122 +
 135.123 +    public void close() throws IOException {
 135.124 +        in.close();
 135.125 +    }
 135.126 +
 135.127 +}
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/rt/emul/compact/src/main/java/java/io/FilterWriter.java	Wed Apr 30 15:04:10 2014 +0200
   136.3 @@ -0,0 +1,107 @@
   136.4 +/*
   136.5 + * Copyright (c) 1996, 2005, 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 +
  136.32 +/**
  136.33 + * Abstract class for writing filtered character streams.
  136.34 + * The abstract class <code>FilterWriter</code> itself
  136.35 + * provides default methods that pass all requests to the
  136.36 + * contained stream. Subclasses of <code>FilterWriter</code>
  136.37 + * should override some of these methods and may also
  136.38 + * provide additional methods and fields.
  136.39 + *
  136.40 + * @author      Mark Reinhold
  136.41 + * @since       JDK1.1
  136.42 + */
  136.43 +
  136.44 +public abstract class FilterWriter extends Writer {
  136.45 +
  136.46 +    /**
  136.47 +     * The underlying character-output stream.
  136.48 +     */
  136.49 +    protected Writer out;
  136.50 +
  136.51 +    /**
  136.52 +     * Create a new filtered writer.
  136.53 +     *
  136.54 +     * @param out  a Writer object to provide the underlying stream.
  136.55 +     * @throws NullPointerException if <code>out</code> is <code>null</code>
  136.56 +     */
  136.57 +    protected FilterWriter(Writer out) {
  136.58 +        super(out);
  136.59 +        this.out = out;
  136.60 +    }
  136.61 +
  136.62 +    /**
  136.63 +     * Writes a single character.
  136.64 +     *
  136.65 +     * @exception  IOException  If an I/O error occurs
  136.66 +     */
  136.67 +    public void write(int c) throws IOException {
  136.68 +        out.write(c);
  136.69 +    }
  136.70 +
  136.71 +    /**
  136.72 +     * Writes a portion of an array of characters.
  136.73 +     *
  136.74 +     * @param  cbuf  Buffer of characters to be written
  136.75 +     * @param  off   Offset from which to start reading characters
  136.76 +     * @param  len   Number of characters to be written
  136.77 +     *
  136.78 +     * @exception  IOException  If an I/O error occurs
  136.79 +     */
  136.80 +    public void write(char cbuf[], int off, int len) throws IOException {
  136.81 +        out.write(cbuf, off, len);
  136.82 +    }
  136.83 +
  136.84 +    /**
  136.85 +     * Writes a portion of a string.
  136.86 +     *
  136.87 +     * @param  str  String to be written
  136.88 +     * @param  off  Offset from which to start reading characters
  136.89 +     * @param  len  Number of characters to be written
  136.90 +     *
  136.91 +     * @exception  IOException  If an I/O error occurs
  136.92 +     */
  136.93 +    public void write(String str, int off, int len) throws IOException {
  136.94 +        out.write(str, off, len);
  136.95 +    }
  136.96 +
  136.97 +    /**
  136.98 +     * Flushes the stream.
  136.99 +     *
 136.100 +     * @exception  IOException  If an I/O error occurs
 136.101 +     */
 136.102 +    public void flush() throws IOException {
 136.103 +        out.flush();
 136.104 +    }
 136.105 +
 136.106 +    public void close() throws IOException {
 136.107 +        out.close();
 136.108 +    }
 136.109 +
 136.110 +}
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/rt/emul/compact/src/main/java/java/io/InterruptedIOException.java	Wed Apr 30 15:04:10 2014 +0200
   137.3 @@ -0,0 +1,74 @@
   137.4 +/*
   137.5 + * Copyright (c) 1995, 2008, 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 +/**
  137.32 + * Signals that an I/O operation has been interrupted. An
  137.33 + * <code>InterruptedIOException</code> is thrown to indicate that an
  137.34 + * input or output transfer has been terminated because the thread
  137.35 + * performing it was interrupted. The field {@link #bytesTransferred}
  137.36 + * indicates how many bytes were successfully transferred before
  137.37 + * the interruption occurred.
  137.38 + *
  137.39 + * @author  unascribed
  137.40 + * @see     java.io.InputStream
  137.41 + * @see     java.io.OutputStream
  137.42 + * @see     java.lang.Thread#interrupt()
  137.43 + * @since   JDK1.0
  137.44 + */
  137.45 +public
  137.46 +class InterruptedIOException extends IOException {
  137.47 +    private static final long serialVersionUID = 4020568460727500567L;
  137.48 +
  137.49 +    /**
  137.50 +     * Constructs an <code>InterruptedIOException</code> with
  137.51 +     * <code>null</code> as its error detail message.
  137.52 +     */
  137.53 +    public InterruptedIOException() {
  137.54 +        super();
  137.55 +    }
  137.56 +
  137.57 +    /**
  137.58 +     * Constructs an <code>InterruptedIOException</code> with the
  137.59 +     * specified detail message. The string <code>s</code> can be
  137.60 +     * retrieved later by the
  137.61 +     * <code>{@link java.lang.Throwable#getMessage}</code>
  137.62 +     * method of class <code>java.lang.Throwable</code>.
  137.63 +     *
  137.64 +     * @param   s   the detail message.
  137.65 +     */
  137.66 +    public InterruptedIOException(String s) {
  137.67 +        super(s);
  137.68 +    }
  137.69 +
  137.70 +    /**
  137.71 +     * Reports how many bytes had been transferred as part of the I/O
  137.72 +     * operation before it was interrupted.
  137.73 +     *
  137.74 +     * @serial
  137.75 +     */
  137.76 +    public int bytesTransferred = 0;
  137.77 +}
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/rt/emul/compact/src/main/java/java/io/LineNumberInputStream.java	Wed Apr 30 15:04:10 2014 +0200
   138.3 @@ -0,0 +1,292 @@
   138.4 +/*
   138.5 + * Copyright (c) 1995, 2004, 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 + * This class is an input stream filter that provides the added
  138.33 + * functionality of keeping track of the current line number.
  138.34 + * <p>
  138.35 + * A line is a sequence of bytes ending with a carriage return
  138.36 + * character (<code>'&#92;r'</code>), a newline character
  138.37 + * (<code>'&#92;n'</code>), or a carriage return character followed
  138.38 + * immediately by a linefeed character. In all three cases, the line
  138.39 + * terminating character(s) are returned as a single newline character.
  138.40 + * <p>
  138.41 + * The line number begins at <code>0</code>, and is incremented by
  138.42 + * <code>1</code> when a <code>read</code> returns a newline character.
  138.43 + *
  138.44 + * @author     Arthur van Hoff
  138.45 + * @see        java.io.LineNumberReader
  138.46 + * @since      JDK1.0
  138.47 + * @deprecated This class incorrectly assumes that bytes adequately represent
  138.48 + *             characters.  As of JDK&nbsp;1.1, the preferred way to operate on
  138.49 + *             character streams is via the new character-stream classes, which
  138.50 + *             include a class for counting line numbers.
  138.51 + */
  138.52 +@Deprecated
  138.53 +public
  138.54 +class LineNumberInputStream extends FilterInputStream {
  138.55 +    int pushBack = -1;
  138.56 +    int lineNumber;
  138.57 +    int markLineNumber;
  138.58 +    int markPushBack = -1;
  138.59 +
  138.60 +    /**
  138.61 +     * Constructs a newline number input stream that reads its input
  138.62 +     * from the specified input stream.
  138.63 +     *
  138.64 +     * @param      in   the underlying input stream.
  138.65 +     */
  138.66 +    public LineNumberInputStream(InputStream in) {
  138.67 +        super(in);
  138.68 +    }
  138.69 +
  138.70 +    /**
  138.71 +     * Reads the next byte of data from this input stream. The value
  138.72 +     * byte is returned as an <code>int</code> in the range
  138.73 +     * <code>0</code> to <code>255</code>. If no byte is available
  138.74 +     * because the end of the stream has been reached, the value
  138.75 +     * <code>-1</code> is returned. This method blocks until input data
  138.76 +     * is available, the end of the stream is detected, or an exception
  138.77 +     * is thrown.
  138.78 +     * <p>
  138.79 +     * The <code>read</code> method of
  138.80 +     * <code>LineNumberInputStream</code> calls the <code>read</code>
  138.81 +     * method of the underlying input stream. It checks for carriage
  138.82 +     * returns and newline characters in the input, and modifies the
  138.83 +     * current line number as appropriate. A carriage-return character or
  138.84 +     * a carriage return followed by a newline character are both
  138.85 +     * converted into a single newline character.
  138.86 +     *
  138.87 +     * @return     the next byte of data, or <code>-1</code> if the end of this
  138.88 +     *             stream is reached.
  138.89 +     * @exception  IOException  if an I/O error occurs.
  138.90 +     * @see        java.io.FilterInputStream#in
  138.91 +     * @see        java.io.LineNumberInputStream#getLineNumber()
  138.92 +     */
  138.93 +    public int read() throws IOException {
  138.94 +        int c = pushBack;
  138.95 +
  138.96 +        if (c != -1) {
  138.97 +            pushBack = -1;
  138.98 +        } else {
  138.99 +            c = in.read();
 138.100 +        }
 138.101 +
 138.102 +        switch (c) {
 138.103 +          case '\r':
 138.104 +            pushBack = in.read();
 138.105 +            if (pushBack == '\n') {
 138.106 +                pushBack = -1;
 138.107 +            }
 138.108 +          case '\n':
 138.109 +            lineNumber++;
 138.110 +            return '\n';
 138.111 +        }
 138.112 +        return c;
 138.113 +    }
 138.114 +
 138.115 +    /**
 138.116 +     * Reads up to <code>len</code> bytes of data from this input stream
 138.117 +     * into an array of bytes. This method blocks until some input is available.
 138.118 +     * <p>
 138.119 +     * The <code>read</code> method of
 138.120 +     * <code>LineNumberInputStream</code> repeatedly calls the
 138.121 +     * <code>read</code> method of zero arguments to fill in the byte array.
 138.122 +     *
 138.123 +     * @param      b     the buffer into which the data is read.
 138.124 +     * @param      off   the start offset of the data.
 138.125 +     * @param      len   the maximum number of bytes read.
 138.126 +     * @return     the total number of bytes read into the buffer, or
 138.127 +     *             <code>-1</code> if there is no more data because the end of
 138.128 +     *             this stream has been reached.
 138.129 +     * @exception  IOException  if an I/O error occurs.
 138.130 +     * @see        java.io.LineNumberInputStream#read()
 138.131 +     */
 138.132 +    public int read(byte b[], int off, int len) throws IOException {
 138.133 +        if (b == null) {
 138.134 +            throw new NullPointerException();
 138.135 +        } else if ((off < 0) || (off > b.length) || (len < 0) ||
 138.136 +                   ((off + len) > b.length) || ((off + len) < 0)) {
 138.137 +            throw new IndexOutOfBoundsException();
 138.138 +        } else if (len == 0) {
 138.139 +            return 0;
 138.140 +        }
 138.141 +
 138.142 +        int c = read();
 138.143 +        if (c == -1) {
 138.144 +            return -1;
 138.145 +        }
 138.146 +        b[off] = (byte)c;
 138.147 +
 138.148 +        int i = 1;
 138.149 +        try {
 138.150 +            for (; i < len ; i++) {
 138.151 +                c = read();
 138.152 +                if (c == -1) {
 138.153 +                    break;
 138.154 +                }
 138.155 +                if (b != null) {
 138.156 +                    b[off + i] = (byte)c;
 138.157 +                }
 138.158 +            }
 138.159 +        } catch (IOException ee) {
 138.160 +        }
 138.161 +        return i;
 138.162 +    }
 138.163 +
 138.164 +    /**
 138.165 +     * Skips over and discards <code>n</code> bytes of data from this
 138.166 +     * input stream. The <code>skip</code> method may, for a variety of
 138.167 +     * reasons, end up skipping over some smaller number of bytes,
 138.168 +     * possibly <code>0</code>. The actual number of bytes skipped is
 138.169 +     * returned.  If <code>n</code> is negative, no bytes are skipped.
 138.170 +     * <p>
 138.171 +     * The <code>skip</code> method of <code>LineNumberInputStream</code> creates
 138.172 +     * a byte array and then repeatedly reads into it until
 138.173 +     * <code>n</code> bytes have been read or the end of the stream has
 138.174 +     * been reached.
 138.175 +     *
 138.176 +     * @param      n   the number of bytes to be skipped.
 138.177 +     * @return     the actual number of bytes skipped.
 138.178 +     * @exception  IOException  if an I/O error occurs.
 138.179 +     * @see        java.io.FilterInputStream#in
 138.180 +     */
 138.181 +    public long skip(long n) throws IOException {
 138.182 +        int chunk = 2048;
 138.183 +        long remaining = n;
 138.184 +        byte data[];
 138.185 +        int nr;
 138.186 +
 138.187 +        if (n <= 0) {
 138.188 +            return 0;
 138.189 +        }
 138.190 +
 138.191 +        data = new byte[chunk];
 138.192 +        while (remaining > 0) {
 138.193 +            nr = read(data, 0, (int) Math.min(chunk, remaining));
 138.194 +            if (nr < 0) {
 138.195 +                break;
 138.196 +            }
 138.197 +            remaining -= nr;
 138.198 +        }
 138.199 +
 138.200 +        return n - remaining;
 138.201 +    }
 138.202 +
 138.203 +    /**
 138.204 +     * Sets the line number to the specified argument.
 138.205 +     *
 138.206 +     * @param      lineNumber   the new line number.
 138.207 +     * @see #getLineNumber
 138.208 +     */
 138.209 +    public void setLineNumber(int lineNumber) {
 138.210 +        this.lineNumber = lineNumber;
 138.211 +    }
 138.212 +
 138.213 +    /**
 138.214 +     * Returns the current line number.
 138.215 +     *
 138.216 +     * @return     the current line number.
 138.217 +     * @see #setLineNumber
 138.218 +     */
 138.219 +    public int getLineNumber() {
 138.220 +        return lineNumber;
 138.221 +    }
 138.222 +
 138.223 +
 138.224 +    /**
 138.225 +     * Returns the number of bytes that can be read from this input
 138.226 +     * stream without blocking.
 138.227 +     * <p>
 138.228 +     * Note that if the underlying input stream is able to supply
 138.229 +     * <i>k</i> input characters without blocking, the
 138.230 +     * <code>LineNumberInputStream</code> can guarantee only to provide
 138.231 +     * <i>k</i>/2 characters without blocking, because the
 138.232 +     * <i>k</i> characters from the underlying input stream might
 138.233 +     * consist of <i>k</i>/2 pairs of <code>'&#92;r'</code> and
 138.234 +     * <code>'&#92;n'</code>, which are converted to just
 138.235 +     * <i>k</i>/2 <code>'&#92;n'</code> characters.
 138.236 +     *
 138.237 +     * @return     the number of bytes that can be read from this input stream
 138.238 +     *             without blocking.
 138.239 +     * @exception  IOException  if an I/O error occurs.
 138.240 +     * @see        java.io.FilterInputStream#in
 138.241 +     */
 138.242 +    public int available() throws IOException {
 138.243 +        return (pushBack == -1) ? super.available()/2 : super.available()/2 + 1;
 138.244 +    }
 138.245 +
 138.246 +    /**
 138.247 +     * Marks the current position in this input stream. A subsequent
 138.248 +     * call to the <code>reset</code> method repositions this stream at
 138.249 +     * the last marked position so that subsequent reads re-read the same bytes.
 138.250 +     * <p>
 138.251 +     * The <code>mark</code> method of
 138.252 +     * <code>LineNumberInputStream</code> remembers the current line
 138.253 +     * number in a private variable, and then calls the <code>mark</code>
 138.254 +     * method of the underlying input stream.
 138.255 +     *
 138.256 +     * @param   readlimit   the maximum limit of bytes that can be read before
 138.257 +     *                      the mark position becomes invalid.
 138.258 +     * @see     java.io.FilterInputStream#in
 138.259 +     * @see     java.io.LineNumberInputStream#reset()
 138.260 +     */
 138.261 +    public void mark(int readlimit) {
 138.262 +        markLineNumber = lineNumber;
 138.263 +        markPushBack   = pushBack;
 138.264 +        in.mark(readlimit);
 138.265 +    }
 138.266 +
 138.267 +    /**
 138.268 +     * Repositions this stream to the position at the time the
 138.269 +     * <code>mark</code> method was last called on this input stream.
 138.270 +     * <p>
 138.271 +     * The <code>reset</code> method of
 138.272 +     * <code>LineNumberInputStream</code> resets the line number to be
 138.273 +     * the line number at the time the <code>mark</code> method was
 138.274 +     * called, and then calls the <code>reset</code> method of the
 138.275 +     * underlying input stream.
 138.276 +     * <p>
 138.277 +     * Stream marks are intended to be used in
 138.278 +     * situations where you need to read ahead a little to see what's in
 138.279 +     * the stream. Often this is most easily done by invoking some
 138.280 +     * general parser. If the stream is of the type handled by the
 138.281 +     * parser, it just chugs along happily. If the stream is not of
 138.282 +     * that type, the parser should toss an exception when it fails,
 138.283 +     * which, if it happens within readlimit bytes, allows the outer
 138.284 +     * code to reset the stream and try another parser.
 138.285 +     *
 138.286 +     * @exception  IOException  if an I/O error occurs.
 138.287 +     * @see        java.io.FilterInputStream#in
 138.288 +     * @see        java.io.LineNumberInputStream#mark(int)
 138.289 +     */
 138.290 +    public void reset() throws IOException {
 138.291 +        lineNumber = markLineNumber;
 138.292 +        pushBack   = markPushBack;
 138.293 +        in.reset();
 138.294 +    }
 138.295 +}
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/rt/emul/compact/src/main/java/java/io/LineNumberReader.java	Wed Apr 30 15:04:10 2014 +0200
   139.3 @@ -0,0 +1,281 @@
   139.4 +/*
   139.5 + * Copyright (c) 1996, 2006, 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.io;
  139.30 +
  139.31 +
  139.32 +/**
  139.33 + * A buffered character-input stream that keeps track of line numbers.  This
  139.34 + * class defines methods {@link #setLineNumber(int)} and {@link
  139.35 + * #getLineNumber()} for setting and getting the current line number
  139.36 + * respectively.
  139.37 + *
  139.38 + * <p> By default, line numbering begins at 0. This number increments at every
  139.39 + * <a href="#lt">line terminator</a> as the data is read, and can be changed
  139.40 + * with a call to <tt>setLineNumber(int)</tt>.  Note however, that
  139.41 + * <tt>setLineNumber(int)</tt> does not actually change the current position in
  139.42 + * the stream; it only changes the value that will be returned by
  139.43 + * <tt>getLineNumber()</tt>.
  139.44 + *
  139.45 + * <p> A line is considered to be <a name="lt">terminated</a> by any one of a
  139.46 + * line feed ('\n'), a carriage return ('\r'), or a carriage return followed
  139.47 + * immediately by a linefeed.
  139.48 + *
  139.49 + * @author      Mark Reinhold
  139.50 + * @since       JDK1.1
  139.51 + */
  139.52 +
  139.53 +public class LineNumberReader extends BufferedReader {
  139.54 +
  139.55 +    /** The current line number */
  139.56 +    private int lineNumber = 0;
  139.57 +
  139.58 +    /** The line number of the mark, if any */
  139.59 +    private int markedLineNumber; // Defaults to 0
  139.60 +
  139.61 +    /** If the next character is a line feed, skip it */
  139.62 +    private boolean skipLF;
  139.63 +
  139.64 +    /** The skipLF flag when the mark was set */
  139.65 +    private boolean markedSkipLF;
  139.66 +
  139.67 +    /**
  139.68 +     * Create a new line-numbering reader, using the default input-buffer
  139.69 +     * size.
  139.70 +     *
  139.71 +     * @param  in
  139.72 +     *         A Reader object to provide the underlying stream
  139.73 +     */
  139.74 +    public LineNumberReader(Reader in) {
  139.75 +        super(in);
  139.76 +    }
  139.77 +
  139.78 +    /**
  139.79 +     * Create a new line-numbering reader, reading characters into a buffer of
  139.80 +     * the given size.
  139.81 +     *
  139.82 +     * @param  in
  139.83 +     *         A Reader object to provide the underlying stream
  139.84 +     *
  139.85 +     * @param  sz
  139.86 +     *         An int specifying the size of the buffer
  139.87 +     */
  139.88 +    public LineNumberReader(Reader in, int sz) {
  139.89 +        super(in, sz);
  139.90 +    }
  139.91 +
  139.92 +    /**
  139.93 +     * Set the current line number.
  139.94 +     *
  139.95 +     * @param  lineNumber
  139.96 +     *         An int specifying the line number
  139.97 +     *
  139.98 +     * @see #getLineNumber
  139.99 +     */
 139.100 +    public void setLineNumber(int lineNumber) {
 139.101 +        this.lineNumber = lineNumber;
 139.102 +    }
 139.103 +
 139.104 +    /**
 139.105 +     * Get the current line number.
 139.106 +     *
 139.107 +     * @return  The current line number
 139.108 +     *
 139.109 +     * @see #setLineNumber
 139.110 +     */
 139.111 +    public int getLineNumber() {
 139.112 +        return lineNumber;
 139.113 +    }
 139.114 +
 139.115 +    /**
 139.116 +     * Read a single character.  <a href="#lt">Line terminators</a> are
 139.117 +     * compressed into single newline ('\n') characters.  Whenever a line
 139.118 +     * terminator is read the current line number is incremented.
 139.119 +     *
 139.120 +     * @return  The character read, or -1 if the end of the stream has been
 139.121 +     *          reached
 139.122 +     *
 139.123 +     * @throws  IOException
 139.124 +     *          If an I/O error occurs
 139.125 +     */
 139.126 +    public int read() throws IOException {
 139.127 +        synchronized (lock) {
 139.128 +            int c = super.read();
 139.129 +            if (skipLF) {
 139.130 +                if (c == '\n')
 139.131 +                    c = super.read();
 139.132 +                skipLF = false;
 139.133 +            }
 139.134 +            switch (c) {
 139.135 +            case '\r':
 139.136 +                skipLF = true;
 139.137 +            case '\n':          /* Fall through */
 139.138 +                lineNumber++;
 139.139 +                return '\n';
 139.140 +            }
 139.141 +            return c;
 139.142 +        }
 139.143 +    }
 139.144 +
 139.145 +    /**
 139.146 +     * Read characters into a portion of an array.  Whenever a <a
 139.147 +     * href="#lt">line terminator</a> is read the current line number is
 139.148 +     * incremented.
 139.149 +     *
 139.150 +     * @param  cbuf
 139.151 +     *         Destination buffer
 139.152 +     *
 139.153 +     * @param  off
 139.154 +     *         Offset at which to start storing characters
 139.155 +     *
 139.156 +     * @param  len
 139.157 +     *         Maximum number of characters to read
 139.158 +     *
 139.159 +     * @return  The number of bytes read, or -1 if the end of the stream has
 139.160 +     *          already been reached
 139.161 +     *
 139.162 +     * @throws  IOException
 139.163 +     *          If an I/O error occurs
 139.164 +     */
 139.165 +    public int read(char cbuf[], int off, int len) throws IOException {
 139.166 +        synchronized (lock) {
 139.167 +            int n = super.read(cbuf, off, len);
 139.168 +
 139.169 +            for (int i = off; i < off + n; i++) {
 139.170 +                int c = cbuf[i];
 139.171 +                if (skipLF) {
 139.172 +                    skipLF = false;
 139.173 +                    if (c == '\n')
 139.174 +                        continue;
 139.175 +                }
 139.176 +                switch (c) {
 139.177 +                case '\r':
 139.178 +                    skipLF = true;
 139.179 +                case '\n':      /* Fall through */
 139.180 +                    lineNumber++;
 139.181 +                    break;
 139.182 +                }
 139.183 +            }
 139.184 +
 139.185 +            return n;
 139.186 +        }
 139.187 +    }
 139.188 +
 139.189 +    /**
 139.190 +     * Read a line of text.  Whenever a <a href="#lt">line terminator</a> is
 139.191 +     * read the current line number is incremented.
 139.192 +     *
 139.193 +     * @return  A String containing the contents of the line, not including
 139.194 +     *          any <a href="#lt">line termination characters</a>, or
 139.195 +     *          <tt>null</tt> if the end of the stream has been reached
 139.196 +     *
 139.197 +     * @throws  IOException
 139.198 +     *          If an I/O error occurs
 139.199 +     */
 139.200 +    public String readLine() throws IOException {
 139.201 +        synchronized (lock) {
 139.202 +            String l = super.readLine(skipLF);
 139.203 +            skipLF = false;
 139.204 +            if (l != null)
 139.205 +                lineNumber++;
 139.206 +            return l;
 139.207 +        }
 139.208 +    }
 139.209 +
 139.210 +    /** Maximum skip-buffer size */
 139.211 +    private static final int maxSkipBufferSize = 8192;
 139.212 +
 139.213 +    /** Skip buffer, null until allocated */
 139.214 +    private char skipBuffer[] = null;
 139.215 +
 139.216 +    /**
 139.217 +     * Skip characters.
 139.218 +     *
 139.219 +     * @param  n
 139.220 +     *         The number of characters to skip
 139.221 +     *
 139.222 +     * @return  The number of characters actually skipped
 139.223 +     *
 139.224 +     * @throws  IOException
 139.225 +     *          If an I/O error occurs
 139.226 +     *
 139.227 +     * @throws  IllegalArgumentException
 139.228 +     *          If <tt>n</tt> is negative
 139.229 +     */
 139.230 +    public long skip(long n) throws IOException {
 139.231 +        if (n < 0)
 139.232 +            throw new IllegalArgumentException("skip() value is negative");
 139.233 +        int nn = (int) Math.min(n, maxSkipBufferSize);
 139.234 +        synchronized (lock) {
 139.235 +            if ((skipBuffer == null) || (skipBuffer.length < nn))
 139.236 +                skipBuffer = new char[nn];
 139.237 +            long r = n;
 139.238 +            while (r > 0) {
 139.239 +                int nc = read(skipBuffer, 0, (int) Math.min(r, nn));
 139.240 +                if (nc == -1)
 139.241 +                    break;
 139.242 +                r -= nc;
 139.243 +            }
 139.244 +            return n - r;
 139.245 +        }
 139.246 +    }
 139.247 +
 139.248 +    /**
 139.249 +     * Mark the present position in the stream.  Subsequent calls to reset()
 139.250 +     * will attempt to reposition the stream to this point, and will also reset
 139.251 +     * the line number appropriately.
 139.252 +     *
 139.253 +     * @param  readAheadLimit
 139.254 +     *         Limit on the number of characters that may be read while still
 139.255 +     *         preserving the mark.  After reading this many characters,
 139.256 +     *         attempting to reset the stream may fail.
 139.257 +     *
 139.258 +     * @throws  IOException
 139.259 +     *          If an I/O error occurs
 139.260 +     */
 139.261 +    public void mark(int readAheadLimit) throws IOException {
 139.262 +        synchronized (lock) {
 139.263 +            super.mark(readAheadLimit);
 139.264 +            markedLineNumber = lineNumber;
 139.265 +            markedSkipLF     = skipLF;
 139.266 +        }
 139.267 +    }
 139.268 +
 139.269 +    /**
 139.270 +     * Reset the stream to the most recent mark.
 139.271 +     *
 139.272 +     * @throws  IOException
 139.273 +     *          If the stream has not been marked, or if the mark has been
 139.274 +     *          invalidated
 139.275 +     */
 139.276 +    public void reset() throws IOException {
 139.277 +        synchronized (lock) {
 139.278 +            super.reset();
 139.279 +            lineNumber = markedLineNumber;
 139.280 +            skipLF     = markedSkipLF;
 139.281 +        }
 139.282 +    }
 139.283 +
 139.284 +}
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/rt/emul/compact/src/main/java/java/io/OutputStreamWriter.java	Wed Apr 30 15:04:10 2014 +0200
   140.3 @@ -0,0 +1,241 @@
   140.4 +/*
   140.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   140.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   140.7 + *
   140.8 + * This code is free software; you can redistribute it and/or modify it
   140.9 + * under the terms of the GNU General Public License version 2 only, as
  140.10 + * published by the Free Software Foundation.  Oracle designates this
  140.11 + * particular file as subject to the "Classpath" exception as provided
  140.12 + * by Oracle in the LICENSE file that accompanied this code.
  140.13 + *
  140.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  140.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  140.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  140.17 + * version 2 for more details (a copy is included in the LICENSE file that
  140.18 + * accompanied this code).
  140.19 + *
  140.20 + * You should have received a copy of the GNU General Public License version
  140.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  140.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  140.23 + *
  140.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  140.25 + * or visit www.oracle.com if you need additional information or have any
  140.26 + * questions.
  140.27 + */
  140.28 +
  140.29 +package java.io;
  140.30 +
  140.31 +import java.nio.charset.Charset;
  140.32 +
  140.33 +/**
  140.34 + * An OutputStreamWriter is a bridge from character streams to byte streams:
  140.35 + * Characters written to it are encoded into bytes using a specified {@link
  140.36 + * java.nio.charset.Charset <code>charset</code>}.  The charset that it uses
  140.37 + * may be specified by name or may be given explicitly, or the platform's
  140.38 + * default charset may be accepted.
  140.39 + *
  140.40 + * <p> Each invocation of a write() method causes the encoding converter to be
  140.41 + * invoked on the given character(s).  The resulting bytes are accumulated in a
  140.42 + * buffer before being written to the underlying output stream.  The size of
  140.43 + * this buffer may be specified, but by default it is large enough for most
  140.44 + * purposes.  Note that the characters passed to the write() methods are not
  140.45 + * buffered.
  140.46 + *
  140.47 + * <p> For top efficiency, consider wrapping an OutputStreamWriter within a
  140.48 + * BufferedWriter so as to avoid frequent converter invocations.  For example:
  140.49 + *
  140.50 + * <pre>
  140.51 + * Writer out
  140.52 + *   = new BufferedWriter(new OutputStreamWriter(System.out));
  140.53 + * </pre>
  140.54 + *
  140.55 + * <p> A <i>surrogate pair</i> is a character represented by a sequence of two
  140.56 + * <tt>char</tt> values: A <i>high</i> surrogate in the range '&#92;uD800' to
  140.57 + * '&#92;uDBFF' followed by a <i>low</i> surrogate in the range '&#92;uDC00' to
  140.58 + * '&#92;uDFFF'.
  140.59 + *
  140.60 + * <p> A <i>malformed surrogate element</i> is a high surrogate that is not
  140.61 + * followed by a low surrogate or a low surrogate that is not preceded by a
  140.62 + * high surrogate.
  140.63 + *
  140.64 + * <p> This class always replaces malformed surrogate elements and unmappable
  140.65 + * character sequences with the charset's default <i>substitution sequence</i>.
  140.66 + * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
  140.67 + * control over the encoding process is required.
  140.68 + *
  140.69 + * @see BufferedWriter
  140.70 + * @see OutputStream
  140.71 + * @see java.nio.charset.Charset
  140.72 + *
  140.73 + * @author      Mark Reinhold
  140.74 + * @since       JDK1.1
  140.75 + */
  140.76 +
  140.77 +public class OutputStreamWriter extends Writer {
  140.78 +    
  140.79 +    /**
  140.80 +     * Creates an OutputStreamWriter that uses the named charset.
  140.81 +     *
  140.82 +     * @param  out
  140.83 +     *         An OutputStream
  140.84 +     *
  140.85 +     * @param  charsetName
  140.86 +     *         The name of a supported
  140.87 +     *         {@link java.nio.charset.Charset </code>charset<code>}
  140.88 +     *
  140.89 +     * @exception  UnsupportedEncodingException
  140.90 +     *             If the named encoding is not supported
  140.91 +     */
  140.92 +    public OutputStreamWriter(OutputStream out, String charsetName)
  140.93 +        throws UnsupportedEncodingException
  140.94 +    {
  140.95 +        super(out);
  140.96 +        if (charsetName == null)
  140.97 +            throw new NullPointerException("charsetName");
  140.98 +        if (!charsetName.toUpperCase().equals("UTF-8")) {
  140.99 +            throw new UnsupportedEncodingException(charsetName);
 140.100 +        }
 140.101 +    }
 140.102 +
 140.103 +    /**
 140.104 +     * Creates an OutputStreamWriter that uses the default character encoding.
 140.105 +     *
 140.106 +     * @param  out  An OutputStream
 140.107 +     */
 140.108 +    public OutputStreamWriter(OutputStream out) {
 140.109 +        super(out);
 140.110 +    }
 140.111 +
 140.112 +    /**
 140.113 +     * Creates an OutputStreamWriter that uses the given charset. </p>
 140.114 +     *
 140.115 +     * @param  out
 140.116 +     *         An OutputStream
 140.117 +     *
 140.118 +     * @param  cs
 140.119 +     *         A charset
 140.120 +     *
 140.121 +     * @since 1.4
 140.122 +     * @spec JSR-51
 140.123 +     */
 140.124 +    public OutputStreamWriter(OutputStream out, Charset cs) {
 140.125 +        this(out);
 140.126 +    }
 140.127 +
 140.128 +    /**
 140.129 +     * Creates an OutputStreamWriter that uses the given charset encoder.  </p>
 140.130 +     *
 140.131 +     * @param  out
 140.132 +     *         An OutputStream
 140.133 +     *
 140.134 +     * @param  enc
 140.135 +     *         A charset encoder
 140.136 +     *
 140.137 +     * @since 1.4
 140.138 +     * @spec JSR-51
 140.139 +     */
 140.140 +//    public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
 140.141 +//        super(out);
 140.142 +//        if (enc == null)
 140.143 +//            throw new NullPointerException("charset encoder");
 140.144 +//        se = StreamEncoder.forOutputStreamWriter(out, this, enc);
 140.145 +//    }
 140.146 +
 140.147 +    /**
 140.148 +     * Returns the name of the character encoding being used by this stream.
 140.149 +     *
 140.150 +     * <p> If the encoding has an historical name then that name is returned;
 140.151 +     * otherwise the encoding's canonical name is returned.
 140.152 +     *
 140.153 +     * <p> If this instance was created with the {@link
 140.154 +     * #OutputStreamWriter(OutputStream, String)} constructor then the returned
 140.155 +     * name, being unique for the encoding, may differ from the name passed to
 140.156 +     * the constructor.  This method may return <tt>null</tt> if the stream has
 140.157 +     * been closed. </p>
 140.158 +     *
 140.159 +     * @return The historical name of this encoding, or possibly
 140.160 +     *         <code>null</code> if the stream has been closed
 140.161 +     *
 140.162 +     * @see java.nio.charset.Charset
 140.163 +     *
 140.164 +     * @revised 1.4
 140.165 +     * @spec JSR-51
 140.166 +     */
 140.167 +    public String getEncoding() {
 140.168 +        return "UTF-8";
 140.169 +    }
 140.170 +
 140.171 +    /**
 140.172 +     * Flushes the output buffer to the underlying byte stream, without flushing
 140.173 +     * the byte stream itself.  This method is non-private only so that it may
 140.174 +     * be invoked by PrintStream.
 140.175 +     */
 140.176 +    void flushBuffer() throws IOException {
 140.177 +        out().flush();
 140.178 +    }
 140.179 +
 140.180 +    /**
 140.181 +     * Writes a single character.
 140.182 +     *
 140.183 +     * @exception  IOException  If an I/O error occurs
 140.184 +     */
 140.185 +    public void write(int c) throws IOException {
 140.186 +        if (c <= 0x7F) {
 140.187 +            out().write(c);
 140.188 +        } else if (c <= 0x7FF) {
 140.189 +            out().write(0xC0 | (c >> 6));
 140.190 +            out().write(0x80 | (c & 0x3F));
 140.191 +        } else {
 140.192 +            out().write(0xE0 | (c >> 12));
 140.193 +            out().write(0x80 | ((c >> 6) & 0x3F));
 140.194 +            out().write(0x80 | (c & 0x3F));
 140.195 +        }
 140.196 +    }
 140.197 +
 140.198 +    /**
 140.199 +     * Writes a portion of an array of characters.
 140.200 +     *
 140.201 +     * @param  cbuf  Buffer of characters
 140.202 +     * @param  off   Offset from which to start writing characters
 140.203 +     * @param  len   Number of characters to write
 140.204 +     *
 140.205 +     * @exception  IOException  If an I/O error occurs
 140.206 +     */
 140.207 +    public void write(char cbuf[], int off, int len) throws IOException {
 140.208 +        while (len-- > 0) {
 140.209 +            write(cbuf[off++]);
 140.210 +        }
 140.211 +    }
 140.212 +
 140.213 +    /**
 140.214 +     * Writes a portion of a string.
 140.215 +     *
 140.216 +     * @param  str  A String
 140.217 +     * @param  off  Offset from which to start writing characters
 140.218 +     * @param  len  Number of characters to write
 140.219 +     *
 140.220 +     * @exception  IOException  If an I/O error occurs
 140.221 +     */
 140.222 +    public void write(String str, int off, int len) throws IOException {
 140.223 +        while (len-- > 0) {
 140.224 +            write(str.charAt(off++));
 140.225 +        }
 140.226 +    }
 140.227 +
 140.228 +    /**
 140.229 +     * Flushes the stream.
 140.230 +     *
 140.231 +     * @exception  IOException  If an I/O error occurs
 140.232 +     */
 140.233 +    public void flush() throws IOException {
 140.234 +        out().flush();
 140.235 +    }
 140.236 +
 140.237 +    public void close() throws IOException {
 140.238 +        out().close();
 140.239 +    }
 140.240 +    
 140.241 +    private OutputStream out() {
 140.242 +        return (OutputStream) lock;
 140.243 +    }
 140.244 +}
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/rt/emul/compact/src/main/java/java/io/PrintStream.java	Wed Apr 30 15:04:10 2014 +0200
   141.3 @@ -0,0 +1,1123 @@
   141.4 +/*
   141.5 + * Copyright (c) 1996, 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.io;
  141.30 +
  141.31 +import java.nio.charset.Charset;
  141.32 +import java.util.Arrays;
  141.33 +
  141.34 +
  141.35 +/**
  141.36 + * A <code>PrintStream</code> adds functionality to another output stream,
  141.37 + * namely the ability to print representations of various data values
  141.38 + * conveniently.  Two other features are provided as well.  Unlike other output
  141.39 + * streams, a <code>PrintStream</code> never throws an
  141.40 + * <code>IOException</code>; instead, exceptional situations merely set an
  141.41 + * internal flag that can be tested via the <code>checkError</code> method.
  141.42 + * Optionally, a <code>PrintStream</code> can be created so as to flush
  141.43 + * automatically; this means that the <code>flush</code> method is
  141.44 + * automatically invoked after a byte array is written, one of the
  141.45 + * <code>println</code> methods is invoked, or a newline character or byte
  141.46 + * (<code>'\n'</code>) is written.
  141.47 + *
  141.48 + * <p> All characters printed by a <code>PrintStream</code> are converted into
  141.49 + * bytes using the platform's default character encoding.  The <code>{@link
  141.50 + * PrintWriter}</code> class should be used in situations that require writing
  141.51 + * characters rather than bytes.
  141.52 + *
  141.53 + * @author     Frank Yellin
  141.54 + * @author     Mark Reinhold
  141.55 + * @since      JDK1.0
  141.56 + */
  141.57 +
  141.58 +public class PrintStream extends FilterOutputStream
  141.59 +    implements Appendable, Closeable
  141.60 +{
  141.61 +
  141.62 +    private final boolean autoFlush;
  141.63 +    private boolean trouble = false;
  141.64 +    private Formatter formatter;
  141.65 +
  141.66 +    /**
  141.67 +     * Track both the text- and character-output streams, so that their buffers
  141.68 +     * can be flushed without flushing the entire stream.
  141.69 +     */
  141.70 +    private BufferedWriter textOut;
  141.71 +    private OutputStreamWriter charOut;
  141.72 +
  141.73 +    /**
  141.74 +     * requireNonNull is explicitly declared here so as not to create an extra
  141.75 +     * dependency on java.util.Objects.requireNonNull. PrintStream is loaded
  141.76 +     * early during system initialization.
  141.77 +     */
  141.78 +    private static <T> T requireNonNull(T obj, String message) {
  141.79 +        if (obj == null)
  141.80 +            throw new NullPointerException(message);
  141.81 +        return obj;
  141.82 +    }
  141.83 +
  141.84 +    /* Private constructors */
  141.85 +    private PrintStream(boolean autoFlush, OutputStream out) {
  141.86 +        super(out);
  141.87 +        this.autoFlush = autoFlush;
  141.88 +        this.charOut = new OutputStreamWriter(this);
  141.89 +        this.textOut = new BufferedWriter(charOut);
  141.90 +    }
  141.91 +    
  141.92 +    static final class Formatter {
  141.93 +    }
  141.94 +    
  141.95 +    static Charset toCharset(String ch) throws UnsupportedEncodingException {
  141.96 +        if (!"UTF-8".equals(ch)) {
  141.97 +            throw new UnsupportedEncodingException();
  141.98 +        }
  141.99 +        return null;
 141.100 +    }
 141.101 +
 141.102 +    private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
 141.103 +        super(out);
 141.104 +        this.autoFlush = autoFlush;
 141.105 +        this.charOut = new OutputStreamWriter(this);
 141.106 +        this.textOut = new BufferedWriter(charOut);
 141.107 +    }
 141.108 +
 141.109 +    /* Variant of the private constructor so that the given charset name
 141.110 +     * can be verified before evaluating the OutputStream argument. Used
 141.111 +     * by constructors creating a FileOutputStream that also take a
 141.112 +     * charset name.
 141.113 +     */
 141.114 +    private PrintStream(boolean autoFlush, Charset charset, OutputStream out)
 141.115 +        throws UnsupportedEncodingException
 141.116 +    {
 141.117 +        this(autoFlush, out, charset);
 141.118 +    }
 141.119 +
 141.120 +    /**
 141.121 +     * Creates a new print stream.  This stream will not flush automatically.
 141.122 +     *
 141.123 +     * @param  out        The output stream to which values and objects will be
 141.124 +     *                    printed
 141.125 +     *
 141.126 +     * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
 141.127 +     */
 141.128 +    public PrintStream(OutputStream out) {
 141.129 +        this(out, false);
 141.130 +    }
 141.131 +
 141.132 +    /**
 141.133 +     * Creates a new print stream.
 141.134 +     *
 141.135 +     * @param  out        The output stream to which values and objects will be
 141.136 +     *                    printed
 141.137 +     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
 141.138 +     *                    whenever a byte array is written, one of the
 141.139 +     *                    <code>println</code> methods is invoked, or a newline
 141.140 +     *                    character or byte (<code>'\n'</code>) is written
 141.141 +     *
 141.142 +     * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
 141.143 +     */
 141.144 +    public PrintStream(OutputStream out, boolean autoFlush) {
 141.145 +        this(autoFlush, requireNonNull(out, "Null output stream"));
 141.146 +    }
 141.147 +
 141.148 +    /**
 141.149 +     * Creates a new print stream.
 141.150 +     *
 141.151 +     * @param  out        The output stream to which values and objects will be
 141.152 +     *                    printed
 141.153 +     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
 141.154 +     *                    whenever a byte array is written, one of the
 141.155 +     *                    <code>println</code> methods is invoked, or a newline
 141.156 +     *                    character or byte (<code>'\n'</code>) is written
 141.157 +     * @param  encoding   The name of a supported
 141.158 +     *                    <a href="../lang/package-summary.html#charenc">
 141.159 +     *                    character encoding</a>
 141.160 +     *
 141.161 +     * @throws  UnsupportedEncodingException
 141.162 +     *          If the named encoding is not supported
 141.163 +     *
 141.164 +     * @since  1.4
 141.165 +     */
 141.166 +    public PrintStream(OutputStream out, boolean autoFlush, String encoding)
 141.167 +        throws UnsupportedEncodingException
 141.168 +    {
 141.169 +        this(autoFlush,
 141.170 +             requireNonNull(out, "Null output stream"),
 141.171 +             toCharset(encoding));
 141.172 +    }
 141.173 +
 141.174 +    /**
 141.175 +     * Creates a new print stream, without automatic line flushing, with the
 141.176 +     * specified file name.  This convenience constructor creates
 141.177 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 141.178 +     * OutputStreamWriter}, which will encode characters using the
 141.179 +     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}
 141.180 +     * for this instance of the Java virtual machine.
 141.181 +     *
 141.182 +     * @param  fileName
 141.183 +     *         The name of the file to use as the destination of this print
 141.184 +     *         stream.  If the file exists, then it will be truncated to
 141.185 +     *         zero size; otherwise, a new file will be created.  The output
 141.186 +     *         will be written to the file and is buffered.
 141.187 +     *
 141.188 +     * @throws  FileNotFoundException
 141.189 +     *          If the given file object does not denote an existing, writable
 141.190 +     *          regular file and a new regular file of that name cannot be
 141.191 +     *          created, or if some other error occurs while opening or
 141.192 +     *          creating the file
 141.193 +     *
 141.194 +     * @throws  SecurityException
 141.195 +     *          If a security manager is present and {@link
 141.196 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 141.197 +     *          access to the file
 141.198 +     *
 141.199 +     * @since  1.5
 141.200 +     */
 141.201 +    public PrintStream(String fileName) throws FileNotFoundException {
 141.202 +        super(null);
 141.203 +        throw new FileNotFoundException();
 141.204 +    }
 141.205 +
 141.206 +    /**
 141.207 +     * Creates a new print stream, without automatic line flushing, with the
 141.208 +     * specified file name and charset.  This convenience constructor creates
 141.209 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 141.210 +     * OutputStreamWriter}, which will encode characters using the provided
 141.211 +     * charset.
 141.212 +     *
 141.213 +     * @param  fileName
 141.214 +     *         The name of the file to use as the destination of this print
 141.215 +     *         stream.  If the file exists, then it will be truncated to
 141.216 +     *         zero size; otherwise, a new file will be created.  The output
 141.217 +     *         will be written to the file and is buffered.
 141.218 +     *
 141.219 +     * @param  csn
 141.220 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 141.221 +     *         charset}
 141.222 +     *
 141.223 +     * @throws  FileNotFoundException
 141.224 +     *          If the given file object does not denote an existing, writable
 141.225 +     *          regular file and a new regular file of that name cannot be
 141.226 +     *          created, or if some other error occurs while opening or
 141.227 +     *          creating the file
 141.228 +     *
 141.229 +     * @throws  SecurityException
 141.230 +     *          If a security manager is present and {@link
 141.231 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 141.232 +     *          access to the file
 141.233 +     *
 141.234 +     * @throws  UnsupportedEncodingException
 141.235 +     *          If the named charset is not supported
 141.236 +     *
 141.237 +     * @since  1.5
 141.238 +     */
 141.239 +    public PrintStream(String fileName, String csn)
 141.240 +        throws FileNotFoundException, UnsupportedEncodingException
 141.241 +    {
 141.242 +        super(null);
 141.243 +        throw new FileNotFoundException();
 141.244 +    }
 141.245 +
 141.246 +    /**
 141.247 +     * Creates a new print stream, without automatic line flushing, with the
 141.248 +     * specified file.  This convenience constructor creates the necessary
 141.249 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 141.250 +     * which will encode characters using the {@linkplain
 141.251 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 141.252 +     * instance of the Java virtual machine.
 141.253 +     *
 141.254 +     * @param  file
 141.255 +     *         The file to use as the destination of this print stream.  If the
 141.256 +     *         file exists, then it will be truncated to zero size; otherwise,
 141.257 +     *         a new file will be created.  The output will be written to the
 141.258 +     *         file and is buffered.
 141.259 +     *
 141.260 +     * @throws  FileNotFoundException
 141.261 +     *          If the given file object does not denote an existing, writable
 141.262 +     *          regular file and a new regular file of that name cannot be
 141.263 +     *          created, or if some other error occurs while opening or
 141.264 +     *          creating the file
 141.265 +     *
 141.266 +     * @throws  SecurityException
 141.267 +     *          If a security manager is present and {@link
 141.268 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 141.269 +     *          denies write access to the file
 141.270 +     *
 141.271 +     * @since  1.5
 141.272 +     */
 141.273 +    public PrintStream(File file) throws FileNotFoundException {
 141.274 +        super(null);
 141.275 +        throw new FileNotFoundException();
 141.276 +    }
 141.277 +
 141.278 +    /**
 141.279 +     * Creates a new print stream, without automatic line flushing, with the
 141.280 +     * specified file and charset.  This convenience constructor creates
 141.281 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 141.282 +     * OutputStreamWriter}, which will encode characters using the provided
 141.283 +     * charset.
 141.284 +     *
 141.285 +     * @param  file
 141.286 +     *         The file to use as the destination of this print stream.  If the
 141.287 +     *         file exists, then it will be truncated to zero size; otherwise,
 141.288 +     *         a new file will be created.  The output will be written to the
 141.289 +     *         file and is buffered.
 141.290 +     *
 141.291 +     * @param  csn
 141.292 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 141.293 +     *         charset}
 141.294 +     *
 141.295 +     * @throws  FileNotFoundException
 141.296 +     *          If the given file object does not denote an existing, writable
 141.297 +     *          regular file and a new regular file of that name cannot be
 141.298 +     *          created, or if some other error occurs while opening or
 141.299 +     *          creating the file
 141.300 +     *
 141.301 +     * @throws  SecurityException
 141.302 +     *          If a security manager is presentand {@link
 141.303 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 141.304 +     *          denies write access to the file
 141.305 +     *
 141.306 +     * @throws  UnsupportedEncodingException
 141.307 +     *          If the named charset is not supported
 141.308 +     *
 141.309 +     * @since  1.5
 141.310 +     */
 141.311 +    public PrintStream(File file, String csn)
 141.312 +        throws FileNotFoundException, UnsupportedEncodingException
 141.313 +    {
 141.314 +        super(null);
 141.315 +        throw new FileNotFoundException();
 141.316 +    }
 141.317 +
 141.318 +    /** Check to make sure that the stream has not been closed */
 141.319 +    private void ensureOpen() throws IOException {
 141.320 +        if (out == null)
 141.321 +            throw new IOException("Stream closed");
 141.322 +    }
 141.323 +
 141.324 +    /**
 141.325 +     * Flushes the stream.  This is done by writing any buffered output bytes to
 141.326 +     * the underlying output stream and then flushing that stream.
 141.327 +     *
 141.328 +     * @see        java.io.OutputStream#flush()
 141.329 +     */
 141.330 +    public void flush() {
 141.331 +        synchronized (this) {
 141.332 +            try {
 141.333 +                ensureOpen();
 141.334 +                out.flush();
 141.335 +            }
 141.336 +            catch (IOException x) {
 141.337 +                trouble = true;
 141.338 +            }
 141.339 +        }
 141.340 +    }
 141.341 +
 141.342 +    private boolean closing = false; /* To avoid recursive closing */
 141.343 +
 141.344 +    /**
 141.345 +     * Closes the stream.  This is done by flushing the stream and then closing
 141.346 +     * the underlying output stream.
 141.347 +     *
 141.348 +     * @see        java.io.OutputStream#close()
 141.349 +     */
 141.350 +    public void close() {
 141.351 +        synchronized (this) {
 141.352 +            if (! closing) {
 141.353 +                closing = true;
 141.354 +                try {
 141.355 +                    textOut.close();
 141.356 +                    out.close();
 141.357 +                }
 141.358 +                catch (IOException x) {
 141.359 +                    trouble = true;
 141.360 +                }
 141.361 +                textOut = null;
 141.362 +                charOut = null;
 141.363 +                out = null;
 141.364 +            }
 141.365 +        }
 141.366 +    }
 141.367 +
 141.368 +    /**
 141.369 +     * Flushes the stream and checks its error state. The internal error state
 141.370 +     * is set to <code>true</code> when the underlying output stream throws an
 141.371 +     * <code>IOException</code> other than <code>InterruptedIOException</code>,
 141.372 +     * and when the <code>setError</code> method is invoked.  If an operation
 141.373 +     * on the underlying output stream throws an
 141.374 +     * <code>InterruptedIOException</code>, then the <code>PrintStream</code>
 141.375 +     * converts the exception back into an interrupt by doing:
 141.376 +     * <pre>
 141.377 +     *     Thread.currentThread().interrupt();
 141.378 +     * </pre>
 141.379 +     * or the equivalent.
 141.380 +     *
 141.381 +     * @return <code>true</code> if and only if this stream has encountered an
 141.382 +     *         <code>IOException</code> other than
 141.383 +     *         <code>InterruptedIOException</code>, or the
 141.384 +     *         <code>setError</code> method has been invoked
 141.385 +     */
 141.386 +    public boolean checkError() {
 141.387 +        if (out != null)
 141.388 +            flush();
 141.389 +        if (out instanceof java.io.PrintStream) {
 141.390 +            PrintStream ps = (PrintStream) out;
 141.391 +            return ps.checkError();
 141.392 +        }
 141.393 +        return trouble;
 141.394 +    }
 141.395 +
 141.396 +    /**
 141.397 +     * Sets the error state of the stream to <code>true</code>.
 141.398 +     *
 141.399 +     * <p> This method will cause subsequent invocations of {@link
 141.400 +     * #checkError()} to return <tt>true</tt> until {@link
 141.401 +     * #clearError()} is invoked.
 141.402 +     *
 141.403 +     * @since JDK1.1
 141.404 +     */
 141.405 +    protected void setError() {
 141.406 +        trouble = true;
 141.407 +    }
 141.408 +
 141.409 +    /**
 141.410 +     * Clears the internal error state of this stream.
 141.411 +     *
 141.412 +     * <p> This method will cause subsequent invocations of {@link
 141.413 +     * #checkError()} to return <tt>false</tt> until another write
 141.414 +     * operation fails and invokes {@link #setError()}.
 141.415 +     *
 141.416 +     * @since 1.6
 141.417 +     */
 141.418 +    protected void clearError() {
 141.419 +        trouble = false;
 141.420 +    }
 141.421 +
 141.422 +    /*
 141.423 +     * Exception-catching, synchronized output operations,
 141.424 +     * which also implement the write() methods of OutputStream
 141.425 +     */
 141.426 +
 141.427 +    /**
 141.428 +     * Writes the specified byte to this stream.  If the byte is a newline and
 141.429 +     * automatic flushing is enabled then the <code>flush</code> method will be
 141.430 +     * invoked.
 141.431 +     *
 141.432 +     * <p> Note that the byte is written as given; to write a character that
 141.433 +     * will be translated according to the platform's default character
 141.434 +     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
 141.435 +     * methods.
 141.436 +     *
 141.437 +     * @param  b  The byte to be written
 141.438 +     * @see #print(char)
 141.439 +     * @see #println(char)
 141.440 +     */
 141.441 +    public void write(int b) {
 141.442 +        try {
 141.443 +            synchronized (this) {
 141.444 +                ensureOpen();
 141.445 +                out.write(b);
 141.446 +                if ((b == '\n') && autoFlush)
 141.447 +                    out.flush();
 141.448 +            }
 141.449 +        }
 141.450 +        catch (InterruptedIOException x) {
 141.451 +            Thread.currentThread().interrupt();
 141.452 +        }
 141.453 +        catch (IOException x) {
 141.454 +            trouble = true;
 141.455 +        }
 141.456 +    }
 141.457 +
 141.458 +    /**
 141.459 +     * Writes <code>len</code> bytes from the specified byte array starting at
 141.460 +     * offset <code>off</code> to this stream.  If automatic flushing is
 141.461 +     * enabled then the <code>flush</code> method will be invoked.
 141.462 +     *
 141.463 +     * <p> Note that the bytes will be written as given; to write characters
 141.464 +     * that will be translated according to the platform's default character
 141.465 +     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
 141.466 +     * methods.
 141.467 +     *
 141.468 +     * @param  buf   A byte array
 141.469 +     * @param  off   Offset from which to start taking bytes
 141.470 +     * @param  len   Number of bytes to write
 141.471 +     */
 141.472 +    public void write(byte buf[], int off, int len) {
 141.473 +        try {
 141.474 +            synchronized (this) {
 141.475 +                ensureOpen();
 141.476 +                out.write(buf, off, len);
 141.477 +                if (autoFlush)
 141.478 +                    out.flush();
 141.479 +            }
 141.480 +        }
 141.481 +        catch (InterruptedIOException x) {
 141.482 +            Thread.currentThread().interrupt();
 141.483 +        }
 141.484 +        catch (IOException x) {
 141.485 +            trouble = true;
 141.486 +        }
 141.487 +    }
 141.488 +
 141.489 +    /*
 141.490 +     * The following private methods on the text- and character-output streams
 141.491 +     * always flush the stream buffers, so that writes to the underlying byte
 141.492 +     * stream occur as promptly as with the original PrintStream.
 141.493 +     */
 141.494 +
 141.495 +    private void write(char buf[]) {
 141.496 +        try {
 141.497 +            synchronized (this) {
 141.498 +                ensureOpen();
 141.499 +                textOut.write(buf);
 141.500 +                textOut.flushBuffer();
 141.501 +                charOut.flushBuffer();
 141.502 +                if (autoFlush) {
 141.503 +                    for (int i = 0; i < buf.length; i++)
 141.504 +                        if (buf[i] == '\n')
 141.505 +                            out.flush();
 141.506 +                }
 141.507 +            }
 141.508 +        }
 141.509 +        catch (InterruptedIOException x) {
 141.510 +            Thread.currentThread().interrupt();
 141.511 +        }
 141.512 +        catch (IOException x) {
 141.513 +            trouble = true;
 141.514 +        }
 141.515 +    }
 141.516 +
 141.517 +    private void write(String s) {
 141.518 +        try {
 141.519 +            synchronized (this) {
 141.520 +                ensureOpen();
 141.521 +                textOut.write(s);
 141.522 +                textOut.flushBuffer();
 141.523 +                charOut.flushBuffer();
 141.524 +                if (autoFlush && (s.indexOf('\n') >= 0))
 141.525 +                    out.flush();
 141.526 +            }
 141.527 +        }
 141.528 +        catch (InterruptedIOException x) {
 141.529 +            Thread.currentThread().interrupt();
 141.530 +        }
 141.531 +        catch (IOException x) {
 141.532 +            trouble = true;
 141.533 +        }
 141.534 +    }
 141.535 +
 141.536 +    private void newLine() {
 141.537 +        try {
 141.538 +            synchronized (this) {
 141.539 +                ensureOpen();
 141.540 +                textOut.newLine();
 141.541 +                textOut.flushBuffer();
 141.542 +                charOut.flushBuffer();
 141.543 +                if (autoFlush)
 141.544 +                    out.flush();
 141.545 +            }
 141.546 +        }
 141.547 +        catch (InterruptedIOException x) {
 141.548 +            Thread.currentThread().interrupt();
 141.549 +        }
 141.550 +        catch (IOException x) {
 141.551 +            trouble = true;
 141.552 +        }
 141.553 +    }
 141.554 +
 141.555 +    /* Methods that do not terminate lines */
 141.556 +
 141.557 +    /**
 141.558 +     * Prints a boolean value.  The string produced by <code>{@link
 141.559 +     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
 141.560 +     * according to the platform's default character encoding, and these bytes
 141.561 +     * are written in exactly the manner of the
 141.562 +     * <code>{@link #write(int)}</code> method.
 141.563 +     *
 141.564 +     * @param      b   The <code>boolean</code> to be printed
 141.565 +     */
 141.566 +    public void print(boolean b) {
 141.567 +        write(b ? "true" : "false");
 141.568 +    }
 141.569 +
 141.570 +    /**
 141.571 +     * Prints a character.  The character is translated into one or more bytes
 141.572 +     * according to the platform's default character encoding, and these bytes
 141.573 +     * are written in exactly the manner of the
 141.574 +     * <code>{@link #write(int)}</code> method.
 141.575 +     *
 141.576 +     * @param      c   The <code>char</code> to be printed
 141.577 +     */
 141.578 +    public void print(char c) {
 141.579 +        write(String.valueOf(c));
 141.580 +    }
 141.581 +
 141.582 +    /**
 141.583 +     * Prints an integer.  The string produced by <code>{@link
 141.584 +     * java.lang.String#valueOf(int)}</code> is translated into bytes
 141.585 +     * according to the platform's default character encoding, and these bytes
 141.586 +     * are written in exactly the manner of the
 141.587 +     * <code>{@link #write(int)}</code> method.
 141.588 +     *
 141.589 +     * @param      i   The <code>int</code> to be printed
 141.590 +     * @see        java.lang.Integer#toString(int)
 141.591 +     */
 141.592 +    public void print(int i) {
 141.593 +        write(String.valueOf(i));
 141.594 +    }
 141.595 +
 141.596 +    /**
 141.597 +     * Prints a long integer.  The string produced by <code>{@link
 141.598 +     * java.lang.String#valueOf(long)}</code> is translated into bytes
 141.599 +     * according to the platform's default character encoding, and these bytes
 141.600 +     * are written in exactly the manner of the
 141.601 +     * <code>{@link #write(int)}</code> method.
 141.602 +     *
 141.603 +     * @param      l   The <code>long</code> to be printed
 141.604 +     * @see        java.lang.Long#toString(long)
 141.605 +     */
 141.606 +    public void print(long l) {
 141.607 +        write(String.valueOf(l));
 141.608 +    }
 141.609 +
 141.610 +    /**
 141.611 +     * Prints a floating-point number.  The string produced by <code>{@link
 141.612 +     * java.lang.String#valueOf(float)}</code> is translated into bytes
 141.613 +     * according to the platform's default character encoding, and these bytes
 141.614 +     * are written in exactly the manner of the
 141.615 +     * <code>{@link #write(int)}</code> method.
 141.616 +     *
 141.617 +     * @param      f   The <code>float</code> to be printed
 141.618 +     * @see        java.lang.Float#toString(float)
 141.619 +     */
 141.620 +    public void print(float f) {
 141.621 +        write(String.valueOf(f));
 141.622 +    }
 141.623 +
 141.624 +    /**
 141.625 +     * Prints a double-precision floating-point number.  The string produced by
 141.626 +     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
 141.627 +     * bytes according to the platform's default character encoding, and these
 141.628 +     * bytes are written in exactly the manner of the <code>{@link
 141.629 +     * #write(int)}</code> method.
 141.630 +     *
 141.631 +     * @param      d   The <code>double</code> to be printed
 141.632 +     * @see        java.lang.Double#toString(double)
 141.633 +     */
 141.634 +    public void print(double d) {
 141.635 +        write(String.valueOf(d));
 141.636 +    }
 141.637 +
 141.638 +    /**
 141.639 +     * Prints an array of characters.  The characters are converted into bytes
 141.640 +     * according to the platform's default character encoding, and these bytes
 141.641 +     * are written in exactly the manner of the
 141.642 +     * <code>{@link #write(int)}</code> method.
 141.643 +     *
 141.644 +     * @param      s   The array of chars to be printed
 141.645 +     *
 141.646 +     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
 141.647 +     */
 141.648 +    public void print(char s[]) {
 141.649 +        write(s);
 141.650 +    }
 141.651 +
 141.652 +    /**
 141.653 +     * Prints a string.  If the argument is <code>null</code> then the string
 141.654 +     * <code>"null"</code> is printed.  Otherwise, the string's characters are
 141.655 +     * converted into bytes according to the platform's default character
 141.656 +     * encoding, and these bytes are written in exactly the manner of the
 141.657 +     * <code>{@link #write(int)}</code> method.
 141.658 +     *
 141.659 +     * @param      s   The <code>String</code> to be printed
 141.660 +     */
 141.661 +    public void print(String s) {
 141.662 +        if (s == null) {
 141.663 +            s = "null";
 141.664 +        }
 141.665 +        write(s);
 141.666 +    }
 141.667 +
 141.668 +    /**
 141.669 +     * Prints an object.  The string produced by the <code>{@link
 141.670 +     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
 141.671 +     * according to the platform's default character encoding, and these bytes
 141.672 +     * are written in exactly the manner of the
 141.673 +     * <code>{@link #write(int)}</code> method.
 141.674 +     *
 141.675 +     * @param      obj   The <code>Object</code> to be printed
 141.676 +     * @see        java.lang.Object#toString()
 141.677 +     */
 141.678 +    public void print(Object obj) {
 141.679 +        write(String.valueOf(obj));
 141.680 +    }
 141.681 +
 141.682 +
 141.683 +    /* Methods that do terminate lines */
 141.684 +
 141.685 +    /**
 141.686 +     * Terminates the current line by writing the line separator string.  The
 141.687 +     * line separator string is defined by the system property
 141.688 +     * <code>line.separator</code>, and is not necessarily a single newline
 141.689 +     * character (<code>'\n'</code>).
 141.690 +     */
 141.691 +    public void println() {
 141.692 +        newLine();
 141.693 +    }
 141.694 +
 141.695 +    /**
 141.696 +     * Prints a boolean and then terminate the line.  This method behaves as
 141.697 +     * though it invokes <code>{@link #print(boolean)}</code> and then
 141.698 +     * <code>{@link #println()}</code>.
 141.699 +     *
 141.700 +     * @param x  The <code>boolean</code> to be printed
 141.701 +     */
 141.702 +    public void println(boolean x) {
 141.703 +        synchronized (this) {
 141.704 +            print(x);
 141.705 +            newLine();
 141.706 +        }
 141.707 +    }
 141.708 +
 141.709 +    /**
 141.710 +     * Prints a character and then terminate the line.  This method behaves as
 141.711 +     * though it invokes <code>{@link #print(char)}</code> and then
 141.712 +     * <code>{@link #println()}</code>.
 141.713 +     *
 141.714 +     * @param x  The <code>char</code> to be printed.
 141.715 +     */
 141.716 +    public void println(char x) {
 141.717 +        synchronized (this) {
 141.718 +            print(x);
 141.719 +            newLine();
 141.720 +        }
 141.721 +    }
 141.722 +
 141.723 +    /**
 141.724 +     * Prints an integer and then terminate the line.  This method behaves as
 141.725 +     * though it invokes <code>{@link #print(int)}</code> and then
 141.726 +     * <code>{@link #println()}</code>.
 141.727 +     *
 141.728 +     * @param x  The <code>int</code> to be printed.
 141.729 +     */
 141.730 +    public void println(int x) {
 141.731 +        synchronized (this) {
 141.732 +            print(x);
 141.733 +            newLine();
 141.734 +        }
 141.735 +    }
 141.736 +
 141.737 +    /**
 141.738 +     * Prints a long and then terminate the line.  This method behaves as
 141.739 +     * though it invokes <code>{@link #print(long)}</code> and then
 141.740 +     * <code>{@link #println()}</code>.
 141.741 +     *
 141.742 +     * @param x  a The <code>long</code> to be printed.
 141.743 +     */
 141.744 +    public void println(long x) {
 141.745 +        synchronized (this) {
 141.746 +            print(x);
 141.747 +            newLine();
 141.748 +        }
 141.749 +    }
 141.750 +
 141.751 +    /**
 141.752 +     * Prints a float and then terminate the line.  This method behaves as
 141.753 +     * though it invokes <code>{@link #print(float)}</code> and then
 141.754 +     * <code>{@link #println()}</code>.
 141.755 +     *
 141.756 +     * @param x  The <code>float</code> to be printed.
 141.757 +     */
 141.758 +    public void println(float x) {
 141.759 +        synchronized (this) {
 141.760 +            print(x);
 141.761 +            newLine();
 141.762 +        }
 141.763 +    }
 141.764 +
 141.765 +    /**
 141.766 +     * Prints a double and then terminate the line.  This method behaves as
 141.767 +     * though it invokes <code>{@link #print(double)}</code> and then
 141.768 +     * <code>{@link #println()}</code>.
 141.769 +     *
 141.770 +     * @param x  The <code>double</code> to be printed.
 141.771 +     */
 141.772 +    public void println(double x) {
 141.773 +        synchronized (this) {
 141.774 +            print(x);
 141.775 +            newLine();
 141.776 +        }
 141.777 +    }
 141.778 +
 141.779 +    /**
 141.780 +     * Prints an array of characters and then terminate the line.  This method
 141.781 +     * behaves as though it invokes <code>{@link #print(char[])}</code> and
 141.782 +     * then <code>{@link #println()}</code>.
 141.783 +     *
 141.784 +     * @param x  an array of chars to print.
 141.785 +     */
 141.786 +    public void println(char x[]) {
 141.787 +        synchronized (this) {
 141.788 +            print(x);
 141.789 +            newLine();
 141.790 +        }
 141.791 +    }
 141.792 +
 141.793 +    /**
 141.794 +     * Prints a String and then terminate the line.  This method behaves as
 141.795 +     * though it invokes <code>{@link #print(String)}</code> and then
 141.796 +     * <code>{@link #println()}</code>.
 141.797 +     *
 141.798 +     * @param x  The <code>String</code> to be printed.
 141.799 +     */
 141.800 +    public void println(String x) {
 141.801 +        synchronized (this) {
 141.802 +            print(x);
 141.803 +            newLine();
 141.804 +        }
 141.805 +    }
 141.806 +
 141.807 +    /**
 141.808 +     * Prints an Object and then terminate the line.  This method calls
 141.809 +     * at first String.valueOf(x) to get the printed object's string value,
 141.810 +     * then behaves as
 141.811 +     * though it invokes <code>{@link #print(String)}</code> and then
 141.812 +     * <code>{@link #println()}</code>.
 141.813 +     *
 141.814 +     * @param x  The <code>Object</code> to be printed.
 141.815 +     */
 141.816 +    public void println(Object x) {
 141.817 +        String s = String.valueOf(x);
 141.818 +        synchronized (this) {
 141.819 +            print(s);
 141.820 +            newLine();
 141.821 +        }
 141.822 +    }
 141.823 +
 141.824 +
 141.825 +    /**
 141.826 +     * A convenience method to write a formatted string to this output stream
 141.827 +     * using the specified format string and arguments.
 141.828 +     *
 141.829 +     * <p> An invocation of this method of the form <tt>out.printf(format,
 141.830 +     * args)</tt> behaves in exactly the same way as the invocation
 141.831 +     *
 141.832 +     * <pre>
 141.833 +     *     out.format(format, args) </pre>
 141.834 +     *
 141.835 +     * @param  format
 141.836 +     *         A format string as described in <a
 141.837 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 141.838 +     *
 141.839 +     * @param  args
 141.840 +     *         Arguments referenced by the format specifiers in the format
 141.841 +     *         string.  If there are more arguments than format specifiers, the
 141.842 +     *         extra arguments are ignored.  The number of arguments is
 141.843 +     *         variable and may be zero.  The maximum number of arguments is
 141.844 +     *         limited by the maximum dimension of a Java array as defined by
 141.845 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 141.846 +     *         The behaviour on a
 141.847 +     *         <tt>null</tt> argument depends on the <a
 141.848 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 141.849 +     *
 141.850 +     * @throws  IllegalFormatException
 141.851 +     *          If a format string contains an illegal syntax, a format
 141.852 +     *          specifier that is incompatible with the given arguments,
 141.853 +     *          insufficient arguments given the format string, or other
 141.854 +     *          illegal conditions.  For specification of all possible
 141.855 +     *          formatting errors, see the <a
 141.856 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 141.857 +     *          formatter class specification.
 141.858 +     *
 141.859 +     * @throws  NullPointerException
 141.860 +     *          If the <tt>format</tt> is <tt>null</tt>
 141.861 +     *
 141.862 +     * @return  This output stream
 141.863 +     *
 141.864 +     * @since  1.5
 141.865 +     */
 141.866 +    public PrintStream printf(String format, Object ... args) {
 141.867 +        append(format).append(Arrays.toString(args));
 141.868 +        return this;
 141.869 +    }
 141.870 +
 141.871 +    /**
 141.872 +     * A convenience method to write a formatted string to this output stream
 141.873 +     * using the specified format string and arguments.
 141.874 +     *
 141.875 +     * <p> An invocation of this method of the form <tt>out.printf(l, format,
 141.876 +     * args)</tt> behaves in exactly the same way as the invocation
 141.877 +     *
 141.878 +     * <pre>
 141.879 +     *     out.format(l, format, args) </pre>
 141.880 +     *
 141.881 +     * @param  l
 141.882 +     *         The {@linkplain java.util.Locale locale} to apply during
 141.883 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 141.884 +     *         is applied.
 141.885 +     *
 141.886 +     * @param  format
 141.887 +     *         A format string as described in <a
 141.888 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 141.889 +     *
 141.890 +     * @param  args
 141.891 +     *         Arguments referenced by the format specifiers in the format
 141.892 +     *         string.  If there are more arguments than format specifiers, the
 141.893 +     *         extra arguments are ignored.  The number of arguments is
 141.894 +     *         variable and may be zero.  The maximum number of arguments is
 141.895 +     *         limited by the maximum dimension of a Java array as defined by
 141.896 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 141.897 +     *         The behaviour on a
 141.898 +     *         <tt>null</tt> argument depends on the <a
 141.899 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 141.900 +     *
 141.901 +     * @throws  IllegalFormatException
 141.902 +     *          If a format string contains an illegal syntax, a format
 141.903 +     *          specifier that is incompatible with the given arguments,
 141.904 +     *          insufficient arguments given the format string, or other
 141.905 +     *          illegal conditions.  For specification of all possible
 141.906 +     *          formatting errors, see the <a
 141.907 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 141.908 +     *          formatter class specification.
 141.909 +     *
 141.910 +     * @throws  NullPointerException
 141.911 +     *          If the <tt>format</tt> is <tt>null</tt>
 141.912 +     *
 141.913 +     * @return  This output stream
 141.914 +     *
 141.915 +     * @since  1.5
 141.916 +     */
 141.917 +//    public PrintStream printf(Locale l, String format, Object ... args) {
 141.918 +//        return format(l, format, args);
 141.919 +//    }
 141.920 +
 141.921 +    /**
 141.922 +     * Writes a formatted string to this output stream using the specified
 141.923 +     * format string and arguments.
 141.924 +     *
 141.925 +     * <p> The locale always used is the one returned by {@link
 141.926 +     * java.util.Locale#getDefault() Locale.getDefault()}, regardless of any
 141.927 +     * previous invocations of other formatting methods on this object.
 141.928 +     *
 141.929 +     * @param  format
 141.930 +     *         A format string as described in <a
 141.931 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 141.932 +     *
 141.933 +     * @param  args
 141.934 +     *         Arguments referenced by the format specifiers in the format
 141.935 +     *         string.  If there are more arguments than format specifiers, the
 141.936 +     *         extra arguments are ignored.  The number of arguments is
 141.937 +     *         variable and may be zero.  The maximum number of arguments is
 141.938 +     *         limited by the maximum dimension of a Java array as defined by
 141.939 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 141.940 +     *         The behaviour on a
 141.941 +     *         <tt>null</tt> argument depends on the <a
 141.942 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 141.943 +     *
 141.944 +     * @throws  IllegalFormatException
 141.945 +     *          If a format string contains an illegal syntax, a format
 141.946 +     *          specifier that is incompatible with the given arguments,
 141.947 +     *          insufficient arguments given the format string, or other
 141.948 +     *          illegal conditions.  For specification of all possible
 141.949 +     *          formatting errors, see the <a
 141.950 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 141.951 +     *          formatter class specification.
 141.952 +     *
 141.953 +     * @throws  NullPointerException
 141.954 +     *          If the <tt>format</tt> is <tt>null</tt>
 141.955 +     *
 141.956 +     * @return  This output stream
 141.957 +     *
 141.958 +     * @since  1.5
 141.959 +     */
 141.960 +//    public PrintStream format(String format, Object ... args) {
 141.961 +//        try {
 141.962 +//            synchronized (this) {
 141.963 +//                ensureOpen();
 141.964 +//                if ((formatter == null)
 141.965 +//                    || (formatter.locale() != Locale.getDefault()))
 141.966 +//                    formatter = new Formatter((Appendable) this);
 141.967 +//                formatter.format(Locale.getDefault(), format, args);
 141.968 +//            }
 141.969 +//        } catch (InterruptedIOException x) {
 141.970 +//            Thread.currentThread().interrupt();
 141.971 +//        } catch (IOException x) {
 141.972 +//            trouble = true;
 141.973 +//        }
 141.974 +//        return this;
 141.975 +//    }
 141.976 +
 141.977 +    /**
 141.978 +     * Writes a formatted string to this output stream using the specified
 141.979 +     * format string and arguments.
 141.980 +     *
 141.981 +     * @param  l
 141.982 +     *         The {@linkplain java.util.Locale locale} to apply during
 141.983 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 141.984 +     *         is applied.
 141.985 +     *
 141.986 +     * @param  format
 141.987 +     *         A format string as described in <a
 141.988 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 141.989 +     *
 141.990 +     * @param  args
 141.991 +     *         Arguments referenced by the format specifiers in the format
 141.992 +     *         string.  If there are more arguments than format specifiers, the
 141.993 +     *         extra arguments are ignored.  The number of arguments is
 141.994 +     *         variable and may be zero.  The maximum number of arguments is
 141.995 +     *         limited by the maximum dimension of a Java array as defined by
 141.996 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 141.997 +     *         The behaviour on a
 141.998 +     *         <tt>null</tt> argument depends on the <a
 141.999 +     *         href="../util/Formatter.html#syntax">conversion</a>.
141.1000 +     *
141.1001 +     * @throws  IllegalFormatException
141.1002 +     *          If a format string contains an illegal syntax, a format
141.1003 +     *          specifier that is incompatible with the given arguments,
141.1004 +     *          insufficient arguments given the format string, or other
141.1005 +     *          illegal conditions.  For specification of all possible
141.1006 +     *          formatting errors, see the <a
141.1007 +     *          href="../util/Formatter.html#detail">Details</a> section of the
141.1008 +     *          formatter class specification.
141.1009 +     *
141.1010 +     * @throws  NullPointerException
141.1011 +     *          If the <tt>format</tt> is <tt>null</tt>
141.1012 +     *
141.1013 +     * @return  This output stream
141.1014 +     *
141.1015 +     * @since  1.5
141.1016 +     */
141.1017 +////    public PrintStream format(Locale l, String format, Object ... args) {
141.1018 +////        try {
141.1019 +////            synchronized (this) {
141.1020 +////                ensureOpen();
141.1021 +////                if ((formatter == null)
141.1022 +////                    || (formatter.locale() != l))
141.1023 +////                    formatter = new Formatter(this, l);
141.1024 +////                formatter.format(l, format, args);
141.1025 +////            }
141.1026 +////        } catch (InterruptedIOException x) {
141.1027 +////            Thread.currentThread().interrupt();
141.1028 +////        } catch (IOException x) {
141.1029 +////            trouble = true;
141.1030 +////        }
141.1031 +////        return this;
141.1032 +////    }
141.1033 +
141.1034 +    /**
141.1035 +     * Appends the specified character sequence to this output stream.
141.1036 +     *
141.1037 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
141.1038 +     * behaves in exactly the same way as the invocation
141.1039 +     *
141.1040 +     * <pre>
141.1041 +     *     out.print(csq.toString()) </pre>
141.1042 +     *
141.1043 +     * <p> Depending on the specification of <tt>toString</tt> for the
141.1044 +     * character sequence <tt>csq</tt>, the entire sequence may not be
141.1045 +     * appended.  For instance, invoking then <tt>toString</tt> method of a
141.1046 +     * character buffer will return a subsequence whose content depends upon
141.1047 +     * the buffer's position and limit.
141.1048 +     *
141.1049 +     * @param  csq
141.1050 +     *         The character sequence to append.  If <tt>csq</tt> is
141.1051 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
141.1052 +     *         appended to this output stream.
141.1053 +     *
141.1054 +     * @return  This output stream
141.1055 +     *
141.1056 +     * @since  1.5
141.1057 +     */
141.1058 +    public PrintStream append(CharSequence csq) {
141.1059 +        if (csq == null)
141.1060 +            print("null");
141.1061 +        else
141.1062 +            print(csq.toString());
141.1063 +        return this;
141.1064 +    }
141.1065 +
141.1066 +    /**
141.1067 +     * Appends a subsequence of the specified character sequence to this output
141.1068 +     * stream.
141.1069 +     *
141.1070 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
141.1071 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
141.1072 +     * exactly the same way as the invocation
141.1073 +     *
141.1074 +     * <pre>
141.1075 +     *     out.print(csq.subSequence(start, end).toString()) </pre>
141.1076 +     *
141.1077 +     * @param  csq
141.1078 +     *         The character sequence from which a subsequence will be
141.1079 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
141.1080 +     *         will be appended as if <tt>csq</tt> contained the four
141.1081 +     *         characters <tt>"null"</tt>.
141.1082 +     *
141.1083 +     * @param  start
141.1084 +     *         The index of the first character in the subsequence
141.1085 +     *
141.1086 +     * @param  end
141.1087 +     *         The index of the character following the last character in the
141.1088 +     *         subsequence
141.1089 +     *
141.1090 +     * @return  This output stream
141.1091 +     *
141.1092 +     * @throws  IndexOutOfBoundsException
141.1093 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
141.1094 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
141.1095 +     *          <tt>csq.length()</tt>
141.1096 +     *
141.1097 +     * @since  1.5
141.1098 +     */
141.1099 +    public PrintStream append(CharSequence csq, int start, int end) {
141.1100 +        CharSequence cs = (csq == null ? "null" : csq);
141.1101 +        write(cs.subSequence(start, end).toString());
141.1102 +        return this;
141.1103 +    }
141.1104 +
141.1105 +    /**
141.1106 +     * Appends the specified character to this output stream.
141.1107 +     *
141.1108 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
141.1109 +     * behaves in exactly the same way as the invocation
141.1110 +     *
141.1111 +     * <pre>
141.1112 +     *     out.print(c) </pre>
141.1113 +     *
141.1114 +     * @param  c
141.1115 +     *         The 16-bit character to append
141.1116 +     *
141.1117 +     * @return  This output stream
141.1118 +     *
141.1119 +     * @since  1.5
141.1120 +     */
141.1121 +    public PrintStream append(char c) {
141.1122 +        print(c);
141.1123 +        return this;
141.1124 +    }
141.1125 +
141.1126 +}
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/rt/emul/compact/src/main/java/java/io/PrintWriter.java	Wed Apr 30 15:04:10 2014 +0200
   142.3 @@ -0,0 +1,1029 @@
   142.4 +/*
   142.5 + * Copyright (c) 1996, 2011, 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.io;
  142.30 +
  142.31 +import java.io.PrintStream.Formatter;
  142.32 +import java.nio.charset.Charset;
  142.33 +import java.util.Arrays;
  142.34 +
  142.35 +/**
  142.36 + * Prints formatted representations of objects to a text-output stream.  This
  142.37 + * class implements all of the <tt>print</tt> methods found in {@link
  142.38 + * PrintStream}.  It does not contain methods for writing raw bytes, for which
  142.39 + * a program should use unencoded byte streams.
  142.40 + *
  142.41 + * <p> Unlike the {@link PrintStream} class, if automatic flushing is enabled
  142.42 + * it will be done only when one of the <tt>println</tt>, <tt>printf</tt>, or
  142.43 + * <tt>format</tt> methods is invoked, rather than whenever a newline character
  142.44 + * happens to be output.  These methods use the platform's own notion of line
  142.45 + * separator rather than the newline character.
  142.46 + *
  142.47 + * <p> Methods in this class never throw I/O exceptions, although some of its
  142.48 + * constructors may.  The client may inquire as to whether any errors have
  142.49 + * occurred by invoking {@link #checkError checkError()}.
  142.50 + *
  142.51 + * @author      Frank Yellin
  142.52 + * @author      Mark Reinhold
  142.53 + * @since       JDK1.1
  142.54 + */
  142.55 +
  142.56 +public class PrintWriter extends Writer {
  142.57 +
  142.58 +    /**
  142.59 +     * The underlying character-output stream of this
  142.60 +     * <code>PrintWriter</code>.
  142.61 +     *
  142.62 +     * @since 1.2
  142.63 +     */
  142.64 +    protected Writer out;
  142.65 +
  142.66 +    private final boolean autoFlush;
  142.67 +    private boolean trouble = false;
  142.68 +    private Formatter formatter;
  142.69 +//    private PrintStream psOut = null;
  142.70 +
  142.71 +    /**
  142.72 +     * Line separator string.  This is the value of the line.separator
  142.73 +     * property at the moment that the stream was created.
  142.74 +     */
  142.75 +    private final String lineSeparator;
  142.76 +
  142.77 +    /**
  142.78 +     * Returns a charset object for the given charset name.
  142.79 +     * @throws NullPointerException          is csn is null
  142.80 +     * @throws UnsupportedEncodingException  if the charset is not supported
  142.81 +     */
  142.82 +    private static Charset toCharset(String csn)
  142.83 +        throws UnsupportedEncodingException
  142.84 +    {
  142.85 +        return PrintStream.toCharset(csn);
  142.86 +    }
  142.87 +
  142.88 +    /**
  142.89 +     * Creates a new PrintWriter, without automatic line flushing.
  142.90 +     *
  142.91 +     * @param  out        A character-output stream
  142.92 +     */
  142.93 +    public PrintWriter (Writer out) {
  142.94 +        this(out, false);
  142.95 +    }
  142.96 +
  142.97 +    /**
  142.98 +     * Creates a new PrintWriter.
  142.99 +     *
 142.100 +     * @param  out        A character-output stream
 142.101 +     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 142.102 +     *                    <tt>printf</tt>, or <tt>format</tt> methods will
 142.103 +     *                    flush the output buffer
 142.104 +     */
 142.105 +    public PrintWriter(Writer out,
 142.106 +                       boolean autoFlush) {
 142.107 +        super(out);
 142.108 +        this.out = out;
 142.109 +        this.autoFlush = autoFlush;
 142.110 +        lineSeparator = "\n";
 142.111 +    }
 142.112 +
 142.113 +    /**
 142.114 +     * Creates a new PrintWriter, without automatic line flushing, from an
 142.115 +     * existing OutputStream.  This convenience constructor creates the
 142.116 +     * necessary intermediate OutputStreamWriter, which will convert characters
 142.117 +     * into bytes using the default character encoding.
 142.118 +     *
 142.119 +     * @param  out        An output stream
 142.120 +     *
 142.121 +     * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 142.122 +     */
 142.123 +    public PrintWriter(OutputStream out) {
 142.124 +        this(out, false);
 142.125 +    }
 142.126 +
 142.127 +    /**
 142.128 +     * Creates a new PrintWriter from an existing OutputStream.  This
 142.129 +     * convenience constructor creates the necessary intermediate
 142.130 +     * OutputStreamWriter, which will convert characters into bytes using the
 142.131 +     * default character encoding.
 142.132 +     *
 142.133 +     * @param  out        An output stream
 142.134 +     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 142.135 +     *                    <tt>printf</tt>, or <tt>format</tt> methods will
 142.136 +     *                    flush the output buffer
 142.137 +     *
 142.138 +     * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 142.139 +     */
 142.140 +    public PrintWriter(OutputStream out, boolean autoFlush) {
 142.141 +        this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
 142.142 +
 142.143 +        // save print stream for error propagation
 142.144 +//        if (out instanceof java.io.PrintStream) {
 142.145 +//            psOut = (PrintStream) out;
 142.146 +//        }
 142.147 +    }
 142.148 +
 142.149 +    /**
 142.150 +     * Creates a new PrintWriter, without automatic line flushing, with the
 142.151 +     * specified file name.  This convenience constructor creates the necessary
 142.152 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 142.153 +     * which will encode characters using the {@linkplain
 142.154 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 142.155 +     * instance of the Java virtual machine.
 142.156 +     *
 142.157 +     * @param  fileName
 142.158 +     *         The name of the file to use as the destination of this writer.
 142.159 +     *         If the file exists then it will be truncated to zero size;
 142.160 +     *         otherwise, a new file will be created.  The output will be
 142.161 +     *         written to the file and is buffered.
 142.162 +     *
 142.163 +     * @throws  FileNotFoundException
 142.164 +     *          If the given string does not denote an existing, writable
 142.165 +     *          regular file and a new regular file of that name cannot be
 142.166 +     *          created, or if some other error occurs while opening or
 142.167 +     *          creating the file
 142.168 +     *
 142.169 +     * @throws  SecurityException
 142.170 +     *          If a security manager is present and {@link
 142.171 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 142.172 +     *          access to the file
 142.173 +     *
 142.174 +     * @since  1.5
 142.175 +     */
 142.176 +    public PrintWriter(String fileName) throws FileNotFoundException {
 142.177 +        super();
 142.178 +        throw new FileNotFoundException();
 142.179 +    }
 142.180 +
 142.181 +    /* Private constructor */
 142.182 +    private PrintWriter(Charset charset, File file)
 142.183 +        throws FileNotFoundException
 142.184 +    {
 142.185 +        super();
 142.186 +        throw new FileNotFoundException();
 142.187 +    }
 142.188 +
 142.189 +    /**
 142.190 +     * Creates a new PrintWriter, without automatic line flushing, with the
 142.191 +     * specified file name and charset.  This convenience constructor creates
 142.192 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 142.193 +     * OutputStreamWriter}, which will encode characters using the provided
 142.194 +     * charset.
 142.195 +     *
 142.196 +     * @param  fileName
 142.197 +     *         The name of the file to use as the destination of this writer.
 142.198 +     *         If the file exists then it will be truncated to zero size;
 142.199 +     *         otherwise, a new file will be created.  The output will be
 142.200 +     *         written to the file and is buffered.
 142.201 +     *
 142.202 +     * @param  csn
 142.203 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 142.204 +     *         charset}
 142.205 +     *
 142.206 +     * @throws  FileNotFoundException
 142.207 +     *          If the given string does not denote an existing, writable
 142.208 +     *          regular file and a new regular file of that name cannot be
 142.209 +     *          created, or if some other error occurs while opening or
 142.210 +     *          creating the file
 142.211 +     *
 142.212 +     * @throws  SecurityException
 142.213 +     *          If a security manager is present and {@link
 142.214 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 142.215 +     *          access to the file
 142.216 +     *
 142.217 +     * @throws  UnsupportedEncodingException
 142.218 +     *          If the named charset is not supported
 142.219 +     *
 142.220 +     * @since  1.5
 142.221 +     */
 142.222 +    public PrintWriter(String fileName, String csn)
 142.223 +        throws FileNotFoundException, UnsupportedEncodingException
 142.224 +    {
 142.225 +        this(toCharset(csn), new File(fileName));
 142.226 +    }
 142.227 +
 142.228 +    /**
 142.229 +     * Creates a new PrintWriter, without automatic line flushing, with the
 142.230 +     * specified file.  This convenience constructor creates the necessary
 142.231 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 142.232 +     * which will encode characters using the {@linkplain
 142.233 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 142.234 +     * instance of the Java virtual machine.
 142.235 +     *
 142.236 +     * @param  file
 142.237 +     *         The file to use as the destination of this writer.  If the file
 142.238 +     *         exists then it will be truncated to zero size; otherwise, a new
 142.239 +     *         file will be created.  The output will be written to the file
 142.240 +     *         and is buffered.
 142.241 +     *
 142.242 +     * @throws  FileNotFoundException
 142.243 +     *          If the given file object does not denote an existing, writable
 142.244 +     *          regular file and a new regular file of that name cannot be
 142.245 +     *          created, or if some other error occurs while opening or
 142.246 +     *          creating the file
 142.247 +     *
 142.248 +     * @throws  SecurityException
 142.249 +     *          If a security manager is present and {@link
 142.250 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 142.251 +     *          denies write access to the file
 142.252 +     *
 142.253 +     * @since  1.5
 142.254 +     */
 142.255 +    public PrintWriter(File file) throws FileNotFoundException {
 142.256 +        super();
 142.257 +        throw new FileNotFoundException();
 142.258 +    }
 142.259 +
 142.260 +    /**
 142.261 +     * Creates a new PrintWriter, without automatic line flushing, with the
 142.262 +     * specified file and charset.  This convenience constructor creates the
 142.263 +     * necessary intermediate {@link java.io.OutputStreamWriter
 142.264 +     * OutputStreamWriter}, which will encode characters using the provided
 142.265 +     * charset.
 142.266 +     *
 142.267 +     * @param  file
 142.268 +     *         The file to use as the destination of this writer.  If the file
 142.269 +     *         exists then it will be truncated to zero size; otherwise, a new
 142.270 +     *         file will be created.  The output will be written to the file
 142.271 +     *         and is buffered.
 142.272 +     *
 142.273 +     * @param  csn
 142.274 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 142.275 +     *         charset}
 142.276 +     *
 142.277 +     * @throws  FileNotFoundException
 142.278 +     *          If the given file object does not denote an existing, writable
 142.279 +     *          regular file and a new regular file of that name cannot be
 142.280 +     *          created, or if some other error occurs while opening or
 142.281 +     *          creating the file
 142.282 +     *
 142.283 +     * @throws  SecurityException
 142.284 +     *          If a security manager is present and {@link
 142.285 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 142.286 +     *          denies write access to the file
 142.287 +     *
 142.288 +     * @throws  UnsupportedEncodingException
 142.289 +     *          If the named charset is not supported
 142.290 +     *
 142.291 +     * @since  1.5
 142.292 +     */
 142.293 +    public PrintWriter(File file, String csn)
 142.294 +        throws FileNotFoundException, UnsupportedEncodingException
 142.295 +    {
 142.296 +        this(toCharset(csn), file);
 142.297 +    }
 142.298 +
 142.299 +    /** Checks to make sure that the stream has not been closed */
 142.300 +    private void ensureOpen() throws IOException {
 142.301 +        if (out == null)
 142.302 +            throw new IOException("Stream closed");
 142.303 +    }
 142.304 +
 142.305 +    /**
 142.306 +     * Flushes the stream.
 142.307 +     * @see #checkError()
 142.308 +     */
 142.309 +    public void flush() {
 142.310 +        try {
 142.311 +            synchronized (lock) {
 142.312 +                ensureOpen();
 142.313 +                out.flush();
 142.314 +            }
 142.315 +        }
 142.316 +        catch (IOException x) {
 142.317 +            trouble = true;
 142.318 +        }
 142.319 +    }
 142.320 +
 142.321 +    /**
 142.322 +     * Closes the stream and releases any system resources associated
 142.323 +     * with it. Closing a previously closed stream has no effect.
 142.324 +     *
 142.325 +     * @see #checkError()
 142.326 +     */
 142.327 +    public void close() {
 142.328 +        try {
 142.329 +            synchronized (lock) {
 142.330 +                if (out == null)
 142.331 +                    return;
 142.332 +                out.close();
 142.333 +                out = null;
 142.334 +            }
 142.335 +        }
 142.336 +        catch (IOException x) {
 142.337 +            trouble = true;
 142.338 +        }
 142.339 +    }
 142.340 +
 142.341 +    /**
 142.342 +     * Flushes the stream if it's not closed and checks its error state.
 142.343 +     *
 142.344 +     * @return <code>true</code> if the print stream has encountered an error,
 142.345 +     *          either on the underlying output stream or during a format
 142.346 +     *          conversion.
 142.347 +     */
 142.348 +    public boolean checkError() {
 142.349 +        if (out != null) {
 142.350 +            flush();
 142.351 +        }
 142.352 +        if (out instanceof java.io.PrintWriter) {
 142.353 +            PrintWriter pw = (PrintWriter) out;
 142.354 +            return pw.checkError();
 142.355 +        } else 
 142.356 +//        if (psOut != null) {
 142.357 +//            return psOut.checkError();
 142.358 +//        }
 142.359 +        return trouble;
 142.360 +    }
 142.361 +
 142.362 +    /**
 142.363 +     * Indicates that an error has occurred.
 142.364 +     *
 142.365 +     * <p> This method will cause subsequent invocations of {@link
 142.366 +     * #checkError()} to return <tt>true</tt> until {@link
 142.367 +     * #clearError()} is invoked.
 142.368 +     */
 142.369 +    protected void setError() {
 142.370 +        trouble = true;
 142.371 +    }
 142.372 +
 142.373 +    /**
 142.374 +     * Clears the error state of this stream.
 142.375 +     *
 142.376 +     * <p> This method will cause subsequent invocations of {@link
 142.377 +     * #checkError()} to return <tt>false</tt> until another write
 142.378 +     * operation fails and invokes {@link #setError()}.
 142.379 +     *
 142.380 +     * @since 1.6
 142.381 +     */
 142.382 +    protected void clearError() {
 142.383 +        trouble = false;
 142.384 +    }
 142.385 +
 142.386 +    /*
 142.387 +     * Exception-catching, synchronized output operations,
 142.388 +     * which also implement the write() methods of Writer
 142.389 +     */
 142.390 +
 142.391 +    /**
 142.392 +     * Writes a single character.
 142.393 +     * @param c int specifying a character to be written.
 142.394 +     */
 142.395 +    public void write(int c) {
 142.396 +        try {
 142.397 +            synchronized (lock) {
 142.398 +                ensureOpen();
 142.399 +                out.write(c);
 142.400 +            }
 142.401 +        }
 142.402 +        catch (InterruptedIOException x) {
 142.403 +            Thread.currentThread().interrupt();
 142.404 +        }
 142.405 +        catch (IOException x) {
 142.406 +            trouble = true;
 142.407 +        }
 142.408 +    }
 142.409 +
 142.410 +    /**
 142.411 +     * Writes A Portion of an array of characters.
 142.412 +     * @param buf Array of characters
 142.413 +     * @param off Offset from which to start writing characters
 142.414 +     * @param len Number of characters to write
 142.415 +     */
 142.416 +    public void write(char buf[], int off, int len) {
 142.417 +        try {
 142.418 +            synchronized (lock) {
 142.419 +                ensureOpen();
 142.420 +                out.write(buf, off, len);
 142.421 +            }
 142.422 +        }
 142.423 +        catch (InterruptedIOException x) {
 142.424 +            Thread.currentThread().interrupt();
 142.425 +        }
 142.426 +        catch (IOException x) {
 142.427 +            trouble = true;
 142.428 +        }
 142.429 +    }
 142.430 +
 142.431 +    /**
 142.432 +     * Writes an array of characters.  This method cannot be inherited from the
 142.433 +     * Writer class because it must suppress I/O exceptions.
 142.434 +     * @param buf Array of characters to be written
 142.435 +     */
 142.436 +    public void write(char buf[]) {
 142.437 +        write(buf, 0, buf.length);
 142.438 +    }
 142.439 +
 142.440 +    /**
 142.441 +     * Writes a portion of a string.
 142.442 +     * @param s A String
 142.443 +     * @param off Offset from which to start writing characters
 142.444 +     * @param len Number of characters to write
 142.445 +     */
 142.446 +    public void write(String s, int off, int len) {
 142.447 +        try {
 142.448 +            synchronized (lock) {
 142.449 +                ensureOpen();
 142.450 +                out.write(s, off, len);
 142.451 +            }
 142.452 +        }
 142.453 +        catch (InterruptedIOException x) {
 142.454 +            Thread.currentThread().interrupt();
 142.455 +        }
 142.456 +        catch (IOException x) {
 142.457 +            trouble = true;
 142.458 +        }
 142.459 +    }
 142.460 +
 142.461 +    /**
 142.462 +     * Writes a string.  This method cannot be inherited from the Writer class
 142.463 +     * because it must suppress I/O exceptions.
 142.464 +     * @param s String to be written
 142.465 +     */
 142.466 +    public void write(String s) {
 142.467 +        write(s, 0, s.length());
 142.468 +    }
 142.469 +
 142.470 +    private void newLine() {
 142.471 +        try {
 142.472 +            synchronized (lock) {
 142.473 +                ensureOpen();
 142.474 +                out.write(lineSeparator);
 142.475 +                if (autoFlush)
 142.476 +                    out.flush();
 142.477 +            }
 142.478 +        }
 142.479 +        catch (InterruptedIOException x) {
 142.480 +            Thread.currentThread().interrupt();
 142.481 +        }
 142.482 +        catch (IOException x) {
 142.483 +            trouble = true;
 142.484 +        }
 142.485 +    }
 142.486 +
 142.487 +    /* Methods that do not terminate lines */
 142.488 +
 142.489 +    /**
 142.490 +     * Prints a boolean value.  The string produced by <code>{@link
 142.491 +     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
 142.492 +     * according to the platform's default character encoding, and these bytes
 142.493 +     * are written in exactly the manner of the <code>{@link
 142.494 +     * #write(int)}</code> method.
 142.495 +     *
 142.496 +     * @param      b   The <code>boolean</code> to be printed
 142.497 +     */
 142.498 +    public void print(boolean b) {
 142.499 +        write(b ? "true" : "false");
 142.500 +    }
 142.501 +
 142.502 +    /**
 142.503 +     * Prints a character.  The character is translated into one or more bytes
 142.504 +     * according to the platform's default character encoding, and these bytes
 142.505 +     * are written in exactly the manner of the <code>{@link
 142.506 +     * #write(int)}</code> method.
 142.507 +     *
 142.508 +     * @param      c   The <code>char</code> to be printed
 142.509 +     */
 142.510 +    public void print(char c) {
 142.511 +        write(c);
 142.512 +    }
 142.513 +
 142.514 +    /**
 142.515 +     * Prints an integer.  The string produced by <code>{@link
 142.516 +     * java.lang.String#valueOf(int)}</code> is translated into bytes according
 142.517 +     * to the platform's default character encoding, and these bytes are
 142.518 +     * written in exactly the manner of the <code>{@link #write(int)}</code>
 142.519 +     * method.
 142.520 +     *
 142.521 +     * @param      i   The <code>int</code> to be printed
 142.522 +     * @see        java.lang.Integer#toString(int)
 142.523 +     */
 142.524 +    public void print(int i) {
 142.525 +        write(String.valueOf(i));
 142.526 +    }
 142.527 +
 142.528 +    /**
 142.529 +     * Prints a long integer.  The string produced by <code>{@link
 142.530 +     * java.lang.String#valueOf(long)}</code> is translated into bytes
 142.531 +     * according to the platform's default character encoding, and these bytes
 142.532 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 142.533 +     * method.
 142.534 +     *
 142.535 +     * @param      l   The <code>long</code> to be printed
 142.536 +     * @see        java.lang.Long#toString(long)
 142.537 +     */
 142.538 +    public void print(long l) {
 142.539 +        write(String.valueOf(l));
 142.540 +    }
 142.541 +
 142.542 +    /**
 142.543 +     * Prints a floating-point number.  The string produced by <code>{@link
 142.544 +     * java.lang.String#valueOf(float)}</code> is translated into bytes
 142.545 +     * according to the platform's default character encoding, and these bytes
 142.546 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 142.547 +     * method.
 142.548 +     *
 142.549 +     * @param      f   The <code>float</code> to be printed
 142.550 +     * @see        java.lang.Float#toString(float)
 142.551 +     */
 142.552 +    public void print(float f) {
 142.553 +        write(String.valueOf(f));
 142.554 +    }
 142.555 +
 142.556 +    /**
 142.557 +     * Prints a double-precision floating-point number.  The string produced by
 142.558 +     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
 142.559 +     * bytes according to the platform's default character encoding, and these
 142.560 +     * bytes are written in exactly the manner of the <code>{@link
 142.561 +     * #write(int)}</code> method.
 142.562 +     *
 142.563 +     * @param      d   The <code>double</code> to be printed
 142.564 +     * @see        java.lang.Double#toString(double)
 142.565 +     */
 142.566 +    public void print(double d) {
 142.567 +        write(String.valueOf(d));
 142.568 +    }
 142.569 +
 142.570 +    /**
 142.571 +     * Prints an array of characters.  The characters are converted into bytes
 142.572 +     * according to the platform's default character encoding, and these bytes
 142.573 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 142.574 +     * method.
 142.575 +     *
 142.576 +     * @param      s   The array of chars to be printed
 142.577 +     *
 142.578 +     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
 142.579 +     */
 142.580 +    public void print(char s[]) {
 142.581 +        write(s);
 142.582 +    }
 142.583 +
 142.584 +    /**
 142.585 +     * Prints a string.  If the argument is <code>null</code> then the string
 142.586 +     * <code>"null"</code> is printed.  Otherwise, the string's characters are
 142.587 +     * converted into bytes according to the platform's default character
 142.588 +     * encoding, and these bytes are written in exactly the manner of the
 142.589 +     * <code>{@link #write(int)}</code> method.
 142.590 +     *
 142.591 +     * @param      s   The <code>String</code> to be printed
 142.592 +     */
 142.593 +    public void print(String s) {
 142.594 +        if (s == null) {
 142.595 +            s = "null";
 142.596 +        }
 142.597 +        write(s);
 142.598 +    }
 142.599 +
 142.600 +    /**
 142.601 +     * Prints an object.  The string produced by the <code>{@link
 142.602 +     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
 142.603 +     * according to the platform's default character encoding, and these bytes
 142.604 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 142.605 +     * method.
 142.606 +     *
 142.607 +     * @param      obj   The <code>Object</code> to be printed
 142.608 +     * @see        java.lang.Object#toString()
 142.609 +     */
 142.610 +    public void print(Object obj) {
 142.611 +        write(String.valueOf(obj));
 142.612 +    }
 142.613 +
 142.614 +    /* Methods that do terminate lines */
 142.615 +
 142.616 +    /**
 142.617 +     * Terminates the current line by writing the line separator string.  The
 142.618 +     * line separator string is defined by the system property
 142.619 +     * <code>line.separator</code>, and is not necessarily a single newline
 142.620 +     * character (<code>'\n'</code>).
 142.621 +     */
 142.622 +    public void println() {
 142.623 +        newLine();
 142.624 +    }
 142.625 +
 142.626 +    /**
 142.627 +     * Prints a boolean value and then terminates the line.  This method behaves
 142.628 +     * as though it invokes <code>{@link #print(boolean)}</code> and then
 142.629 +     * <code>{@link #println()}</code>.
 142.630 +     *
 142.631 +     * @param x the <code>boolean</code> value to be printed
 142.632 +     */
 142.633 +    public void println(boolean x) {
 142.634 +        synchronized (lock) {
 142.635 +            print(x);
 142.636 +            println();
 142.637 +        }
 142.638 +    }
 142.639 +
 142.640 +    /**
 142.641 +     * Prints a character and then terminates the line.  This method behaves as
 142.642 +     * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
 142.643 +     * #println()}</code>.
 142.644 +     *
 142.645 +     * @param x the <code>char</code> value to be printed
 142.646 +     */
 142.647 +    public void println(char x) {
 142.648 +        synchronized (lock) {
 142.649 +            print(x);
 142.650 +            println();
 142.651 +        }
 142.652 +    }
 142.653 +
 142.654 +    /**
 142.655 +     * Prints an integer and then terminates the line.  This method behaves as
 142.656 +     * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
 142.657 +     * #println()}</code>.
 142.658 +     *
 142.659 +     * @param x the <code>int</code> value to be printed
 142.660 +     */
 142.661 +    public void println(int x) {
 142.662 +        synchronized (lock) {
 142.663 +            print(x);
 142.664 +            println();
 142.665 +        }
 142.666 +    }
 142.667 +
 142.668 +    /**
 142.669 +     * Prints a long integer and then terminates the line.  This method behaves
 142.670 +     * as though it invokes <code>{@link #print(long)}</code> and then
 142.671 +     * <code>{@link #println()}</code>.
 142.672 +     *
 142.673 +     * @param x the <code>long</code> value to be printed
 142.674 +     */
 142.675 +    public void println(long x) {
 142.676 +        synchronized (lock) {
 142.677 +            print(x);
 142.678 +            println();
 142.679 +        }
 142.680 +    }
 142.681 +
 142.682 +    /**
 142.683 +     * Prints a floating-point number and then terminates the line.  This method
 142.684 +     * behaves as though it invokes <code>{@link #print(float)}</code> and then
 142.685 +     * <code>{@link #println()}</code>.
 142.686 +     *
 142.687 +     * @param x the <code>float</code> value to be printed
 142.688 +     */
 142.689 +    public void println(float x) {
 142.690 +        synchronized (lock) {
 142.691 +            print(x);
 142.692 +            println();
 142.693 +        }
 142.694 +    }
 142.695 +
 142.696 +    /**
 142.697 +     * Prints a double-precision floating-point number and then terminates the
 142.698 +     * line.  This method behaves as though it invokes <code>{@link
 142.699 +     * #print(double)}</code> and then <code>{@link #println()}</code>.
 142.700 +     *
 142.701 +     * @param x the <code>double</code> value to be printed
 142.702 +     */
 142.703 +    public void println(double x) {
 142.704 +        synchronized (lock) {
 142.705 +            print(x);
 142.706 +            println();
 142.707 +        }
 142.708 +    }
 142.709 +
 142.710 +    /**
 142.711 +     * Prints an array of characters and then terminates the line.  This method
 142.712 +     * behaves as though it invokes <code>{@link #print(char[])}</code> and then
 142.713 +     * <code>{@link #println()}</code>.
 142.714 +     *
 142.715 +     * @param x the array of <code>char</code> values to be printed
 142.716 +     */
 142.717 +    public void println(char x[]) {
 142.718 +        synchronized (lock) {
 142.719 +            print(x);
 142.720 +            println();
 142.721 +        }
 142.722 +    }
 142.723 +
 142.724 +    /**
 142.725 +     * Prints a String and then terminates the line.  This method behaves as
 142.726 +     * though it invokes <code>{@link #print(String)}</code> and then
 142.727 +     * <code>{@link #println()}</code>.
 142.728 +     *
 142.729 +     * @param x the <code>String</code> value to be printed
 142.730 +     */
 142.731 +    public void println(String x) {
 142.732 +        synchronized (lock) {
 142.733 +            print(x);
 142.734 +            println();
 142.735 +        }
 142.736 +    }
 142.737 +
 142.738 +    /**
 142.739 +     * Prints an Object and then terminates the line.  This method calls
 142.740 +     * at first String.valueOf(x) to get the printed object's string value,
 142.741 +     * then behaves as
 142.742 +     * though it invokes <code>{@link #print(String)}</code> and then
 142.743 +     * <code>{@link #println()}</code>.
 142.744 +     *
 142.745 +     * @param x  The <code>Object</code> to be printed.
 142.746 +     */
 142.747 +    public void println(Object x) {
 142.748 +        String s = String.valueOf(x);
 142.749 +        synchronized (lock) {
 142.750 +            print(s);
 142.751 +            println();
 142.752 +        }
 142.753 +    }
 142.754 +
 142.755 +    /**
 142.756 +     * A convenience method to write a formatted string to this writer using
 142.757 +     * the specified format string and arguments.  If automatic flushing is
 142.758 +     * enabled, calls to this method will flush the output buffer.
 142.759 +     *
 142.760 +     * <p> An invocation of this method of the form <tt>out.printf(format,
 142.761 +     * args)</tt> behaves in exactly the same way as the invocation
 142.762 +     *
 142.763 +     * <pre>
 142.764 +     *     out.format(format, args) </pre>
 142.765 +     *
 142.766 +     * @param  format
 142.767 +     *         A format string as described in <a
 142.768 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 142.769 +     *
 142.770 +     * @param  args
 142.771 +     *         Arguments referenced by the format specifiers in the format
 142.772 +     *         string.  If there are more arguments than format specifiers, the
 142.773 +     *         extra arguments are ignored.  The number of arguments is
 142.774 +     *         variable and may be zero.  The maximum number of arguments is
 142.775 +     *         limited by the maximum dimension of a Java array as defined by
 142.776 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 142.777 +     *         The behaviour on a
 142.778 +     *         <tt>null</tt> argument depends on the <a
 142.779 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 142.780 +     *
 142.781 +     * @throws  IllegalFormatException
 142.782 +     *          If a format string contains an illegal syntax, a format
 142.783 +     *          specifier that is incompatible with the given arguments,
 142.784 +     *          insufficient arguments given the format string, or other
 142.785 +     *          illegal conditions.  For specification of all possible
 142.786 +     *          formatting errors, see the <a
 142.787 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 142.788 +     *          formatter class specification.
 142.789 +     *
 142.790 +     * @throws  NullPointerException
 142.791 +     *          If the <tt>format</tt> is <tt>null</tt>
 142.792 +     *
 142.793 +     * @return  This writer
 142.794 +     *
 142.795 +     * @since  1.5
 142.796 +     */
 142.797 +    public PrintWriter printf(String format, Object ... args) {
 142.798 +        return format(format, args);
 142.799 +    }
 142.800 +
 142.801 +    /**
 142.802 +     * A convenience method to write a formatted string to this writer using
 142.803 +     * the specified format string and arguments.  If automatic flushing is
 142.804 +     * enabled, calls to this method will flush the output buffer.
 142.805 +     *
 142.806 +     * <p> An invocation of this method of the form <tt>out.printf(l, format,
 142.807 +     * args)</tt> behaves in exactly the same way as the invocation
 142.808 +     *
 142.809 +     * <pre>
 142.810 +     *     out.format(l, format, args) </pre>
 142.811 +     *
 142.812 +     * @param  l
 142.813 +     *         The {@linkplain java.util.Locale locale} to apply during
 142.814 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 142.815 +     *         is applied.
 142.816 +     *
 142.817 +     * @param  format
 142.818 +     *         A format string as described in <a
 142.819 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 142.820 +     *
 142.821 +     * @param  args
 142.822 +     *         Arguments referenced by the format specifiers in the format
 142.823 +     *         string.  If there are more arguments than format specifiers, the
 142.824 +     *         extra arguments are ignored.  The number of arguments is
 142.825 +     *         variable and may be zero.  The maximum number of arguments is
 142.826 +     *         limited by the maximum dimension of a Java array as defined by
 142.827 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 142.828 +     *         The behaviour on a
 142.829 +     *         <tt>null</tt> argument depends on the <a
 142.830 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 142.831 +     *
 142.832 +     * @throws  IllegalFormatException
 142.833 +     *          If a format string contains an illegal syntax, a format
 142.834 +     *          specifier that is incompatible with the given arguments,
 142.835 +     *          insufficient arguments given the format string, or other
 142.836 +     *          illegal conditions.  For specification of all possible
 142.837 +     *          formatting errors, see the <a
 142.838 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 142.839 +     *          formatter class specification.
 142.840 +     *
 142.841 +     * @throws  NullPointerException
 142.842 +     *          If the <tt>format</tt> is <tt>null</tt>
 142.843 +     *
 142.844 +     * @return  This writer
 142.845 +     *
 142.846 +     * @since  1.5
 142.847 +     */
 142.848 +//    public PrintWriter printf(Locale l, String format, Object ... args) {
 142.849 +//        return format(l, format, args);
 142.850 +//    }
 142.851 +
 142.852 +    /**
 142.853 +     * Writes a formatted string to this writer using the specified format
 142.854 +     * string and arguments.  If automatic flushing is enabled, calls to this
 142.855 +     * method will flush the output buffer.
 142.856 +     *
 142.857 +     * <p> The locale always used is the one returned by {@link
 142.858 +     * java.util.Locale#getDefault() Locale.getDefault()}, regardless of any
 142.859 +     * previous invocations of other formatting methods on this object.
 142.860 +     *
 142.861 +     * @param  format
 142.862 +     *         A format string as described in <a
 142.863 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 142.864 +     *
 142.865 +     * @param  args
 142.866 +     *         Arguments referenced by the format specifiers in the format
 142.867 +     *         string.  If there are more arguments than format specifiers, the
 142.868 +     *         extra arguments are ignored.  The number of arguments is
 142.869 +     *         variable and may be zero.  The maximum number of arguments is
 142.870 +     *         limited by the maximum dimension of a Java array as defined by
 142.871 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 142.872 +     *         The behaviour on a
 142.873 +     *         <tt>null</tt> argument depends on the <a
 142.874 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 142.875 +     *
 142.876 +     * @throws  IllegalFormatException
 142.877 +     *          If a format string contains an illegal syntax, a format
 142.878 +     *          specifier that is incompatible with the given arguments,
 142.879 +     *          insufficient arguments given the format string, or other
 142.880 +     *          illegal conditions.  For specification of all possible
 142.881 +     *          formatting errors, see the <a
 142.882 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 142.883 +     *          Formatter class specification.
 142.884 +     *
 142.885 +     * @throws  NullPointerException
 142.886 +     *          If the <tt>format</tt> is <tt>null</tt>
 142.887 +     *
 142.888 +     * @return  This writer
 142.889 +     *
 142.890 +     * @since  1.5
 142.891 +     */
 142.892 +    public PrintWriter format(String format, Object ... args) {
 142.893 +        append(format).append(Arrays.toString(args));
 142.894 +        return this;
 142.895 +    }
 142.896 +
 142.897 +    /**
 142.898 +     * Writes a formatted string to this writer using the specified format
 142.899 +     * string and arguments.  If automatic flushing is enabled, calls to this
 142.900 +     * method will flush the output buffer.
 142.901 +     *
 142.902 +     * @param  l
 142.903 +     *         The {@linkplain java.util.Locale locale} to apply during
 142.904 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 142.905 +     *         is applied.
 142.906 +     *
 142.907 +     * @param  format
 142.908 +     *         A format string as described in <a
 142.909 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 142.910 +     *
 142.911 +     * @param  args
 142.912 +     *         Arguments referenced by the format specifiers in the format
 142.913 +     *         string.  If there are more arguments than format specifiers, the
 142.914 +     *         extra arguments are ignored.  The number of arguments is
 142.915 +     *         variable and may be zero.  The maximum number of arguments is
 142.916 +     *         limited by the maximum dimension of a Java array as defined by
 142.917 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 142.918 +     *         The behaviour on a
 142.919 +     *         <tt>null</tt> argument depends on the <a
 142.920 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 142.921 +     *
 142.922 +     * @throws  IllegalFormatException
 142.923 +     *          If a format string contains an illegal syntax, a format
 142.924 +     *          specifier that is incompatible with the given arguments,
 142.925 +     *          insufficient arguments given the format string, or other
 142.926 +     *          illegal conditions.  For specification of all possible
 142.927 +     *          formatting errors, see the <a
 142.928 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 142.929 +     *          formatter class specification.
 142.930 +     *
 142.931 +     * @throws  NullPointerException
 142.932 +     *          If the <tt>format</tt> is <tt>null</tt>
 142.933 +     *
 142.934 +     * @return  This writer
 142.935 +     *
 142.936 +     * @since  1.5
 142.937 +     */
 142.938 +//    public PrintWriter format(Locale l, String format, Object ... args) {
 142.939 +//        return format(format, args);
 142.940 +//    }
 142.941 +
 142.942 +    /**
 142.943 +     * Appends the specified character sequence to this writer.
 142.944 +     *
 142.945 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
 142.946 +     * behaves in exactly the same way as the invocation
 142.947 +     *
 142.948 +     * <pre>
 142.949 +     *     out.write(csq.toString()) </pre>
 142.950 +     *
 142.951 +     * <p> Depending on the specification of <tt>toString</tt> for the
 142.952 +     * character sequence <tt>csq</tt>, the entire sequence may not be
 142.953 +     * appended. For instance, invoking the <tt>toString</tt> method of a
 142.954 +     * character buffer will return a subsequence whose content depends upon
 142.955 +     * the buffer's position and limit.
 142.956 +     *
 142.957 +     * @param  csq
 142.958 +     *         The character sequence to append.  If <tt>csq</tt> is
 142.959 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
 142.960 +     *         appended to this writer.
 142.961 +     *
 142.962 +     * @return  This writer
 142.963 +     *
 142.964 +     * @since  1.5
 142.965 +     */
 142.966 +    public PrintWriter append(CharSequence csq) {
 142.967 +        if (csq == null)
 142.968 +            write("null");
 142.969 +        else
 142.970 +            write(csq.toString());
 142.971 +        return this;
 142.972 +    }
 142.973 +
 142.974 +    /**
 142.975 +     * Appends a subsequence of the specified character sequence to this writer.
 142.976 +     *
 142.977 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
 142.978 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
 142.979 +     * exactly the same way as the invocation
 142.980 +     *
 142.981 +     * <pre>
 142.982 +     *     out.write(csq.subSequence(start, end).toString()) </pre>
 142.983 +     *
 142.984 +     * @param  csq
 142.985 +     *         The character sequence from which a subsequence will be
 142.986 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
 142.987 +     *         will be appended as if <tt>csq</tt> contained the four
 142.988 +     *         characters <tt>"null"</tt>.
 142.989 +     *
 142.990 +     * @param  start
 142.991 +     *         The index of the first character in the subsequence
 142.992 +     *
 142.993 +     * @param  end
 142.994 +     *         The index of the character following the last character in the
 142.995 +     *         subsequence
 142.996 +     *
 142.997 +     * @return  This writer
 142.998 +     *
 142.999 +     * @throws  IndexOutOfBoundsException
142.1000 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
142.1001 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
142.1002 +     *          <tt>csq.length()</tt>
142.1003 +     *
142.1004 +     * @since  1.5
142.1005 +     */
142.1006 +    public PrintWriter append(CharSequence csq, int start, int end) {
142.1007 +        CharSequence cs = (csq == null ? "null" : csq);
142.1008 +        write(cs.subSequence(start, end).toString());
142.1009 +        return this;
142.1010 +    }
142.1011 +
142.1012 +    /**
142.1013 +     * Appends the specified character to this writer.
142.1014 +     *
142.1015 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
142.1016 +     * behaves in exactly the same way as the invocation
142.1017 +     *
142.1018 +     * <pre>
142.1019 +     *     out.write(c) </pre>
142.1020 +     *
142.1021 +     * @param  c
142.1022 +     *         The 16-bit character to append
142.1023 +     *
142.1024 +     * @return  This writer
142.1025 +     *
142.1026 +     * @since 1.5
142.1027 +     */
142.1028 +    public PrintWriter append(char c) {
142.1029 +        write(c);
142.1030 +        return this;
142.1031 +    }
142.1032 +}
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/rt/emul/compact/src/main/java/java/io/StringReader.java	Wed Apr 30 15:04:10 2014 +0200
   143.3 @@ -0,0 +1,201 @@
   143.4 +/*
   143.5 + * Copyright (c) 1996, 2005, 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 +package java.io;
  143.30 +
  143.31 +
  143.32 +/**
  143.33 + * A character stream whose source is a string.
  143.34 + *
  143.35 + * @author      Mark Reinhold
  143.36 + * @since       JDK1.1
  143.37 + */
  143.38 +
  143.39 +public class StringReader extends Reader {
  143.40 +
  143.41 +    private String str;
  143.42 +    private int length;
  143.43 +    private int next = 0;
  143.44 +    private int mark = 0;
  143.45 +
  143.46 +    /**
  143.47 +     * Creates a new string reader.
  143.48 +     *
  143.49 +     * @param s  String providing the character stream.
  143.50 +     */
  143.51 +    public StringReader(String s) {
  143.52 +        this.str = s;
  143.53 +        this.length = s.length();
  143.54 +    }
  143.55 +
  143.56 +    /** Check to make sure that the stream has not been closed */
  143.57 +    private void ensureOpen() throws IOException {
  143.58 +        if (str == null)
  143.59 +            throw new IOException("Stream closed");
  143.60 +    }
  143.61 +
  143.62 +    /**
  143.63 +     * Reads a single character.
  143.64 +     *
  143.65 +     * @return     The character read, or -1 if the end of the stream has been
  143.66 +     *             reached
  143.67 +     *
  143.68 +     * @exception  IOException  If an I/O error occurs
  143.69 +     */
  143.70 +    public int read() throws IOException {
  143.71 +        synchronized (lock) {
  143.72 +            ensureOpen();
  143.73 +            if (next >= length)
  143.74 +                return -1;
  143.75 +            return str.charAt(next++);
  143.76 +        }
  143.77 +    }
  143.78 +
  143.79 +    /**
  143.80 +     * Reads characters into a portion of an array.
  143.81 +     *
  143.82 +     * @param      cbuf  Destination buffer
  143.83 +     * @param      off   Offset at which to start writing characters
  143.84 +     * @param      len   Maximum number of characters to read
  143.85 +     *
  143.86 +     * @return     The number of characters read, or -1 if the end of the
  143.87 +     *             stream has been reached
  143.88 +     *
  143.89 +     * @exception  IOException  If an I/O error occurs
  143.90 +     */
  143.91 +    public int read(char cbuf[], int off, int len) throws IOException {
  143.92 +        synchronized (lock) {
  143.93 +            ensureOpen();
  143.94 +            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  143.95 +                ((off + len) > cbuf.length) || ((off + len) < 0)) {
  143.96 +                throw new IndexOutOfBoundsException();
  143.97 +            } else if (len == 0) {
  143.98 +                return 0;
  143.99 +            }
 143.100 +            if (next >= length)
 143.101 +                return -1;
 143.102 +            int n = Math.min(length - next, len);
 143.103 +            str.getChars(next, next + n, cbuf, off);
 143.104 +            next += n;
 143.105 +            return n;
 143.106 +        }
 143.107 +    }
 143.108 +
 143.109 +    /**
 143.110 +     * Skips the specified number of characters in the stream. Returns
 143.111 +     * the number of characters that were skipped.
 143.112 +     *
 143.113 +     * <p>The <code>ns</code> parameter may be negative, even though the
 143.114 +     * <code>skip</code> method of the {@link Reader} superclass throws
 143.115 +     * an exception in this case. Negative values of <code>ns</code> cause the
 143.116 +     * stream to skip backwards. Negative return values indicate a skip
 143.117 +     * backwards. It is not possible to skip backwards past the beginning of
 143.118 +     * the string.
 143.119 +     *
 143.120 +     * <p>If the entire string has been read or skipped, then this method has
 143.121 +     * no effect and always returns 0.
 143.122 +     *
 143.123 +     * @exception  IOException  If an I/O error occurs
 143.124 +     */
 143.125 +    public long skip(long ns) throws IOException {
 143.126 +        synchronized (lock) {
 143.127 +            ensureOpen();
 143.128 +            if (next >= length)
 143.129 +                return 0;
 143.130 +            // Bound skip by beginning and end of the source
 143.131 +            long n = Math.min(length - next, ns);
 143.132 +            n = Math.max(-next, n);
 143.133 +            next += n;
 143.134 +            return n;
 143.135 +        }
 143.136 +    }
 143.137 +
 143.138 +    /**
 143.139 +     * Tells whether this stream is ready to be read.
 143.140 +     *
 143.141 +     * @return True if the next read() is guaranteed not to block for input
 143.142 +     *
 143.143 +     * @exception  IOException  If the stream is closed
 143.144 +     */
 143.145 +    public boolean ready() throws IOException {
 143.146 +        synchronized (lock) {
 143.147 +        ensureOpen();
 143.148 +        return true;
 143.149 +        }
 143.150 +    }
 143.151 +
 143.152 +    /**
 143.153 +     * Tells whether this stream supports the mark() operation, which it does.
 143.154 +     */
 143.155 +    public boolean markSupported() {
 143.156 +        return true;
 143.157 +    }
 143.158 +
 143.159 +    /**
 143.160 +     * Marks the present position in the stream.  Subsequent calls to reset()
 143.161 +     * will reposition the stream to this point.
 143.162 +     *
 143.163 +     * @param  readAheadLimit  Limit on the number of characters that may be
 143.164 +     *                         read while still preserving the mark.  Because
 143.165 +     *                         the stream's input comes from a string, there
 143.166 +     *                         is no actual limit, so this argument must not
 143.167 +     *                         be negative, but is otherwise ignored.
 143.168 +     *
 143.169 +     * @exception  IllegalArgumentException  If readAheadLimit is < 0
 143.170 +     * @exception  IOException  If an I/O error occurs
 143.171 +     */
 143.172 +    public void mark(int readAheadLimit) throws IOException {
 143.173 +        if (readAheadLimit < 0){
 143.174 +            throw new IllegalArgumentException("Read-ahead limit < 0");
 143.175 +        }
 143.176 +        synchronized (lock) {
 143.177 +            ensureOpen();
 143.178 +            mark = next;
 143.179 +        }
 143.180 +    }
 143.181 +
 143.182 +    /**
 143.183 +     * Resets the stream to the most recent mark, or to the beginning of the
 143.184 +     * string if it has never been marked.
 143.185 +     *
 143.186 +     * @exception  IOException  If an I/O error occurs
 143.187 +     */
 143.188 +    public void reset() throws IOException {
 143.189 +        synchronized (lock) {
 143.190 +            ensureOpen();
 143.191 +            next = mark;
 143.192 +        }
 143.193 +    }
 143.194 +
 143.195 +    /**
 143.196 +     * Closes the stream and releases any system resources associated with
 143.197 +     * it. Once the stream has been closed, further read(),
 143.198 +     * ready(), mark(), or reset() invocations will throw an IOException.
 143.199 +     * Closing a previously closed stream has no effect.
 143.200 +     */
 143.201 +    public void close() {
 143.202 +        str = null;
 143.203 +    }
 143.204 +}
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/rt/emul/compact/src/main/java/java/io/StringWriter.java	Wed Apr 30 15:04:10 2014 +0200
   144.3 @@ -0,0 +1,236 @@
   144.4 +/*
   144.5 + * Copyright (c) 1996, 2004, 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 +package java.io;
  144.30 +
  144.31 +
  144.32 +/**
  144.33 + * A character stream that collects its output in a string buffer, which can
  144.34 + * then be used to construct a string.
  144.35 + * <p>
  144.36 + * Closing a <tt>StringWriter</tt> has no effect. The methods in this class
  144.37 + * can be called after the stream has been closed without generating an
  144.38 + * <tt>IOException</tt>.
  144.39 + *
  144.40 + * @author      Mark Reinhold
  144.41 + * @since       JDK1.1
  144.42 + */
  144.43 +
  144.44 +public class StringWriter extends Writer {
  144.45 +
  144.46 +    private StringBuffer buf;
  144.47 +
  144.48 +    /**
  144.49 +     * Create a new string writer using the default initial string-buffer
  144.50 +     * size.
  144.51 +     */
  144.52 +    public StringWriter() {
  144.53 +        buf = new StringBuffer();
  144.54 +        lock = buf;
  144.55 +    }
  144.56 +
  144.57 +    /**
  144.58 +     * Create a new string writer using the specified initial string-buffer
  144.59 +     * size.
  144.60 +     *
  144.61 +     * @param initialSize
  144.62 +     *        The number of <tt>char</tt> values that will fit into this buffer
  144.63 +     *        before it is automatically expanded
  144.64 +     *
  144.65 +     * @throws IllegalArgumentException
  144.66 +     *         If <tt>initialSize</tt> is negative
  144.67 +     */
  144.68 +    public StringWriter(int initialSize) {
  144.69 +        if (initialSize < 0) {
  144.70 +            throw new IllegalArgumentException("Negative buffer size");
  144.71 +        }
  144.72 +        buf = new StringBuffer(initialSize);
  144.73 +        lock = buf;
  144.74 +    }
  144.75 +
  144.76 +    /**
  144.77 +     * Write a single character.
  144.78 +     */
  144.79 +    public void write(int c) {
  144.80 +        buf.append((char) c);
  144.81 +    }
  144.82 +
  144.83 +    /**
  144.84 +     * Write a portion of an array of characters.
  144.85 +     *
  144.86 +     * @param  cbuf  Array of characters
  144.87 +     * @param  off   Offset from which to start writing characters
  144.88 +     * @param  len   Number of characters to write
  144.89 +     */
  144.90 +    public void write(char cbuf[], int off, int len) {
  144.91 +        if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  144.92 +            ((off + len) > cbuf.length) || ((off + len) < 0)) {
  144.93 +            throw new IndexOutOfBoundsException();
  144.94 +        } else if (len == 0) {
  144.95 +            return;
  144.96 +        }
  144.97 +        buf.append(cbuf, off, len);
  144.98 +    }
  144.99 +
 144.100 +    /**
 144.101 +     * Write a string.
 144.102 +     */
 144.103 +    public void write(String str) {
 144.104 +        buf.append(str);
 144.105 +    }
 144.106 +
 144.107 +    /**
 144.108 +     * Write a portion of a string.
 144.109 +     *
 144.110 +     * @param  str  String to be written
 144.111 +     * @param  off  Offset from which to start writing characters
 144.112 +     * @param  len  Number of characters to write
 144.113 +     */
 144.114 +    public void write(String str, int off, int len)  {
 144.115 +        buf.append(str.substring(off, off + len));
 144.116 +    }
 144.117 +
 144.118 +    /**
 144.119 +     * Appends the specified character sequence to this writer.
 144.120 +     *
 144.121 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
 144.122 +     * behaves in exactly the same way as the invocation
 144.123 +     *
 144.124 +     * <pre>
 144.125 +     *     out.write(csq.toString()) </pre>
 144.126 +     *
 144.127 +     * <p> Depending on the specification of <tt>toString</tt> for the
 144.128 +     * character sequence <tt>csq</tt>, the entire sequence may not be
 144.129 +     * appended. For instance, invoking the <tt>toString</tt> method of a
 144.130 +     * character buffer will return a subsequence whose content depends upon
 144.131 +     * the buffer's position and limit.
 144.132 +     *
 144.133 +     * @param  csq
 144.134 +     *         The character sequence to append.  If <tt>csq</tt> is
 144.135 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
 144.136 +     *         appended to this writer.
 144.137 +     *
 144.138 +     * @return  This writer
 144.139 +     *
 144.140 +     * @since  1.5
 144.141 +     */
 144.142 +    public StringWriter append(CharSequence csq) {
 144.143 +        if (csq == null)
 144.144 +            write("null");
 144.145 +        else
 144.146 +            write(csq.toString());
 144.147 +        return this;
 144.148 +    }
 144.149 +
 144.150 +    /**
 144.151 +     * Appends a subsequence of the specified character sequence to this writer.
 144.152 +     *
 144.153 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
 144.154 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
 144.155 +     * exactly the same way as the invocation
 144.156 +     *
 144.157 +     * <pre>
 144.158 +     *     out.write(csq.subSequence(start, end).toString()) </pre>
 144.159 +     *
 144.160 +     * @param  csq
 144.161 +     *         The character sequence from which a subsequence will be
 144.162 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
 144.163 +     *         will be appended as if <tt>csq</tt> contained the four
 144.164 +     *         characters <tt>"null"</tt>.
 144.165 +     *
 144.166 +     * @param  start
 144.167 +     *         The index of the first character in the subsequence
 144.168 +     *
 144.169 +     * @param  end
 144.170 +     *         The index of the character following the last character in the
 144.171 +     *         subsequence
 144.172 +     *
 144.173 +     * @return  This writer
 144.174 +     *
 144.175 +     * @throws  IndexOutOfBoundsException
 144.176 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
 144.177 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
 144.178 +     *          <tt>csq.length()</tt>
 144.179 +     *
 144.180 +     * @since  1.5
 144.181 +     */
 144.182 +    public StringWriter append(CharSequence csq, int start, int end) {
 144.183 +        CharSequence cs = (csq == null ? "null" : csq);
 144.184 +        write(cs.subSequence(start, end).toString());
 144.185 +        return this;
 144.186 +    }
 144.187 +
 144.188 +    /**
 144.189 +     * Appends the specified character to this writer.
 144.190 +     *
 144.191 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
 144.192 +     * behaves in exactly the same way as the invocation
 144.193 +     *
 144.194 +     * <pre>
 144.195 +     *     out.write(c) </pre>
 144.196 +     *
 144.197 +     * @param  c
 144.198 +     *         The 16-bit character to append
 144.199 +     *
 144.200 +     * @return  This writer
 144.201 +     *
 144.202 +     * @since 1.5
 144.203 +     */
 144.204 +    public StringWriter append(char c) {
 144.205 +        write(c);
 144.206 +        return this;
 144.207 +    }
 144.208 +
 144.209 +    /**
 144.210 +     * Return the buffer's current value as a string.
 144.211 +     */
 144.212 +    public String toString() {
 144.213 +        return buf.toString();
 144.214 +    }
 144.215 +
 144.216 +    /**
 144.217 +     * Return the string buffer itself.
 144.218 +     *
 144.219 +     * @return StringBuffer holding the current buffer value.
 144.220 +     */
 144.221 +    public StringBuffer getBuffer() {
 144.222 +        return buf;
 144.223 +    }
 144.224 +
 144.225 +    /**
 144.226 +     * Flush the stream.
 144.227 +     */
 144.228 +    public void flush() {
 144.229 +    }
 144.230 +
 144.231 +    /**
 144.232 +     * Closing a <tt>StringWriter</tt> has no effect. The methods in this
 144.233 +     * class can be called after the stream has been closed without generating
 144.234 +     * an <tt>IOException</tt>.
 144.235 +     */
 144.236 +    public void close() throws IOException {
 144.237 +    }
 144.238 +
 144.239 +}
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/rt/emul/compact/src/main/java/java/io/SyncFailedException.java	Wed Apr 30 15:04:10 2014 +0200
   145.3 @@ -0,0 +1,48 @@
   145.4 +/*
   145.5 + * Copyright (c) 1996, 2008, 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.io;
  145.30 +
  145.31 +/**
  145.32 + * Signals that a sync operation has failed.
  145.33 + *
  145.34 + * @author  Ken Arnold
  145.35 + * @see     java.io.FileDescriptor#sync
  145.36 + * @see     java.io.IOException
  145.37 + * @since   JDK1.1
  145.38 + */
  145.39 +public class SyncFailedException extends IOException {
  145.40 +    private static final long serialVersionUID = -2353342684412443330L;
  145.41 +
  145.42 +    /**
  145.43 +     * Constructs an SyncFailedException with a detail message.
  145.44 +     * A detail message is a String that describes this particular exception.
  145.45 +     *
  145.46 +     * @param desc  a String describing the exception.
  145.47 +     */
  145.48 +    public SyncFailedException(String desc) {
  145.49 +        super(desc);
  145.50 +    }
  145.51 +}
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/rt/emul/compact/src/main/java/java/io/Writer.java	Wed Apr 30 15:04:10 2014 +0200
   146.3 @@ -0,0 +1,325 @@
   146.4 +/*
   146.5 + * Copyright (c) 1996, 2005, 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 +package java.io;
  146.30 +
  146.31 +
  146.32 +/**
  146.33 + * Abstract class for writing to character streams.  The only methods that a
  146.34 + * subclass must implement are write(char[], int, int), flush(), and close().
  146.35 + * Most subclasses, however, will override some of the methods defined here in
  146.36 + * order to provide higher efficiency, additional functionality, or both.
  146.37 + *
  146.38 + * @see Writer
  146.39 + * @see   BufferedWriter
  146.40 + * @see   CharArrayWriter
  146.41 + * @see   FilterWriter
  146.42 + * @see   OutputStreamWriter
  146.43 + * @see     FileWriter
  146.44 + * @see   PipedWriter
  146.45 + * @see   PrintWriter
  146.46 + * @see   StringWriter
  146.47 + * @see Reader
  146.48 + *
  146.49 + * @author      Mark Reinhold
  146.50 + * @since       JDK1.1
  146.51 + */
  146.52 +
  146.53 +public abstract class Writer implements Appendable, Closeable, Flushable {
  146.54 +
  146.55 +    /**
  146.56 +     * Temporary buffer used to hold writes of strings and single characters
  146.57 +     */
  146.58 +    private char[] writeBuffer;
  146.59 +
  146.60 +    /**
  146.61 +     * Size of writeBuffer, must be >= 1
  146.62 +     */
  146.63 +    private final int writeBufferSize = 1024;
  146.64 +
  146.65 +    /**
  146.66 +     * The object used to synchronize operations on this stream.  For
  146.67 +     * efficiency, a character-stream object may use an object other than
  146.68 +     * itself to protect critical sections.  A subclass should therefore use
  146.69 +     * the object in this field rather than <tt>this</tt> or a synchronized
  146.70 +     * method.
  146.71 +     */
  146.72 +    protected Object lock;
  146.73 +
  146.74 +    /**
  146.75 +     * Creates a new character-stream writer whose critical sections will
  146.76 +     * synchronize on the writer itself.
  146.77 +     */
  146.78 +    protected Writer() {
  146.79 +        this.lock = this;
  146.80 +    }
  146.81 +
  146.82 +    /**
  146.83 +     * Creates a new character-stream writer whose critical sections will
  146.84 +     * synchronize on the given object.
  146.85 +     *
  146.86 +     * @param  lock
  146.87 +     *         Object to synchronize on
  146.88 +     */
  146.89 +    protected Writer(Object lock) {
  146.90 +        if (lock == null) {
  146.91 +            throw new NullPointerException();
  146.92 +        }
  146.93 +        this.lock = lock;
  146.94 +    }
  146.95 +
  146.96 +    /**
  146.97 +     * Writes a single character.  The character to be written is contained in
  146.98 +     * the 16 low-order bits of the given integer value; the 16 high-order bits
  146.99 +     * are ignored.
 146.100 +     *
 146.101 +     * <p> Subclasses that intend to support efficient single-character output
 146.102 +     * should override this method.
 146.103 +     *
 146.104 +     * @param  c
 146.105 +     *         int specifying a character to be written
 146.106 +     *
 146.107 +     * @throws  IOException
 146.108 +     *          If an I/O error occurs
 146.109 +     */
 146.110 +    public void write(int c) throws IOException {
 146.111 +        synchronized (lock) {
 146.112 +            if (writeBuffer == null){
 146.113 +                writeBuffer = new char[writeBufferSize];
 146.114 +            }
 146.115 +            writeBuffer[0] = (char) c;
 146.116 +            write(writeBuffer, 0, 1);
 146.117 +        }
 146.118 +    }
 146.119 +
 146.120 +    /**
 146.121 +     * Writes an array of characters.
 146.122 +     *
 146.123 +     * @param  cbuf
 146.124 +     *         Array of characters to be written
 146.125 +     *
 146.126 +     * @throws  IOException
 146.127 +     *          If an I/O error occurs
 146.128 +     */
 146.129 +    public void write(char cbuf[]) throws IOException {
 146.130 +        write(cbuf, 0, cbuf.length);
 146.131 +    }
 146.132 +
 146.133 +    /**
 146.134 +     * Writes a portion of an array of characters.
 146.135 +     *
 146.136 +     * @param  cbuf
 146.137 +     *         Array of characters
 146.138 +     *
 146.139 +     * @param  off
 146.140 +     *         Offset from which to start writing characters
 146.141 +     *
 146.142 +     * @param  len
 146.143 +     *         Number of characters to write
 146.144 +     *
 146.145 +     * @throws  IOException
 146.146 +     *          If an I/O error occurs
 146.147 +     */
 146.148 +    abstract public void write(char cbuf[], int off, int len) throws IOException;
 146.149 +
 146.150 +    /**
 146.151 +     * Writes a string.
 146.152 +     *
 146.153 +     * @param  str
 146.154 +     *         String to be written
 146.155 +     *
 146.156 +     * @throws  IOException
 146.157 +     *          If an I/O error occurs
 146.158 +     */
 146.159 +    public void write(String str) throws IOException {
 146.160 +        write(str, 0, str.length());
 146.161 +    }
 146.162 +
 146.163 +    /**
 146.164 +     * Writes a portion of a string.
 146.165 +     *
 146.166 +     * @param  str
 146.167 +     *         A String
 146.168 +     *
 146.169 +     * @param  off
 146.170 +     *         Offset from which to start writing characters
 146.171 +     *
 146.172 +     * @param  len
 146.173 +     *         Number of characters to write
 146.174 +     *
 146.175 +     * @throws  IndexOutOfBoundsException
 146.176 +     *          If <tt>off</tt> is negative, or <tt>len</tt> is negative,
 146.177 +     *          or <tt>off+len</tt> is negative or greater than the length
 146.178 +     *          of the given string
 146.179 +     *
 146.180 +     * @throws  IOException
 146.181 +     *          If an I/O error occurs
 146.182 +     */
 146.183 +    public void write(String str, int off, int len) throws IOException {
 146.184 +        synchronized (lock) {
 146.185 +            char cbuf[];
 146.186 +            if (len <= writeBufferSize) {
 146.187 +                if (writeBuffer == null) {
 146.188 +                    writeBuffer = new char[writeBufferSize];
 146.189 +                }
 146.190 +                cbuf = writeBuffer;
 146.191 +            } else {    // Don't permanently allocate very large buffers.
 146.192 +                cbuf = new char[len];
 146.193 +            }
 146.194 +            str.getChars(off, (off + len), cbuf, 0);
 146.195 +            write(cbuf, 0, len);
 146.196 +        }
 146.197 +    }
 146.198 +
 146.199 +    /**
 146.200 +     * Appends the specified character sequence to this writer.
 146.201 +     *
 146.202 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
 146.203 +     * behaves in exactly the same way as the invocation
 146.204 +     *
 146.205 +     * <pre>
 146.206 +     *     out.write(csq.toString()) </pre>
 146.207 +     *
 146.208 +     * <p> Depending on the specification of <tt>toString</tt> for the
 146.209 +     * character sequence <tt>csq</tt>, the entire sequence may not be
 146.210 +     * appended. For instance, invoking the <tt>toString</tt> method of a
 146.211 +     * character buffer will return a subsequence whose content depends upon
 146.212 +     * the buffer's position and limit.
 146.213 +     *
 146.214 +     * @param  csq
 146.215 +     *         The character sequence to append.  If <tt>csq</tt> is
 146.216 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
 146.217 +     *         appended to this writer.
 146.218 +     *
 146.219 +     * @return  This writer
 146.220 +     *
 146.221 +     * @throws  IOException
 146.222 +     *          If an I/O error occurs
 146.223 +     *
 146.224 +     * @since  1.5
 146.225 +     */
 146.226 +    public Writer append(CharSequence csq) throws IOException {
 146.227 +        if (csq == null)
 146.228 +            write("null");
 146.229 +        else
 146.230 +            write(csq.toString());
 146.231 +        return this;
 146.232 +    }
 146.233 +
 146.234 +    /**
 146.235 +     * Appends a subsequence of the specified character sequence to this writer.
 146.236 +     * <tt>Appendable</tt>.
 146.237 +     *
 146.238 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
 146.239 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
 146.240 +     * same way as the invocation
 146.241 +     *
 146.242 +     * <pre>
 146.243 +     *     out.write(csq.subSequence(start, end).toString()) </pre>
 146.244 +     *
 146.245 +     * @param  csq
 146.246 +     *         The character sequence from which a subsequence will be
 146.247 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
 146.248 +     *         will be appended as if <tt>csq</tt> contained the four
 146.249 +     *         characters <tt>"null"</tt>.
 146.250 +     *
 146.251 +     * @param  start
 146.252 +     *         The index of the first character in the subsequence
 146.253 +     *
 146.254 +     * @param  end
 146.255 +     *         The index of the character following the last character in the
 146.256 +     *         subsequence
 146.257 +     *
 146.258 +     * @return  This writer
 146.259 +     *
 146.260 +     * @throws  IndexOutOfBoundsException
 146.261 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
 146.262 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
 146.263 +     *          <tt>csq.length()</tt>
 146.264 +     *
 146.265 +     * @throws  IOException
 146.266 +     *          If an I/O error occurs
 146.267 +     *
 146.268 +     * @since  1.5
 146.269 +     */
 146.270 +    public Writer append(CharSequence csq, int start, int end) throws IOException {
 146.271 +        CharSequence cs = (csq == null ? "null" : csq);
 146.272 +        write(cs.subSequence(start, end).toString());
 146.273 +        return this;
 146.274 +    }
 146.275 +
 146.276 +    /**
 146.277 +     * Appends the specified character to this writer.
 146.278 +     *
 146.279 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
 146.280 +     * behaves in exactly the same way as the invocation
 146.281 +     *
 146.282 +     * <pre>
 146.283 +     *     out.write(c) </pre>
 146.284 +     *
 146.285 +     * @param  c
 146.286 +     *         The 16-bit character to append
 146.287 +     *
 146.288 +     * @return  This writer
 146.289 +     *
 146.290 +     * @throws  IOException
 146.291 +     *          If an I/O error occurs
 146.292 +     *
 146.293 +     * @since 1.5
 146.294 +     */
 146.295 +    public Writer append(char c) throws IOException {
 146.296 +        write(c);
 146.297 +        return this;
 146.298 +    }
 146.299 +
 146.300 +    /**
 146.301 +     * Flushes the stream.  If the stream has saved any characters from the
 146.302 +     * various write() methods in a buffer, write them immediately to their
 146.303 +     * intended destination.  Then, if that destination is another character or
 146.304 +     * byte stream, flush it.  Thus one flush() invocation will flush all the
 146.305 +     * buffers in a chain of Writers and OutputStreams.
 146.306 +     *
 146.307 +     * <p> If the intended destination of this stream is an abstraction provided
 146.308 +     * by the underlying operating system, for example a file, then flushing the
 146.309 +     * stream guarantees only that bytes previously written to the stream are
 146.310 +     * passed to the operating system for writing; it does not guarantee that
 146.311 +     * they are actually written to a physical device such as a disk drive.
 146.312 +     *
 146.313 +     * @throws  IOException
 146.314 +     *          If an I/O error occurs
 146.315 +     */
 146.316 +    abstract public void flush() throws IOException;
 146.317 +
 146.318 +    /**
 146.319 +     * Closes the stream, flushing it first. Once the stream has been closed,
 146.320 +     * further write() or flush() invocations will cause an IOException to be
 146.321 +     * thrown. Closing a previously closed stream has no effect.
 146.322 +     *
 146.323 +     * @throws  IOException
 146.324 +     *          If an I/O error occurs
 146.325 +     */
 146.326 +    abstract public void close() throws IOException;
 146.327 +
 146.328 +}
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/rt/emul/compact/src/main/java/java/lang/StackOverflowError.java	Wed Apr 30 15:04:10 2014 +0200
   147.3 @@ -0,0 +1,55 @@
   147.4 +/*
   147.5 + * Copyright (c) 1994, 2008, 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.lang;
  147.30 +
  147.31 +/**
  147.32 + * Thrown when a stack overflow occurs because an application
  147.33 + * recurses too deeply.
  147.34 + *
  147.35 + * @author unascribed
  147.36 + * @since   JDK1.0
  147.37 + */
  147.38 +public
  147.39 +class StackOverflowError extends VirtualMachineError {
  147.40 +    private static final long serialVersionUID = 8609175038441759607L;
  147.41 +
  147.42 +    /**
  147.43 +     * Constructs a <code>StackOverflowError</code> with no detail message.
  147.44 +     */
  147.45 +    public StackOverflowError() {
  147.46 +        super();
  147.47 +    }
  147.48 +
  147.49 +    /**
  147.50 +     * Constructs a <code>StackOverflowError</code> with the specified
  147.51 +     * detail message.
  147.52 +     *
  147.53 +     * @param   s   the detail message.
  147.54 +     */
  147.55 +    public StackOverflowError(String s) {
  147.56 +        super(s);
  147.57 +    }
  147.58 +}
   148.1 --- a/rt/emul/compact/src/main/java/java/lang/System.java	Tue Apr 29 15:25:58 2014 +0200
   148.2 +++ b/rt/emul/compact/src/main/java/java/lang/System.java	Wed Apr 30 15:04:10 2014 +0200
   148.3 @@ -17,6 +17,15 @@
   148.4   */
   148.5  package java.lang;
   148.6  
   148.7 +import java.io.BufferedOutputStream;
   148.8 +import java.io.ByteArrayInputStream;
   148.9 +import java.io.IOException;
  148.10 +import java.io.InputStream;
  148.11 +import java.io.OutputStream;
  148.12 +import java.io.PrintStream;
  148.13 +import java.util.Properties;
  148.14 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  148.15 +
  148.16  /** Poor man's re-implementation of most important System methods.
  148.17   *
  148.18   * @author Jaroslav Tulach <jtulach@netbeans.org>
  148.19 @@ -33,4 +42,90 @@
  148.20          return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
  148.21      }
  148.22      
  148.23 +    public static int identityHashCode(Object obj) {
  148.24 +        return Class.defaultHashCode(obj);
  148.25 +    }
  148.26 +
  148.27 +    public static String getProperty(String name) {
  148.28 +        if ("os.name".equals(name)) {
  148.29 +            return userAgent();
  148.30 +        }
  148.31 +        return null;
  148.32 +    }
  148.33 +    
  148.34 +    @JavaScriptBody(args = {}, body = "return (typeof navigator !== 'undefined') ? navigator.userAgent : 'unknown';")
  148.35 +    private static native String userAgent();
  148.36 +    
  148.37 +    public static String getProperty(String key, String def) {
  148.38 +        return def;
  148.39 +    }
  148.40 +    
  148.41 +    public static Properties getProperties() {
  148.42 +        throw new SecurityException();
  148.43 +    }
  148.44 +    
  148.45 +    public static void setProperties(Properties p) {
  148.46 +        throw new SecurityException();
  148.47 +    }
  148.48 +    
  148.49 +    /**
  148.50 +     * Returns the system-dependent line separator string.  It always
  148.51 +     * returns the same value - the initial value of the {@linkplain
  148.52 +     * #getProperty(String) system property} {@code line.separator}.
  148.53 +     *
  148.54 +     * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
  148.55 +     * Windows systems it returns {@code "\r\n"}.
  148.56 +     */
  148.57 +    public static String lineSeparator() {
  148.58 +        return "\n";
  148.59 +    }
  148.60 +
  148.61 +    @JavaScriptBody(args = { "exitCode" }, body = "window.close();")
  148.62 +    public static void exit(int exitCode) {
  148.63 +    }
  148.64 +    
  148.65 +    public final static InputStream in;
  148.66 +
  148.67 +    public final static PrintStream out;
  148.68 +
  148.69 +    public final static PrintStream err;
  148.70 +    
  148.71 +    public static void setOut(PrintStream out) {
  148.72 +        throw new SecurityException();
  148.73 +    }
  148.74 +
  148.75 +    public static void setIn(InputStream in) {
  148.76 +        throw new SecurityException();
  148.77 +    }
  148.78 +
  148.79 +    public static void setErr(PrintStream err) {
  148.80 +        throw new SecurityException();
  148.81 +    }
  148.82 +    
  148.83 +    static {
  148.84 +        in = new ByteArrayInputStream(new byte[0]);
  148.85 +        out = new PrintStream(new BufferedOutputStream(new SystemStream("log")));
  148.86 +        err = new PrintStream(new BufferedOutputStream(new SystemStream("warn")));
  148.87 +    }
  148.88 +
  148.89 +    private static final class SystemStream extends OutputStream {
  148.90 +        private final String method;
  148.91 +
  148.92 +        public SystemStream(String method) {
  148.93 +            this.method = method;
  148.94 +        }
  148.95 +
  148.96 +        @Override
  148.97 +        public void write(byte b[], int off, int len) throws IOException {
  148.98 +            write(method, new String(b, off, len, "UTF-8"));
  148.99 +        }
 148.100 +
 148.101 +        @JavaScriptBody(args = { "method", "b" }, body = "if (typeof console !== 'undefined') console[method](b.toString());")
 148.102 +        private static native void write(String method, String b);
 148.103 +
 148.104 +        @Override
 148.105 +        public void write(int b) throws IOException {
 148.106 +            write(new byte[] { (byte)b });
 148.107 +        }
 148.108 +    } // end of SystemStream
 148.109  }
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/rt/emul/compact/src/main/java/java/lang/Thread.java	Wed Apr 30 15:04:10 2014 +0200
   149.3 @@ -0,0 +1,1547 @@
   149.4 +/*
   149.5 + * Copyright (c) 1994, 2011, 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.lang;
  149.30 +
  149.31 +import java.util.Map;
  149.32 +
  149.33 +
  149.34 +/**
  149.35 + * A <i>thread</i> is a thread of execution in a program. The Java
  149.36 + * Virtual Machine allows an application to have multiple threads of
  149.37 + * execution running concurrently.
  149.38 + * <p>
  149.39 + * Every thread has a priority. Threads with higher priority are
  149.40 + * executed in preference to threads with lower priority. Each thread
  149.41 + * may or may not also be marked as a daemon. When code running in
  149.42 + * some thread creates a new <code>Thread</code> object, the new
  149.43 + * thread has its priority initially set equal to the priority of the
  149.44 + * creating thread, and is a daemon thread if and only if the
  149.45 + * creating thread is a daemon.
  149.46 + * <p>
  149.47 + * When a Java Virtual Machine starts up, there is usually a single
  149.48 + * non-daemon thread (which typically calls the method named
  149.49 + * <code>main</code> of some designated class). The Java Virtual
  149.50 + * Machine continues to execute threads until either of the following
  149.51 + * occurs:
  149.52 + * <ul>
  149.53 + * <li>The <code>exit</code> method of class <code>Runtime</code> has been
  149.54 + *     called and the security manager has permitted the exit operation
  149.55 + *     to take place.
  149.56 + * <li>All threads that are not daemon threads have died, either by
  149.57 + *     returning from the call to the <code>run</code> method or by
  149.58 + *     throwing an exception that propagates beyond the <code>run</code>
  149.59 + *     method.
  149.60 + * </ul>
  149.61 + * <p>
  149.62 + * There are two ways to create a new thread of execution. One is to
  149.63 + * declare a class to be a subclass of <code>Thread</code>. This
  149.64 + * subclass should override the <code>run</code> method of class
  149.65 + * <code>Thread</code>. An instance of the subclass can then be
  149.66 + * allocated and started. For example, a thread that computes primes
  149.67 + * larger than a stated value could be written as follows:
  149.68 + * <p><hr><blockquote><pre>
  149.69 + *     class PrimeThread extends Thread {
  149.70 + *         long minPrime;
  149.71 + *         PrimeThread(long minPrime) {
  149.72 + *             this.minPrime = minPrime;
  149.73 + *         }
  149.74 + *
  149.75 + *         public void run() {
  149.76 + *             // compute primes larger than minPrime
  149.77 + *             &nbsp;.&nbsp;.&nbsp;.
  149.78 + *         }
  149.79 + *     }
  149.80 + * </pre></blockquote><hr>
  149.81 + * <p>
  149.82 + * The following code would then create a thread and start it running:
  149.83 + * <p><blockquote><pre>
  149.84 + *     PrimeThread p = new PrimeThread(143);
  149.85 + *     p.start();
  149.86 + * </pre></blockquote>
  149.87 + * <p>
  149.88 + * The other way to create a thread is to declare a class that
  149.89 + * implements the <code>Runnable</code> interface. That class then
  149.90 + * implements the <code>run</code> method. An instance of the class can
  149.91 + * then be allocated, passed as an argument when creating
  149.92 + * <code>Thread</code>, and started. The same example in this other
  149.93 + * style looks like the following:
  149.94 + * <p><hr><blockquote><pre>
  149.95 + *     class PrimeRun implements Runnable {
  149.96 + *         long minPrime;
  149.97 + *         PrimeRun(long minPrime) {
  149.98 + *             this.minPrime = minPrime;
  149.99 + *         }
 149.100 + *
 149.101 + *         public void run() {
 149.102 + *             // compute primes larger than minPrime
 149.103 + *             &nbsp;.&nbsp;.&nbsp;.
 149.104 + *         }
 149.105 + *     }
 149.106 + * </pre></blockquote><hr>
 149.107 + * <p>
 149.108 + * The following code would then create a thread and start it running:
 149.109 + * <p><blockquote><pre>
 149.110 + *     PrimeRun p = new PrimeRun(143);
 149.111 + *     new Thread(p).start();
 149.112 + * </pre></blockquote>
 149.113 + * <p>
 149.114 + * Every thread has a name for identification purposes. More than
 149.115 + * one thread may have the same name. If a name is not specified when
 149.116 + * a thread is created, a new name is generated for it.
 149.117 + * <p>
 149.118 + * Unless otherwise noted, passing a {@code null} argument to a constructor
 149.119 + * or method in this class will cause a {@link NullPointerException} to be
 149.120 + * thrown.
 149.121 + *
 149.122 + * @author  unascribed
 149.123 + * @see     Runnable
 149.124 + * @see     Runtime#exit(int)
 149.125 + * @see     #run()
 149.126 + * @see     #stop()
 149.127 + * @since   JDK1.0
 149.128 + */
 149.129 +public
 149.130 +class Thread implements Runnable {
 149.131 +
 149.132 +    /**
 149.133 +     * The minimum priority that a thread can have.
 149.134 +     */
 149.135 +    public final static int MIN_PRIORITY = 1;
 149.136 +
 149.137 +   /**
 149.138 +     * The default priority that is assigned to a thread.
 149.139 +     */
 149.140 +    public final static int NORM_PRIORITY = 5;
 149.141 +
 149.142 +    /**
 149.143 +     * The maximum priority that a thread can have.
 149.144 +     */
 149.145 +    public final static int MAX_PRIORITY = 10;
 149.146 +
 149.147 +    private static final Thread ONE = new Thread("main");
 149.148 +    /**
 149.149 +     * Returns a reference to the currently executing thread object.
 149.150 +     *
 149.151 +     * @return  the currently executing thread.
 149.152 +     */
 149.153 +    public static Thread currentThread() {
 149.154 +        return ONE;
 149.155 +    }
 149.156 +
 149.157 +    /**
 149.158 +     * A hint to the scheduler that the current thread is willing to yield
 149.159 +     * its current use of a processor. The scheduler is free to ignore this
 149.160 +     * hint.
 149.161 +     *
 149.162 +     * <p> Yield is a heuristic attempt to improve relative progression
 149.163 +     * between threads that would otherwise over-utilise a CPU. Its use
 149.164 +     * should be combined with detailed profiling and benchmarking to
 149.165 +     * ensure that it actually has the desired effect.
 149.166 +     *
 149.167 +     * <p> It is rarely appropriate to use this method. It may be useful
 149.168 +     * for debugging or testing purposes, where it may help to reproduce
 149.169 +     * bugs due to race conditions. It may also be useful when designing
 149.170 +     * concurrency control constructs such as the ones in the
 149.171 +     * {@link java.util.concurrent.locks} package.
 149.172 +     */
 149.173 +    public static void yield() {
 149.174 +    }
 149.175 +
 149.176 +    /**
 149.177 +     * Causes the currently executing thread to sleep (temporarily cease
 149.178 +     * execution) for the specified number of milliseconds, subject to
 149.179 +     * the precision and accuracy of system timers and schedulers. The thread
 149.180 +     * does not lose ownership of any monitors.
 149.181 +     *
 149.182 +     * @param  millis
 149.183 +     *         the length of time to sleep in milliseconds
 149.184 +     *
 149.185 +     * @throws  IllegalArgumentException
 149.186 +     *          if the value of {@code millis} is negative
 149.187 +     *
 149.188 +     * @throws  InterruptedException
 149.189 +     *          if any thread has interrupted the current thread. The
 149.190 +     *          <i>interrupted status</i> of the current thread is
 149.191 +     *          cleared when this exception is thrown.
 149.192 +     */
 149.193 +    public static native void sleep(long millis) throws InterruptedException;
 149.194 +
 149.195 +    /**
 149.196 +     * Causes the currently executing thread to sleep (temporarily cease
 149.197 +     * execution) for the specified number of milliseconds plus the specified
 149.198 +     * number of nanoseconds, subject to the precision and accuracy of system
 149.199 +     * timers and schedulers. The thread does not lose ownership of any
 149.200 +     * monitors.
 149.201 +     *
 149.202 +     * @param  millis
 149.203 +     *         the length of time to sleep in milliseconds
 149.204 +     *
 149.205 +     * @param  nanos
 149.206 +     *         {@code 0-999999} additional nanoseconds to sleep
 149.207 +     *
 149.208 +     * @throws  IllegalArgumentException
 149.209 +     *          if the value of {@code millis} is negative, or the value of
 149.210 +     *          {@code nanos} is not in the range {@code 0-999999}
 149.211 +     *
 149.212 +     * @throws  InterruptedException
 149.213 +     *          if any thread has interrupted the current thread. The
 149.214 +     *          <i>interrupted status</i> of the current thread is
 149.215 +     *          cleared when this exception is thrown.
 149.216 +     */
 149.217 +    public static void sleep(long millis, int nanos)
 149.218 +    throws InterruptedException {
 149.219 +        if (millis < 0) {
 149.220 +            throw new IllegalArgumentException("timeout value is negative");
 149.221 +        }
 149.222 +
 149.223 +        if (nanos < 0 || nanos > 999999) {
 149.224 +            throw new IllegalArgumentException(
 149.225 +                                "nanosecond timeout value out of range");
 149.226 +        }
 149.227 +
 149.228 +        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
 149.229 +            millis++;
 149.230 +        }
 149.231 +
 149.232 +        sleep(millis);
 149.233 +    }
 149.234 +    private Runnable target;
 149.235 +    private String name;
 149.236 +
 149.237 +    /**
 149.238 +     * Throws CloneNotSupportedException as a Thread can not be meaningfully
 149.239 +     * cloned. Construct a new Thread instead.
 149.240 +     *
 149.241 +     * @throws  CloneNotSupportedException
 149.242 +     *          always
 149.243 +     */
 149.244 +    @Override
 149.245 +    protected Object clone() throws CloneNotSupportedException {
 149.246 +        throw new CloneNotSupportedException();
 149.247 +    }
 149.248 +
 149.249 +    /**
 149.250 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.251 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.252 +     * {@code (null, null, gname)}, where {@code gname} is a newly generated
 149.253 +     * name. Automatically generated names are of the form
 149.254 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 149.255 +     */
 149.256 +    public Thread() {
 149.257 +        init(null, null, "Thread-" + nextThreadNum(), 0);
 149.258 +    }
 149.259 +    
 149.260 +    private static int nextThreadNum() {
 149.261 +        return -1;
 149.262 +    }
 149.263 +
 149.264 +    /**
 149.265 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.266 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.267 +     * {@code (null, target, gname)}, where {@code gname} is a newly generated
 149.268 +     * name. Automatically generated names are of the form
 149.269 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 149.270 +     *
 149.271 +     * @param  target
 149.272 +     *         the object whose {@code run} method is invoked when this thread
 149.273 +     *         is started. If {@code null}, this classes {@code run} method does
 149.274 +     *         nothing.
 149.275 +     */
 149.276 +    public Thread(Runnable target) {
 149.277 +        init(null, target, "Thread-" + nextThreadNum(), 0);
 149.278 +    }
 149.279 +
 149.280 +    /**
 149.281 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.282 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.283 +     * {@code (group, target, gname)} ,where {@code gname} is a newly generated
 149.284 +     * name. Automatically generated names are of the form
 149.285 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 149.286 +     *
 149.287 +     * @param  group
 149.288 +     *         the thread group. If {@code null} and there is a security
 149.289 +     *         manager, the group is determined by {@linkplain
 149.290 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 149.291 +     *         If there is not a security manager or {@code
 149.292 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 149.293 +     *         is set to the current thread's thread group.
 149.294 +     *
 149.295 +     * @param  target
 149.296 +     *         the object whose {@code run} method is invoked when this thread
 149.297 +     *         is started. If {@code null}, this thread's run method is invoked.
 149.298 +     *
 149.299 +     * @throws  SecurityException
 149.300 +     *          if the current thread cannot create a thread in the specified
 149.301 +     *          thread group
 149.302 +     */
 149.303 +//    public Thread(ThreadGroup group, Runnable target) {
 149.304 +//        init(group, target, "Thread-" + nextThreadNum(), 0);
 149.305 +//    }
 149.306 +
 149.307 +    /**
 149.308 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.309 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.310 +     * {@code (null, null, name)}.
 149.311 +     *
 149.312 +     * @param   name
 149.313 +     *          the name of the new thread
 149.314 +     */
 149.315 +    public Thread(String name) {
 149.316 +        init(null, null, name, 0);
 149.317 +    }
 149.318 +    
 149.319 +    private void init(Object o1, Runnable trgt, String nm, int i4) {
 149.320 +        this.target = trgt;
 149.321 +        this.name = nm;
 149.322 +    }
 149.323 +
 149.324 +    /**
 149.325 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.326 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.327 +     * {@code (group, null, name)}.
 149.328 +     *
 149.329 +     * @param  group
 149.330 +     *         the thread group. If {@code null} and there is a security
 149.331 +     *         manager, the group is determined by {@linkplain
 149.332 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 149.333 +     *         If there is not a security manager or {@code
 149.334 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 149.335 +     *         is set to the current thread's thread group.
 149.336 +     *
 149.337 +     * @param  name
 149.338 +     *         the name of the new thread
 149.339 +     *
 149.340 +     * @throws  SecurityException
 149.341 +     *          if the current thread cannot create a thread in the specified
 149.342 +     *          thread group
 149.343 +     */
 149.344 +//    public Thread(ThreadGroup group, String name) {
 149.345 +//        init(group, null, name, 0);
 149.346 +//    }
 149.347 +
 149.348 +    /**
 149.349 +     * Allocates a new {@code Thread} object. This constructor has the same
 149.350 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 149.351 +     * {@code (null, target, name)}.
 149.352 +     *
 149.353 +     * @param  target
 149.354 +     *         the object whose {@code run} method is invoked when this thread
 149.355 +     *         is started. If {@code null}, this thread's run method is invoked.
 149.356 +     *
 149.357 +     * @param  name
 149.358 +     *         the name of the new thread
 149.359 +     */
 149.360 +    public Thread(Runnable target, String name) {
 149.361 +        init(null, target, name, 0);
 149.362 +    }
 149.363 +
 149.364 +    /**
 149.365 +     * Allocates a new {@code Thread} object so that it has {@code target}
 149.366 +     * as its run object, has the specified {@code name} as its name,
 149.367 +     * and belongs to the thread group referred to by {@code group}.
 149.368 +     *
 149.369 +     * <p>If there is a security manager, its
 149.370 +     * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}
 149.371 +     * method is invoked with the ThreadGroup as its argument.
 149.372 +     *
 149.373 +     * <p>In addition, its {@code checkPermission} method is invoked with
 149.374 +     * the {@code RuntimePermission("enableContextClassLoaderOverride")}
 149.375 +     * permission when invoked directly or indirectly by the constructor
 149.376 +     * of a subclass which overrides the {@code getContextClassLoader}
 149.377 +     * or {@code setContextClassLoader} methods.
 149.378 +     *
 149.379 +     * <p>The priority of the newly created thread is set equal to the
 149.380 +     * priority of the thread creating it, that is, the currently running
 149.381 +     * thread. The method {@linkplain #setPriority setPriority} may be
 149.382 +     * used to change the priority to a new value.
 149.383 +     *
 149.384 +     * <p>The newly created thread is initially marked as being a daemon
 149.385 +     * thread if and only if the thread creating it is currently marked
 149.386 +     * as a daemon thread. The method {@linkplain #setDaemon setDaemon}
 149.387 +     * may be used to change whether or not a thread is a daemon.
 149.388 +     *
 149.389 +     * @param  group
 149.390 +     *         the thread group. If {@code null} and there is a security
 149.391 +     *         manager, the group is determined by {@linkplain
 149.392 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 149.393 +     *         If there is not a security manager or {@code
 149.394 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 149.395 +     *         is set to the current thread's thread group.
 149.396 +     *
 149.397 +     * @param  target
 149.398 +     *         the object whose {@code run} method is invoked when this thread
 149.399 +     *         is started. If {@code null}, this thread's run method is invoked.
 149.400 +     *
 149.401 +     * @param  name
 149.402 +     *         the name of the new thread
 149.403 +     *
 149.404 +     * @throws  SecurityException
 149.405 +     *          if the current thread cannot create a thread in the specified
 149.406 +     *          thread group or cannot override the context class loader methods.
 149.407 +     */
 149.408 +//    public Thread(ThreadGroup group, Runnable target, String name) {
 149.409 +//        init(group, target, name, 0);
 149.410 +//    }
 149.411 +
 149.412 +    /**
 149.413 +     * Allocates a new {@code Thread} object so that it has {@code target}
 149.414 +     * as its run object, has the specified {@code name} as its name,
 149.415 +     * and belongs to the thread group referred to by {@code group}, and has
 149.416 +     * the specified <i>stack size</i>.
 149.417 +     *
 149.418 +     * <p>This constructor is identical to {@link
 149.419 +     * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact
 149.420 +     * that it allows the thread stack size to be specified.  The stack size
 149.421 +     * is the approximate number of bytes of address space that the virtual
 149.422 +     * machine is to allocate for this thread's stack.  <b>The effect of the
 149.423 +     * {@code stackSize} parameter, if any, is highly platform dependent.</b>
 149.424 +     *
 149.425 +     * <p>On some platforms, specifying a higher value for the
 149.426 +     * {@code stackSize} parameter may allow a thread to achieve greater
 149.427 +     * recursion depth before throwing a {@link StackOverflowError}.
 149.428 +     * Similarly, specifying a lower value may allow a greater number of
 149.429 +     * threads to exist concurrently without throwing an {@link
 149.430 +     * OutOfMemoryError} (or other internal error).  The details of
 149.431 +     * the relationship between the value of the <tt>stackSize</tt> parameter
 149.432 +     * and the maximum recursion depth and concurrency level are
 149.433 +     * platform-dependent.  <b>On some platforms, the value of the
 149.434 +     * {@code stackSize} parameter may have no effect whatsoever.</b>
 149.435 +     *
 149.436 +     * <p>The virtual machine is free to treat the {@code stackSize}
 149.437 +     * parameter as a suggestion.  If the specified value is unreasonably low
 149.438 +     * for the platform, the virtual machine may instead use some
 149.439 +     * platform-specific minimum value; if the specified value is unreasonably
 149.440 +     * high, the virtual machine may instead use some platform-specific
 149.441 +     * maximum.  Likewise, the virtual machine is free to round the specified
 149.442 +     * value up or down as it sees fit (or to ignore it completely).
 149.443 +     *
 149.444 +     * <p>Specifying a value of zero for the {@code stackSize} parameter will
 149.445 +     * cause this constructor to behave exactly like the
 149.446 +     * {@code Thread(ThreadGroup, Runnable, String)} constructor.
 149.447 +     *
 149.448 +     * <p><i>Due to the platform-dependent nature of the behavior of this
 149.449 +     * constructor, extreme care should be exercised in its use.
 149.450 +     * The thread stack size necessary to perform a given computation will
 149.451 +     * likely vary from one JRE implementation to another.  In light of this
 149.452 +     * variation, careful tuning of the stack size parameter may be required,
 149.453 +     * and the tuning may need to be repeated for each JRE implementation on
 149.454 +     * which an application is to run.</i>
 149.455 +     *
 149.456 +     * <p>Implementation note: Java platform implementers are encouraged to
 149.457 +     * document their implementation's behavior with respect to the
 149.458 +     * {@code stackSize} parameter.
 149.459 +     *
 149.460 +     *
 149.461 +     * @param  group
 149.462 +     *         the thread group. If {@code null} and there is a security
 149.463 +     *         manager, the group is determined by {@linkplain
 149.464 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 149.465 +     *         If there is not a security manager or {@code
 149.466 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 149.467 +     *         is set to the current thread's thread group.
 149.468 +     *
 149.469 +     * @param  target
 149.470 +     *         the object whose {@code run} method is invoked when this thread
 149.471 +     *         is started. If {@code null}, this thread's run method is invoked.
 149.472 +     *
 149.473 +     * @param  name
 149.474 +     *         the name of the new thread
 149.475 +     *
 149.476 +     * @param  stackSize
 149.477 +     *         the desired stack size for the new thread, or zero to indicate
 149.478 +     *         that this parameter is to be ignored.
 149.479 +     *
 149.480 +     * @throws  SecurityException
 149.481 +     *          if the current thread cannot create a thread in the specified
 149.482 +     *          thread group
 149.483 +     *
 149.484 +     * @since 1.4
 149.485 +     */
 149.486 +//    public Thread(ThreadGroup group, Runnable target, String name,
 149.487 +//                  long stackSize) {
 149.488 +//        init(group, target, name, stackSize);
 149.489 +//    }
 149.490 +
 149.491 +    /**
 149.492 +     * Causes this thread to begin execution; the Java Virtual Machine
 149.493 +     * calls the <code>run</code> method of this thread.
 149.494 +     * <p>
 149.495 +     * The result is that two threads are running concurrently: the
 149.496 +     * current thread (which returns from the call to the
 149.497 +     * <code>start</code> method) and the other thread (which executes its
 149.498 +     * <code>run</code> method).
 149.499 +     * <p>
 149.500 +     * It is never legal to start a thread more than once.
 149.501 +     * In particular, a thread may not be restarted once it has completed
 149.502 +     * execution.
 149.503 +     *
 149.504 +     * @exception  IllegalThreadStateException  if the thread was already
 149.505 +     *               started.
 149.506 +     * @see        #run()
 149.507 +     * @see        #stop()
 149.508 +     */
 149.509 +    public void start() {
 149.510 +        throw new SecurityException();
 149.511 +    }
 149.512 +
 149.513 +    /**
 149.514 +     * If this thread was constructed using a separate
 149.515 +     * <code>Runnable</code> run object, then that
 149.516 +     * <code>Runnable</code> object's <code>run</code> method is called;
 149.517 +     * otherwise, this method does nothing and returns.
 149.518 +     * <p>
 149.519 +     * Subclasses of <code>Thread</code> should override this method.
 149.520 +     *
 149.521 +     * @see     #start()
 149.522 +     * @see     #stop()
 149.523 +     * @see     #Thread(ThreadGroup, Runnable, String)
 149.524 +     */
 149.525 +    @Override
 149.526 +    public void run() {
 149.527 +        if (target != null) {
 149.528 +            target.run();
 149.529 +        }
 149.530 +    }
 149.531 +
 149.532 +    /**
 149.533 +     * Forces the thread to stop executing.
 149.534 +     * <p>
 149.535 +     * If there is a security manager installed, its <code>checkAccess</code>
 149.536 +     * method is called with <code>this</code>
 149.537 +     * as its argument. This may result in a
 149.538 +     * <code>SecurityException</code> being raised (in the current thread).
 149.539 +     * <p>
 149.540 +     * If this thread is different from the current thread (that is, the current
 149.541 +     * thread is trying to stop a thread other than itself), the
 149.542 +     * security manager's <code>checkPermission</code> method (with a
 149.543 +     * <code>RuntimePermission("stopThread")</code> argument) is called in
 149.544 +     * addition.
 149.545 +     * Again, this may result in throwing a
 149.546 +     * <code>SecurityException</code> (in the current thread).
 149.547 +     * <p>
 149.548 +     * The thread represented by this thread is forced to stop whatever
 149.549 +     * it is doing abnormally and to throw a newly created
 149.550 +     * <code>ThreadDeath</code> object as an exception.
 149.551 +     * <p>
 149.552 +     * It is permitted to stop a thread that has not yet been started.
 149.553 +     * If the thread is eventually started, it immediately terminates.
 149.554 +     * <p>
 149.555 +     * An application should not normally try to catch
 149.556 +     * <code>ThreadDeath</code> unless it must do some extraordinary
 149.557 +     * cleanup operation (note that the throwing of
 149.558 +     * <code>ThreadDeath</code> causes <code>finally</code> clauses of
 149.559 +     * <code>try</code> statements to be executed before the thread
 149.560 +     * officially dies).  If a <code>catch</code> clause catches a
 149.561 +     * <code>ThreadDeath</code> object, it is important to rethrow the
 149.562 +     * object so that the thread actually dies.
 149.563 +     * <p>
 149.564 +     * The top-level error handler that reacts to otherwise uncaught
 149.565 +     * exceptions does not print out a message or otherwise notify the
 149.566 +     * application if the uncaught exception is an instance of
 149.567 +     * <code>ThreadDeath</code>.
 149.568 +     *
 149.569 +     * @exception  SecurityException  if the current thread cannot
 149.570 +     *               modify this thread.
 149.571 +     * @see        #interrupt()
 149.572 +     * @see        #checkAccess()
 149.573 +     * @see        #run()
 149.574 +     * @see        #start()
 149.575 +     * @see        ThreadDeath
 149.576 +     * @see        ThreadGroup#uncaughtException(Thread,Throwable)
 149.577 +     * @see        SecurityManager#checkAccess(Thread)
 149.578 +     * @see        SecurityManager#checkPermission
 149.579 +     * @deprecated This method is inherently unsafe.  Stopping a thread with
 149.580 +     *       Thread.stop causes it to unlock all of the monitors that it
 149.581 +     *       has locked (as a natural consequence of the unchecked
 149.582 +     *       <code>ThreadDeath</code> exception propagating up the stack).  If
 149.583 +     *       any of the objects previously protected by these monitors were in
 149.584 +     *       an inconsistent state, the damaged objects become visible to
 149.585 +     *       other threads, potentially resulting in arbitrary behavior.  Many
 149.586 +     *       uses of <code>stop</code> should be replaced by code that simply
 149.587 +     *       modifies some variable to indicate that the target thread should
 149.588 +     *       stop running.  The target thread should check this variable
 149.589 +     *       regularly, and return from its run method in an orderly fashion
 149.590 +     *       if the variable indicates that it is to stop running.  If the
 149.591 +     *       target thread waits for long periods (on a condition variable,
 149.592 +     *       for example), the <code>interrupt</code> method should be used to
 149.593 +     *       interrupt the wait.
 149.594 +     *       For more information, see
 149.595 +     *       <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 149.596 +     *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 149.597 +     */
 149.598 +    @Deprecated
 149.599 +    public final void stop() {
 149.600 +        stop(null);
 149.601 +    }
 149.602 +
 149.603 +    /**
 149.604 +     * Forces the thread to stop executing.
 149.605 +     * <p>
 149.606 +     * If there is a security manager installed, the <code>checkAccess</code>
 149.607 +     * method of this thread is called, which may result in a
 149.608 +     * <code>SecurityException</code> being raised (in the current thread).
 149.609 +     * <p>
 149.610 +     * If this thread is different from the current thread (that is, the current
 149.611 +     * thread is trying to stop a thread other than itself) or
 149.612 +     * <code>obj</code> is not an instance of <code>ThreadDeath</code>, the
 149.613 +     * security manager's <code>checkPermission</code> method (with the
 149.614 +     * <code>RuntimePermission("stopThread")</code> argument) is called in
 149.615 +     * addition.
 149.616 +     * Again, this may result in throwing a
 149.617 +     * <code>SecurityException</code> (in the current thread).
 149.618 +     * <p>
 149.619 +     * If the argument <code>obj</code> is null, a
 149.620 +     * <code>NullPointerException</code> is thrown (in the current thread).
 149.621 +     * <p>
 149.622 +     * The thread represented by this thread is forced to stop
 149.623 +     * whatever it is doing abnormally and to throw the
 149.624 +     * <code>Throwable</code> object <code>obj</code> as an exception. This
 149.625 +     * is an unusual action to take; normally, the <code>stop</code> method
 149.626 +     * that takes no arguments should be used.
 149.627 +     * <p>
 149.628 +     * It is permitted to stop a thread that has not yet been started.
 149.629 +     * If the thread is eventually started, it immediately terminates.
 149.630 +     *
 149.631 +     * @param      obj   the Throwable object to be thrown.
 149.632 +     * @exception  SecurityException  if the current thread cannot modify
 149.633 +     *               this thread.
 149.634 +     * @throws     NullPointerException if obj is <tt>null</tt>.
 149.635 +     * @see        #interrupt()
 149.636 +     * @see        #checkAccess()
 149.637 +     * @see        #run()
 149.638 +     * @see        #start()
 149.639 +     * @see        #stop()
 149.640 +     * @see        SecurityManager#checkAccess(Thread)
 149.641 +     * @see        SecurityManager#checkPermission
 149.642 +     * @deprecated This method is inherently unsafe.  See {@link #stop()}
 149.643 +     *        for details.  An additional danger of this
 149.644 +     *        method is that it may be used to generate exceptions that the
 149.645 +     *        target thread is unprepared to handle (including checked
 149.646 +     *        exceptions that the thread could not possibly throw, were it
 149.647 +     *        not for this method).
 149.648 +     *        For more information, see
 149.649 +     *        <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 149.650 +     *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 149.651 +     */
 149.652 +    @Deprecated
 149.653 +    public final synchronized void stop(Throwable obj) {
 149.654 +        throw new SecurityException();
 149.655 +    }
 149.656 +
 149.657 +    /**
 149.658 +     * Interrupts this thread.
 149.659 +     *
 149.660 +     * <p> Unless the current thread is interrupting itself, which is
 149.661 +     * always permitted, the {@link #checkAccess() checkAccess} method
 149.662 +     * of this thread is invoked, which may cause a {@link
 149.663 +     * SecurityException} to be thrown.
 149.664 +     *
 149.665 +     * <p> If this thread is blocked in an invocation of the {@link
 149.666 +     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
 149.667 +     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
 149.668 +     * class, or of the {@link #join()}, {@link #join(long)}, {@link
 149.669 +     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
 149.670 +     * methods of this class, then its interrupt status will be cleared and it
 149.671 +     * will receive an {@link InterruptedException}.
 149.672 +     *
 149.673 +     * <p> If this thread is blocked in an I/O operation upon an {@link
 149.674 +     * java.nio.channels.InterruptibleChannel </code>interruptible
 149.675 +     * channel<code>} then the channel will be closed, the thread's interrupt
 149.676 +     * status will be set, and the thread will receive a {@link
 149.677 +     * java.nio.channels.ClosedByInterruptException}.
 149.678 +     *
 149.679 +     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
 149.680 +     * then the thread's interrupt status will be set and it will return
 149.681 +     * immediately from the selection operation, possibly with a non-zero
 149.682 +     * value, just as if the selector's {@link
 149.683 +     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
 149.684 +     *
 149.685 +     * <p> If none of the previous conditions hold then this thread's interrupt
 149.686 +     * status will be set. </p>
 149.687 +     *
 149.688 +     * <p> Interrupting a thread that is not alive need not have any effect.
 149.689 +     *
 149.690 +     * @throws  SecurityException
 149.691 +     *          if the current thread cannot modify this thread
 149.692 +     *
 149.693 +     * @revised 6.0
 149.694 +     * @spec JSR-51
 149.695 +     */
 149.696 +    public void interrupt() {
 149.697 +        throw new SecurityException();
 149.698 +    }
 149.699 +
 149.700 +    /**
 149.701 +     * Tests whether the current thread has been interrupted.  The
 149.702 +     * <i>interrupted status</i> of the thread is cleared by this method.  In
 149.703 +     * other words, if this method were to be called twice in succession, the
 149.704 +     * second call would return false (unless the current thread were
 149.705 +     * interrupted again, after the first call had cleared its interrupted
 149.706 +     * status and before the second call had examined it).
 149.707 +     *
 149.708 +     * <p>A thread interruption ignored because a thread was not alive
 149.709 +     * at the time of the interrupt will be reflected by this method
 149.710 +     * returning false.
 149.711 +     *
 149.712 +     * @return  <code>true</code> if the current thread has been interrupted;
 149.713 +     *          <code>false</code> otherwise.
 149.714 +     * @see #isInterrupted()
 149.715 +     * @revised 6.0
 149.716 +     */
 149.717 +    public static boolean interrupted() {
 149.718 +        return currentThread().isInterrupted();
 149.719 +    }
 149.720 +
 149.721 +    /**
 149.722 +     * Tests whether this thread has been interrupted.  The <i>interrupted
 149.723 +     * status</i> of the thread is unaffected by this method.
 149.724 +     *
 149.725 +     * <p>A thread interruption ignored because a thread was not alive
 149.726 +     * at the time of the interrupt will be reflected by this method
 149.727 +     * returning false.
 149.728 +     *
 149.729 +     * @return  <code>true</code> if this thread has been interrupted;
 149.730 +     *          <code>false</code> otherwise.
 149.731 +     * @see     #interrupted()
 149.732 +     * @revised 6.0
 149.733 +     */
 149.734 +    public boolean isInterrupted() {
 149.735 +        return false;
 149.736 +    }
 149.737 +
 149.738 +    /**
 149.739 +     * Throws {@link NoSuchMethodError}.
 149.740 +     *
 149.741 +     * @deprecated This method was originally designed to destroy this
 149.742 +     *     thread without any cleanup. Any monitors it held would have
 149.743 +     *     remained locked. However, the method was never implemented.
 149.744 +     *     If if were to be implemented, it would be deadlock-prone in
 149.745 +     *     much the manner of {@link #suspend}. If the target thread held
 149.746 +     *     a lock protecting a critical system resource when it was
 149.747 +     *     destroyed, no thread could ever access this resource again.
 149.748 +     *     If another thread ever attempted to lock this resource, deadlock
 149.749 +     *     would result. Such deadlocks typically manifest themselves as
 149.750 +     *     "frozen" processes. For more information, see
 149.751 +     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
 149.752 +     *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 149.753 +     * @throws NoSuchMethodError always
 149.754 +     */
 149.755 +    @Deprecated
 149.756 +    public void destroy() {
 149.757 +        throw new SecurityException();
 149.758 +    }
 149.759 +
 149.760 +    /**
 149.761 +     * Tests if this thread is alive. A thread is alive if it has
 149.762 +     * been started and has not yet died.
 149.763 +     *
 149.764 +     * @return  <code>true</code> if this thread is alive;
 149.765 +     *          <code>false</code> otherwise.
 149.766 +     */
 149.767 +    public final boolean isAlive() {
 149.768 +        return true;
 149.769 +    }
 149.770 +
 149.771 +    /**
 149.772 +     * Suspends this thread.
 149.773 +     * <p>
 149.774 +     * First, the <code>checkAccess</code> method of this thread is called
 149.775 +     * with no arguments. This may result in throwing a
 149.776 +     * <code>SecurityException </code>(in the current thread).
 149.777 +     * <p>
 149.778 +     * If the thread is alive, it is suspended and makes no further
 149.779 +     * progress unless and until it is resumed.
 149.780 +     *
 149.781 +     * @exception  SecurityException  if the current thread cannot modify
 149.782 +     *               this thread.
 149.783 +     * @see #checkAccess
 149.784 +     * @deprecated   This method has been deprecated, as it is
 149.785 +     *   inherently deadlock-prone.  If the target thread holds a lock on the
 149.786 +     *   monitor protecting a critical system resource when it is suspended, no
 149.787 +     *   thread can access this resource until the target thread is resumed. If
 149.788 +     *   the thread that would resume the target thread attempts to lock this
 149.789 +     *   monitor prior to calling <code>resume</code>, deadlock results.  Such
 149.790 +     *   deadlocks typically manifest themselves as "frozen" processes.
 149.791 +     *   For more information, see
 149.792 +     *   <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 149.793 +     *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 149.794 +     */
 149.795 +    @Deprecated
 149.796 +    public final void suspend() {
 149.797 +        checkAccess();
 149.798 +    }
 149.799 +
 149.800 +    /**
 149.801 +     * Resumes a suspended thread.
 149.802 +     * <p>
 149.803 +     * First, the <code>checkAccess</code> method of this thread is called
 149.804 +     * with no arguments. This may result in throwing a
 149.805 +     * <code>SecurityException</code> (in the current thread).
 149.806 +     * <p>
 149.807 +     * If the thread is alive but suspended, it is resumed and is
 149.808 +     * permitted to make progress in its execution.
 149.809 +     *
 149.810 +     * @exception  SecurityException  if the current thread cannot modify this
 149.811 +     *               thread.
 149.812 +     * @see        #checkAccess
 149.813 +     * @see        #suspend()
 149.814 +     * @deprecated This method exists solely for use with {@link #suspend},
 149.815 +     *     which has been deprecated because it is deadlock-prone.
 149.816 +     *     For more information, see
 149.817 +     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 149.818 +     *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 149.819 +     */
 149.820 +    @Deprecated
 149.821 +    public final void resume() {
 149.822 +        checkAccess();
 149.823 +    }
 149.824 +
 149.825 +    /**
 149.826 +     * Changes the priority of this thread.
 149.827 +     * <p>
 149.828 +     * First the <code>checkAccess</code> method of this thread is called
 149.829 +     * with no arguments. This may result in throwing a
 149.830 +     * <code>SecurityException</code>.
 149.831 +     * <p>
 149.832 +     * Otherwise, the priority of this thread is set to the smaller of
 149.833 +     * the specified <code>newPriority</code> and the maximum permitted
 149.834 +     * priority of the thread's thread group.
 149.835 +     *
 149.836 +     * @param newPriority priority to set this thread to
 149.837 +     * @exception  IllegalArgumentException  If the priority is not in the
 149.838 +     *               range <code>MIN_PRIORITY</code> to
 149.839 +     *               <code>MAX_PRIORITY</code>.
 149.840 +     * @exception  SecurityException  if the current thread cannot modify
 149.841 +     *               this thread.
 149.842 +     * @see        #getPriority
 149.843 +     * @see        #checkAccess()
 149.844 +     * @see        #getThreadGroup()
 149.845 +     * @see        #MAX_PRIORITY
 149.846 +     * @see        #MIN_PRIORITY
 149.847 +     * @see        ThreadGroup#getMaxPriority()
 149.848 +     */
 149.849 +    public final void setPriority(int newPriority) {
 149.850 +        throw new SecurityException();
 149.851 +    }
 149.852 +
 149.853 +    /**
 149.854 +     * Returns this thread's priority.
 149.855 +     *
 149.856 +     * @return  this thread's priority.
 149.857 +     * @see     #setPriority
 149.858 +     */
 149.859 +    public final int getPriority() {
 149.860 +        return Thread.NORM_PRIORITY;
 149.861 +    }
 149.862 +
 149.863 +    /**
 149.864 +     * Changes the name of this thread to be equal to the argument
 149.865 +     * <code>name</code>.
 149.866 +     * <p>
 149.867 +     * First the <code>checkAccess</code> method of this thread is called
 149.868 +     * with no arguments. This may result in throwing a
 149.869 +     * <code>SecurityException</code>.
 149.870 +     *
 149.871 +     * @param      name   the new name for this thread.
 149.872 +     * @exception  SecurityException  if the current thread cannot modify this
 149.873 +     *               thread.
 149.874 +     * @see        #getName
 149.875 +     * @see        #checkAccess()
 149.876 +     */
 149.877 +    public final void setName(String name) {
 149.878 +        throw new SecurityException();
 149.879 +    }
 149.880 +
 149.881 +    /**
 149.882 +     * Returns this thread's name.
 149.883 +     *
 149.884 +     * @return  this thread's name.
 149.885 +     * @see     #setName(String)
 149.886 +     */
 149.887 +    public final String getName() {
 149.888 +        return String.valueOf(name);
 149.889 +    }
 149.890 +
 149.891 +    /**
 149.892 +     * Returns the thread group to which this thread belongs.
 149.893 +     * This method returns null if this thread has died
 149.894 +     * (been stopped).
 149.895 +     *
 149.896 +     * @return  this thread's thread group.
 149.897 +     */
 149.898 +//    public final ThreadGroup getThreadGroup() {
 149.899 +//        return group;
 149.900 +//    }
 149.901 +
 149.902 +    /**
 149.903 +     * Returns an estimate of the number of active threads in the current
 149.904 +     * thread's {@linkplain java.lang.ThreadGroup thread group} and its
 149.905 +     * subgroups. Recursively iterates over all subgroups in the current
 149.906 +     * thread's thread group.
 149.907 +     *
 149.908 +     * <p> The value returned is only an estimate because the number of
 149.909 +     * threads may change dynamically while this method traverses internal
 149.910 +     * data structures, and might be affected by the presence of certain
 149.911 +     * system threads. This method is intended primarily for debugging
 149.912 +     * and monitoring purposes.
 149.913 +     *
 149.914 +     * @return  an estimate of the number of active threads in the current
 149.915 +     *          thread's thread group and in any other thread group that
 149.916 +     *          has the current thread's thread group as an ancestor
 149.917 +     */
 149.918 +    public static int activeCount() {
 149.919 +        return 1;
 149.920 +    }
 149.921 +
 149.922 +    /**
 149.923 +     * Copies into the specified array every active thread in the current
 149.924 +     * thread's thread group and its subgroups. This method simply
 149.925 +     * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])}
 149.926 +     * method of the current thread's thread group.
 149.927 +     *
 149.928 +     * <p> An application might use the {@linkplain #activeCount activeCount}
 149.929 +     * method to get an estimate of how big the array should be, however
 149.930 +     * <i>if the array is too short to hold all the threads, the extra threads
 149.931 +     * are silently ignored.</i>  If it is critical to obtain every active
 149.932 +     * thread in the current thread's thread group and its subgroups, the
 149.933 +     * invoker should verify that the returned int value is strictly less
 149.934 +     * than the length of {@code tarray}.
 149.935 +     *
 149.936 +     * <p> Due to the inherent race condition in this method, it is recommended
 149.937 +     * that the method only be used for debugging and monitoring purposes.
 149.938 +     *
 149.939 +     * @param  tarray
 149.940 +     *         an array into which to put the list of threads
 149.941 +     *
 149.942 +     * @return  the number of threads put into the array
 149.943 +     *
 149.944 +     * @throws  SecurityException
 149.945 +     *          if {@link java.lang.ThreadGroup#checkAccess} determines that
 149.946 +     *          the current thread cannot access its thread group
 149.947 +     */
 149.948 +    public static int enumerate(Thread tarray[]) {
 149.949 +        throw new SecurityException();
 149.950 +    }
 149.951 +
 149.952 +    /**
 149.953 +     * Counts the number of stack frames in this thread. The thread must
 149.954 +     * be suspended.
 149.955 +     *
 149.956 +     * @return     the number of stack frames in this thread.
 149.957 +     * @exception  IllegalThreadStateException  if this thread is not
 149.958 +     *             suspended.
 149.959 +     * @deprecated The definition of this call depends on {@link #suspend},
 149.960 +     *             which is deprecated.  Further, the results of this call
 149.961 +     *             were never well-defined.
 149.962 +     */
 149.963 +    @Deprecated
 149.964 +    public native int countStackFrames();
 149.965 +
 149.966 +    /**
 149.967 +     * Waits at most {@code millis} milliseconds for this thread to
 149.968 +     * die. A timeout of {@code 0} means to wait forever.
 149.969 +     *
 149.970 +     * <p> This implementation uses a loop of {@code this.wait} calls
 149.971 +     * conditioned on {@code this.isAlive}. As a thread terminates the
 149.972 +     * {@code this.notifyAll} method is invoked. It is recommended that
 149.973 +     * applications not use {@code wait}, {@code notify}, or
 149.974 +     * {@code notifyAll} on {@code Thread} instances.
 149.975 +     *
 149.976 +     * @param  millis
 149.977 +     *         the time to wait in milliseconds
 149.978 +     *
 149.979 +     * @throws  IllegalArgumentException
 149.980 +     *          if the value of {@code millis} is negative
 149.981 +     *
 149.982 +     * @throws  InterruptedException
 149.983 +     *          if any thread has interrupted the current thread. The
 149.984 +     *          <i>interrupted status</i> of the current thread is
 149.985 +     *          cleared when this exception is thrown.
 149.986 +     */
 149.987 +    public final synchronized void join(long millis)
 149.988 +    throws InterruptedException {
 149.989 +        long base = System.currentTimeMillis();
 149.990 +        long now = 0;
 149.991 +
 149.992 +        if (millis < 0) {
 149.993 +            throw new IllegalArgumentException("timeout value is negative");
 149.994 +        }
 149.995 +
 149.996 +        if (millis == 0) {
 149.997 +            while (isAlive()) {
 149.998 +                wait(0);
 149.999 +            }
149.1000 +        } else {
149.1001 +            while (isAlive()) {
149.1002 +                long delay = millis - now;
149.1003 +                if (delay <= 0) {
149.1004 +                    break;
149.1005 +                }
149.1006 +                wait(delay);
149.1007 +                now = System.currentTimeMillis() - base;
149.1008 +            }
149.1009 +        }
149.1010 +    }
149.1011 +
149.1012 +    /**
149.1013 +     * Waits at most {@code millis} milliseconds plus
149.1014 +     * {@code nanos} nanoseconds for this thread to die.
149.1015 +     *
149.1016 +     * <p> This implementation uses a loop of {@code this.wait} calls
149.1017 +     * conditioned on {@code this.isAlive}. As a thread terminates the
149.1018 +     * {@code this.notifyAll} method is invoked. It is recommended that
149.1019 +     * applications not use {@code wait}, {@code notify}, or
149.1020 +     * {@code notifyAll} on {@code Thread} instances.
149.1021 +     *
149.1022 +     * @param  millis
149.1023 +     *         the time to wait in milliseconds
149.1024 +     *
149.1025 +     * @param  nanos
149.1026 +     *         {@code 0-999999} additional nanoseconds to wait
149.1027 +     *
149.1028 +     * @throws  IllegalArgumentException
149.1029 +     *          if the value of {@code millis} is negative, or the value
149.1030 +     *          of {@code nanos} is not in the range {@code 0-999999}
149.1031 +     *
149.1032 +     * @throws  InterruptedException
149.1033 +     *          if any thread has interrupted the current thread. The
149.1034 +     *          <i>interrupted status</i> of the current thread is
149.1035 +     *          cleared when this exception is thrown.
149.1036 +     */
149.1037 +    public final synchronized void join(long millis, int nanos)
149.1038 +    throws InterruptedException {
149.1039 +
149.1040 +        if (millis < 0) {
149.1041 +            throw new IllegalArgumentException("timeout value is negative");
149.1042 +        }
149.1043 +
149.1044 +        if (nanos < 0 || nanos > 999999) {
149.1045 +            throw new IllegalArgumentException(
149.1046 +                                "nanosecond timeout value out of range");
149.1047 +        }
149.1048 +
149.1049 +        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
149.1050 +            millis++;
149.1051 +        }
149.1052 +
149.1053 +        join(millis);
149.1054 +    }
149.1055 +
149.1056 +    /**
149.1057 +     * Waits for this thread to die.
149.1058 +     *
149.1059 +     * <p> An invocation of this method behaves in exactly the same
149.1060 +     * way as the invocation
149.1061 +     *
149.1062 +     * <blockquote>
149.1063 +     * {@linkplain #join(long) join}{@code (0)}
149.1064 +     * </blockquote>
149.1065 +     *
149.1066 +     * @throws  InterruptedException
149.1067 +     *          if any thread has interrupted the current thread. The
149.1068 +     *          <i>interrupted status</i> of the current thread is
149.1069 +     *          cleared when this exception is thrown.
149.1070 +     */
149.1071 +    public final void join() throws InterruptedException {
149.1072 +        join(0);
149.1073 +    }
149.1074 +
149.1075 +    /**
149.1076 +     * Prints a stack trace of the current thread to the standard error stream.
149.1077 +     * This method is used only for debugging.
149.1078 +     *
149.1079 +     * @see     Throwable#printStackTrace()
149.1080 +     */
149.1081 +    public static void dumpStack() {
149.1082 +        new Exception("Stack trace").printStackTrace();
149.1083 +    }
149.1084 +
149.1085 +    /**
149.1086 +     * Marks this thread as either a {@linkplain #isDaemon daemon} thread
149.1087 +     * or a user thread. The Java Virtual Machine exits when the only
149.1088 +     * threads running are all daemon threads.
149.1089 +     *
149.1090 +     * <p> This method must be invoked before the thread is started.
149.1091 +     *
149.1092 +     * @param  on
149.1093 +     *         if {@code true}, marks this thread as a daemon thread
149.1094 +     *
149.1095 +     * @throws  IllegalThreadStateException
149.1096 +     *          if this thread is {@linkplain #isAlive alive}
149.1097 +     *
149.1098 +     * @throws  SecurityException
149.1099 +     *          if {@link #checkAccess} determines that the current
149.1100 +     *          thread cannot modify this thread
149.1101 +     */
149.1102 +    public final void setDaemon(boolean on) {
149.1103 +        throw new SecurityException();
149.1104 +    }
149.1105 +
149.1106 +    /**
149.1107 +     * Tests if this thread is a daemon thread.
149.1108 +     *
149.1109 +     * @return  <code>true</code> if this thread is a daemon thread;
149.1110 +     *          <code>false</code> otherwise.
149.1111 +     * @see     #setDaemon(boolean)
149.1112 +     */
149.1113 +    public final boolean isDaemon() {
149.1114 +        return false;
149.1115 +    }
149.1116 +
149.1117 +    /**
149.1118 +     * Determines if the currently running thread has permission to
149.1119 +     * modify this thread.
149.1120 +     * <p>
149.1121 +     * If there is a security manager, its <code>checkAccess</code> method
149.1122 +     * is called with this thread as its argument. This may result in
149.1123 +     * throwing a <code>SecurityException</code>.
149.1124 +     *
149.1125 +     * @exception  SecurityException  if the current thread is not allowed to
149.1126 +     *               access this thread.
149.1127 +     * @see        SecurityManager#checkAccess(Thread)
149.1128 +     */
149.1129 +    public final void checkAccess() {
149.1130 +        throw new SecurityException();
149.1131 +    }
149.1132 +
149.1133 +    /**
149.1134 +     * Returns a string representation of this thread, including the
149.1135 +     * thread's name, priority, and thread group.
149.1136 +     *
149.1137 +     * @return  a string representation of this thread.
149.1138 +     */
149.1139 +    public String toString() {
149.1140 +        return "Thread[" + getName() + "," + getPriority() + "," +
149.1141 +                        "" + "]";
149.1142 +    }
149.1143 +
149.1144 +    /**
149.1145 +     * Returns the context ClassLoader for this Thread. The context
149.1146 +     * ClassLoader is provided by the creator of the thread for use
149.1147 +     * by code running in this thread when loading classes and resources.
149.1148 +     * If not {@linkplain #setContextClassLoader set}, the default is the
149.1149 +     * ClassLoader context of the parent Thread. The context ClassLoader of the
149.1150 +     * primordial thread is typically set to the class loader used to load the
149.1151 +     * application.
149.1152 +     *
149.1153 +     * <p>If a security manager is present, and the invoker's class loader is not
149.1154 +     * {@code null} and is not the same as or an ancestor of the context class
149.1155 +     * loader, then this method invokes the security manager's {@link
149.1156 +     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
149.1157 +     * method with a {@link RuntimePermission RuntimePermission}{@code
149.1158 +     * ("getClassLoader")} permission to verify that retrieval of the context
149.1159 +     * class loader is permitted.
149.1160 +     *
149.1161 +     * @return  the context ClassLoader for this Thread, or {@code null}
149.1162 +     *          indicating the system class loader (or, failing that, the
149.1163 +     *          bootstrap class loader)
149.1164 +     *
149.1165 +     * @throws  SecurityException
149.1166 +     *          if the current thread cannot get the context ClassLoader
149.1167 +     *
149.1168 +     * @since 1.2
149.1169 +     */
149.1170 +    public ClassLoader getContextClassLoader() {
149.1171 +        return ClassLoader.getSystemClassLoader();
149.1172 +    }
149.1173 +
149.1174 +    /**
149.1175 +     * Sets the context ClassLoader for this Thread. The context
149.1176 +     * ClassLoader can be set when a thread is created, and allows
149.1177 +     * the creator of the thread to provide the appropriate class loader,
149.1178 +     * through {@code getContextClassLoader}, to code running in the thread
149.1179 +     * when loading classes and resources.
149.1180 +     *
149.1181 +     * <p>If a security manager is present, its {@link
149.1182 +     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
149.1183 +     * method is invoked with a {@link RuntimePermission RuntimePermission}{@code
149.1184 +     * ("setContextClassLoader")} permission to see if setting the context
149.1185 +     * ClassLoader is permitted.
149.1186 +     *
149.1187 +     * @param  cl
149.1188 +     *         the context ClassLoader for this Thread, or null  indicating the
149.1189 +     *         system class loader (or, failing that, the bootstrap class loader)
149.1190 +     *
149.1191 +     * @throws  SecurityException
149.1192 +     *          if the current thread cannot set the context ClassLoader
149.1193 +     *
149.1194 +     * @since 1.2
149.1195 +     */
149.1196 +    public void setContextClassLoader(ClassLoader cl) {
149.1197 +        if (cl == ClassLoader.getSystemClassLoader()) {
149.1198 +            return;
149.1199 +        }
149.1200 +        throw new SecurityException();
149.1201 +    }
149.1202 +
149.1203 +    /**
149.1204 +     * Returns <tt>true</tt> if and only if the current thread holds the
149.1205 +     * monitor lock on the specified object.
149.1206 +     *
149.1207 +     * <p>This method is designed to allow a program to assert that
149.1208 +     * the current thread already holds a specified lock:
149.1209 +     * <pre>
149.1210 +     *     assert Thread.holdsLock(obj);
149.1211 +     * </pre>
149.1212 +     *
149.1213 +     * @param  obj the object on which to test lock ownership
149.1214 +     * @throws NullPointerException if obj is <tt>null</tt>
149.1215 +     * @return <tt>true</tt> if the current thread holds the monitor lock on
149.1216 +     *         the specified object.
149.1217 +     * @since 1.4
149.1218 +     */
149.1219 +    public static boolean holdsLock(Object obj) {
149.1220 +        return true;
149.1221 +    }
149.1222 +
149.1223 +    /**
149.1224 +     * Returns an array of stack trace elements representing the stack dump
149.1225 +     * of this thread.  This method will return a zero-length array if
149.1226 +     * this thread has not started, has started but has not yet been
149.1227 +     * scheduled to run by the system, or has terminated.
149.1228 +     * If the returned array is of non-zero length then the first element of
149.1229 +     * the array represents the top of the stack, which is the most recent
149.1230 +     * method invocation in the sequence.  The last element of the array
149.1231 +     * represents the bottom of the stack, which is the least recent method
149.1232 +     * invocation in the sequence.
149.1233 +     *
149.1234 +     * <p>If there is a security manager, and this thread is not
149.1235 +     * the current thread, then the security manager's
149.1236 +     * <tt>checkPermission</tt> method is called with a
149.1237 +     * <tt>RuntimePermission("getStackTrace")</tt> permission
149.1238 +     * to see if it's ok to get the stack trace.
149.1239 +     *
149.1240 +     * <p>Some virtual machines may, under some circumstances, omit one
149.1241 +     * or more stack frames from the stack trace.  In the extreme case,
149.1242 +     * a virtual machine that has no stack trace information concerning
149.1243 +     * this thread is permitted to return a zero-length array from this
149.1244 +     * method.
149.1245 +     *
149.1246 +     * @return an array of <tt>StackTraceElement</tt>,
149.1247 +     * each represents one stack frame.
149.1248 +     *
149.1249 +     * @throws SecurityException
149.1250 +     *        if a security manager exists and its
149.1251 +     *        <tt>checkPermission</tt> method doesn't allow
149.1252 +     *        getting the stack trace of thread.
149.1253 +     * @see SecurityManager#checkPermission
149.1254 +     * @see RuntimePermission
149.1255 +     * @see Throwable#getStackTrace
149.1256 +     *
149.1257 +     * @since 1.5
149.1258 +     */
149.1259 +    public StackTraceElement[] getStackTrace() {
149.1260 +        throw new SecurityException();
149.1261 +    }
149.1262 +
149.1263 +    /**
149.1264 +     * Returns a map of stack traces for all live threads.
149.1265 +     * The map keys are threads and each map value is an array of
149.1266 +     * <tt>StackTraceElement</tt> that represents the stack dump
149.1267 +     * of the corresponding <tt>Thread</tt>.
149.1268 +     * The returned stack traces are in the format specified for
149.1269 +     * the {@link #getStackTrace getStackTrace} method.
149.1270 +     *
149.1271 +     * <p>The threads may be executing while this method is called.
149.1272 +     * The stack trace of each thread only represents a snapshot and
149.1273 +     * each stack trace may be obtained at different time.  A zero-length
149.1274 +     * array will be returned in the map value if the virtual machine has
149.1275 +     * no stack trace information about a thread.
149.1276 +     *
149.1277 +     * <p>If there is a security manager, then the security manager's
149.1278 +     * <tt>checkPermission</tt> method is called with a
149.1279 +     * <tt>RuntimePermission("getStackTrace")</tt> permission as well as
149.1280 +     * <tt>RuntimePermission("modifyThreadGroup")</tt> permission
149.1281 +     * to see if it is ok to get the stack trace of all threads.
149.1282 +     *
149.1283 +     * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of
149.1284 +     * <tt>StackTraceElement</tt> that represents the stack trace of
149.1285 +     * the corresponding thread.
149.1286 +     *
149.1287 +     * @throws SecurityException
149.1288 +     *        if a security manager exists and its
149.1289 +     *        <tt>checkPermission</tt> method doesn't allow
149.1290 +     *        getting the stack trace of thread.
149.1291 +     * @see #getStackTrace
149.1292 +     * @see SecurityManager#checkPermission
149.1293 +     * @see RuntimePermission
149.1294 +     * @see Throwable#getStackTrace
149.1295 +     *
149.1296 +     * @since 1.5
149.1297 +     */
149.1298 +    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
149.1299 +        throw new SecurityException();
149.1300 +    }
149.1301 +
149.1302 +    /**
149.1303 +     * Returns the identifier of this Thread.  The thread ID is a positive
149.1304 +     * <tt>long</tt> number generated when this thread was created.
149.1305 +     * The thread ID is unique and remains unchanged during its lifetime.
149.1306 +     * When a thread is terminated, this thread ID may be reused.
149.1307 +     *
149.1308 +     * @return this thread's ID.
149.1309 +     * @since 1.5
149.1310 +     */
149.1311 +    public long getId() {
149.1312 +        return 0;
149.1313 +    }
149.1314 +
149.1315 +    /**
149.1316 +     * A thread state.  A thread can be in one of the following states:
149.1317 +     * <ul>
149.1318 +     * <li>{@link #NEW}<br>
149.1319 +     *     A thread that has not yet started is in this state.
149.1320 +     *     </li>
149.1321 +     * <li>{@link #RUNNABLE}<br>
149.1322 +     *     A thread executing in the Java virtual machine is in this state.
149.1323 +     *     </li>
149.1324 +     * <li>{@link #BLOCKED}<br>
149.1325 +     *     A thread that is blocked waiting for a monitor lock
149.1326 +     *     is in this state.
149.1327 +     *     </li>
149.1328 +     * <li>{@link #WAITING}<br>
149.1329 +     *     A thread that is waiting indefinitely for another thread to
149.1330 +     *     perform a particular action is in this state.
149.1331 +     *     </li>
149.1332 +     * <li>{@link #TIMED_WAITING}<br>
149.1333 +     *     A thread that is waiting for another thread to perform an action
149.1334 +     *     for up to a specified waiting time is in this state.
149.1335 +     *     </li>
149.1336 +     * <li>{@link #TERMINATED}<br>
149.1337 +     *     A thread that has exited is in this state.
149.1338 +     *     </li>
149.1339 +     * </ul>
149.1340 +     *
149.1341 +     * <p>
149.1342 +     * A thread can be in only one state at a given point in time.
149.1343 +     * These states are virtual machine states which do not reflect
149.1344 +     * any operating system thread states.
149.1345 +     *
149.1346 +     * @since   1.5
149.1347 +     * @see #getState
149.1348 +     */
149.1349 +    public enum State {
149.1350 +        /**
149.1351 +         * Thread state for a thread which has not yet started.
149.1352 +         */
149.1353 +        NEW,
149.1354 +
149.1355 +        /**
149.1356 +         * Thread state for a runnable thread.  A thread in the runnable
149.1357 +         * state is executing in the Java virtual machine but it may
149.1358 +         * be waiting for other resources from the operating system
149.1359 +         * such as processor.
149.1360 +         */
149.1361 +        RUNNABLE,
149.1362 +
149.1363 +        /**
149.1364 +         * Thread state for a thread blocked waiting for a monitor lock.
149.1365 +         * A thread in the blocked state is waiting for a monitor lock
149.1366 +         * to enter a synchronized block/method or
149.1367 +         * reenter a synchronized block/method after calling
149.1368 +         * {@link Object#wait() Object.wait}.
149.1369 +         */
149.1370 +        BLOCKED,
149.1371 +
149.1372 +        /**
149.1373 +         * Thread state for a waiting thread.
149.1374 +         * A thread is in the waiting state due to calling one of the
149.1375 +         * following methods:
149.1376 +         * <ul>
149.1377 +         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
149.1378 +         *   <li>{@link #join() Thread.join} with no timeout</li>
149.1379 +         *   <li>{@link LockSupport#park() LockSupport.park}</li>
149.1380 +         * </ul>
149.1381 +         *
149.1382 +         * <p>A thread in the waiting state is waiting for another thread to
149.1383 +         * perform a particular action.
149.1384 +         *
149.1385 +         * For example, a thread that has called <tt>Object.wait()</tt>
149.1386 +         * on an object is waiting for another thread to call
149.1387 +         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
149.1388 +         * that object. A thread that has called <tt>Thread.join()</tt>
149.1389 +         * is waiting for a specified thread to terminate.
149.1390 +         */
149.1391 +        WAITING,
149.1392 +
149.1393 +        /**
149.1394 +         * Thread state for a waiting thread with a specified waiting time.
149.1395 +         * A thread is in the timed waiting state due to calling one of
149.1396 +         * the following methods with a specified positive waiting time:
149.1397 +         * <ul>
149.1398 +         *   <li>{@link #sleep Thread.sleep}</li>
149.1399 +         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
149.1400 +         *   <li>{@link #join(long) Thread.join} with timeout</li>
149.1401 +         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
149.1402 +         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
149.1403 +         * </ul>
149.1404 +         */
149.1405 +        TIMED_WAITING,
149.1406 +
149.1407 +        /**
149.1408 +         * Thread state for a terminated thread.
149.1409 +         * The thread has completed execution.
149.1410 +         */
149.1411 +        TERMINATED;
149.1412 +    }
149.1413 +
149.1414 +    /**
149.1415 +     * Returns the state of this thread.
149.1416 +     * This method is designed for use in monitoring of the system state,
149.1417 +     * not for synchronization control.
149.1418 +     *
149.1419 +     * @return this thread's state.
149.1420 +     * @since 1.5
149.1421 +     */
149.1422 +    public State getState() {
149.1423 +        // get current thread state
149.1424 +        return State.RUNNABLE;
149.1425 +    }
149.1426 +
149.1427 +    // Added in JSR-166
149.1428 +
149.1429 +    /**
149.1430 +     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
149.1431 +     * terminates due to an uncaught exception.
149.1432 +     * <p>When a thread is about to terminate due to an uncaught exception
149.1433 +     * the Java Virtual Machine will query the thread for its
149.1434 +     * <tt>UncaughtExceptionHandler</tt> using
149.1435 +     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
149.1436 +     * <tt>uncaughtException</tt> method, passing the thread and the
149.1437 +     * exception as arguments.
149.1438 +     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
149.1439 +     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
149.1440 +     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
149.1441 +     * has no
149.1442 +     * special requirements for dealing with the exception, it can forward
149.1443 +     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
149.1444 +     * default uncaught exception handler}.
149.1445 +     *
149.1446 +     * @see #setDefaultUncaughtExceptionHandler
149.1447 +     * @see #setUncaughtExceptionHandler
149.1448 +     * @see ThreadGroup#uncaughtException
149.1449 +     * @since 1.5
149.1450 +     */
149.1451 +    public interface UncaughtExceptionHandler {
149.1452 +        /**
149.1453 +         * Method invoked when the given thread terminates due to the
149.1454 +         * given uncaught exception.
149.1455 +         * <p>Any exception thrown by this method will be ignored by the
149.1456 +         * Java Virtual Machine.
149.1457 +         * @param t the thread
149.1458 +         * @param e the exception
149.1459 +         */
149.1460 +        void uncaughtException(Thread t, Throwable e);
149.1461 +    }
149.1462 +
149.1463 +    // null unless explicitly set
149.1464 +    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
149.1465 +
149.1466 +    // null unless explicitly set
149.1467 +    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
149.1468 +
149.1469 +    /**
149.1470 +     * Set the default handler invoked when a thread abruptly terminates
149.1471 +     * due to an uncaught exception, and no other handler has been defined
149.1472 +     * for that thread.
149.1473 +     *
149.1474 +     * <p>Uncaught exception handling is controlled first by the thread, then
149.1475 +     * by the thread's {@link ThreadGroup} object and finally by the default
149.1476 +     * uncaught exception handler. If the thread does not have an explicit
149.1477 +     * uncaught exception handler set, and the thread's thread group
149.1478 +     * (including parent thread groups)  does not specialize its
149.1479 +     * <tt>uncaughtException</tt> method, then the default handler's
149.1480 +     * <tt>uncaughtException</tt> method will be invoked.
149.1481 +     * <p>By setting the default uncaught exception handler, an application
149.1482 +     * can change the way in which uncaught exceptions are handled (such as
149.1483 +     * logging to a specific device, or file) for those threads that would
149.1484 +     * already accept whatever &quot;default&quot; behavior the system
149.1485 +     * provided.
149.1486 +     *
149.1487 +     * <p>Note that the default uncaught exception handler should not usually
149.1488 +     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
149.1489 +     * infinite recursion.
149.1490 +     *
149.1491 +     * @param eh the object to use as the default uncaught exception handler.
149.1492 +     * If <tt>null</tt> then there is no default handler.
149.1493 +     *
149.1494 +     * @throws SecurityException if a security manager is present and it
149.1495 +     *         denies <tt>{@link RuntimePermission}
149.1496 +     *         (&quot;setDefaultUncaughtExceptionHandler&quot;)</tt>
149.1497 +     *
149.1498 +     * @see #setUncaughtExceptionHandler
149.1499 +     * @see #getUncaughtExceptionHandler
149.1500 +     * @see ThreadGroup#uncaughtException
149.1501 +     * @since 1.5
149.1502 +     */
149.1503 +    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
149.1504 +        throw new SecurityException();
149.1505 +    }
149.1506 +
149.1507 +    /**
149.1508 +     * Returns the default handler invoked when a thread abruptly terminates
149.1509 +     * due to an uncaught exception. If the returned value is <tt>null</tt>,
149.1510 +     * there is no default.
149.1511 +     * @since 1.5
149.1512 +     * @see #setDefaultUncaughtExceptionHandler
149.1513 +     */
149.1514 +    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
149.1515 +        return defaultUncaughtExceptionHandler;
149.1516 +    }
149.1517 +
149.1518 +    /**
149.1519 +     * Returns the handler invoked when this thread abruptly terminates
149.1520 +     * due to an uncaught exception. If this thread has not had an
149.1521 +     * uncaught exception handler explicitly set then this thread's
149.1522 +     * <tt>ThreadGroup</tt> object is returned, unless this thread
149.1523 +     * has terminated, in which case <tt>null</tt> is returned.
149.1524 +     * @since 1.5
149.1525 +     */
149.1526 +    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
149.1527 +        return uncaughtExceptionHandler != null ?
149.1528 +            uncaughtExceptionHandler : null;
149.1529 +    }
149.1530 +
149.1531 +    /**
149.1532 +     * Set the handler invoked when this thread abruptly terminates
149.1533 +     * due to an uncaught exception.
149.1534 +     * <p>A thread can take full control of how it responds to uncaught
149.1535 +     * exceptions by having its uncaught exception handler explicitly set.
149.1536 +     * If no such handler is set then the thread's <tt>ThreadGroup</tt>
149.1537 +     * object acts as its handler.
149.1538 +     * @param eh the object to use as this thread's uncaught exception
149.1539 +     * handler. If <tt>null</tt> then this thread has no explicit handler.
149.1540 +     * @throws  SecurityException  if the current thread is not allowed to
149.1541 +     *          modify this thread.
149.1542 +     * @see #setDefaultUncaughtExceptionHandler
149.1543 +     * @see ThreadGroup#uncaughtException
149.1544 +     * @since 1.5
149.1545 +     */
149.1546 +    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
149.1547 +        checkAccess();
149.1548 +        uncaughtExceptionHandler = eh;
149.1549 +    }
149.1550 +}
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/rt/emul/compact/src/main/java/java/lang/ThreadLocal.java	Wed Apr 30 15:04:10 2014 +0200
   150.3 @@ -0,0 +1,157 @@
   150.4 +/*
   150.5 + * Copyright (c) 1997, 2007, 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 +package java.lang;
  150.30 +
  150.31 +/**
  150.32 + * This class provides thread-local variables.  These variables differ from
  150.33 + * their normal counterparts in that each thread that accesses one (via its
  150.34 + * <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized
  150.35 + * copy of the variable.  <tt>ThreadLocal</tt> instances are typically private
  150.36 + * static fields in classes that wish to associate state with a thread (e.g.,
  150.37 + * a user ID or Transaction ID).
  150.38 + *
  150.39 + * <p>For example, the class below generates unique identifiers local to each
  150.40 + * thread.
  150.41 + * A thread's id is assigned the first time it invokes <tt>ThreadId.get()</tt>
  150.42 + * and remains unchanged on subsequent calls.
  150.43 + * <pre>
  150.44 + * import java.util.concurrent.atomic.AtomicInteger;
  150.45 + *
  150.46 + * public class ThreadId {
  150.47 + *     // Atomic integer containing the next thread ID to be assigned
  150.48 + *     private static final AtomicInteger nextId = new AtomicInteger(0);
  150.49 + *
  150.50 + *     // Thread local variable containing each thread's ID
  150.51 + *     private static final ThreadLocal&lt;Integer> threadId =
  150.52 + *         new ThreadLocal&lt;Integer>() {
  150.53 + *             &#64;Override protected Integer initialValue() {
  150.54 + *                 return nextId.getAndIncrement();
  150.55 + *         }
  150.56 + *     };
  150.57 + *
  150.58 + *     // Returns the current thread's unique ID, assigning it if necessary
  150.59 + *     public static int get() {
  150.60 + *         return threadId.get();
  150.61 + *     }
  150.62 + * }
  150.63 + * </pre>
  150.64 + * <p>Each thread holds an implicit reference to its copy of a thread-local
  150.65 + * variable as long as the thread is alive and the <tt>ThreadLocal</tt>
  150.66 + * instance is accessible; after a thread goes away, all of its copies of
  150.67 + * thread-local instances are subject to garbage collection (unless other
  150.68 + * references to these copies exist).
  150.69 + *
  150.70 + * @author  Josh Bloch and Doug Lea
  150.71 + * @since   1.2
  150.72 + */
  150.73 +public class ThreadLocal<T> {
  150.74 +    private static final Object NONE = new Object();
  150.75 +    private Object value = NONE;
  150.76 +    
  150.77 +    /**
  150.78 +     * Returns the current thread's "initial value" for this
  150.79 +     * thread-local variable.  This method will be invoked the first
  150.80 +     * time a thread accesses the variable with the {@link #get}
  150.81 +     * method, unless the thread previously invoked the {@link #set}
  150.82 +     * method, in which case the <tt>initialValue</tt> method will not
  150.83 +     * be invoked for the thread.  Normally, this method is invoked at
  150.84 +     * most once per thread, but it may be invoked again in case of
  150.85 +     * subsequent invocations of {@link #remove} followed by {@link #get}.
  150.86 +     *
  150.87 +     * <p>This implementation simply returns <tt>null</tt>; if the
  150.88 +     * programmer desires thread-local variables to have an initial
  150.89 +     * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
  150.90 +     * subclassed, and this method overridden.  Typically, an
  150.91 +     * anonymous inner class will be used.
  150.92 +     *
  150.93 +     * @return the initial value for this thread-local
  150.94 +     */
  150.95 +    protected T initialValue() {
  150.96 +        return null;
  150.97 +    }
  150.98 +
  150.99 +    /**
 150.100 +     * Creates a thread local variable.
 150.101 +     */
 150.102 +    public ThreadLocal() {
 150.103 +    }
 150.104 +
 150.105 +    /**
 150.106 +     * Returns the value in the current thread's copy of this
 150.107 +     * thread-local variable.  If the variable has no value for the
 150.108 +     * current thread, it is first initialized to the value returned
 150.109 +     * by an invocation of the {@link #initialValue} method.
 150.110 +     *
 150.111 +     * @return the current thread's value of this thread-local
 150.112 +     */
 150.113 +    public T get() {
 150.114 +        if (value == NONE) {
 150.115 +            return setInitialValue();
 150.116 +        } else {
 150.117 +            return (T)value;
 150.118 +        }
 150.119 +    }
 150.120 +
 150.121 +    /**
 150.122 +     * Variant of set() to establish initialValue. Used instead
 150.123 +     * of set() in case user has overridden the set() method.
 150.124 +     *
 150.125 +     * @return the initial value
 150.126 +     */
 150.127 +    private T setInitialValue() {
 150.128 +        T v = initialValue();
 150.129 +        this.value = v;
 150.130 +        return v;
 150.131 +    }
 150.132 +
 150.133 +    /**
 150.134 +     * Sets the current thread's copy of this thread-local variable
 150.135 +     * to the specified value.  Most subclasses will have no need to
 150.136 +     * override this method, relying solely on the {@link #initialValue}
 150.137 +     * method to set the values of thread-locals.
 150.138 +     *
 150.139 +     * @param value the value to be stored in the current thread's copy of
 150.140 +     *        this thread-local.
 150.141 +     */
 150.142 +    public void set(T value) {
 150.143 +        this.value = value;
 150.144 +    }
 150.145 +
 150.146 +    /**
 150.147 +     * Removes the current thread's value for this thread-local
 150.148 +     * variable.  If this thread-local variable is subsequently
 150.149 +     * {@linkplain #get read} by the current thread, its value will be
 150.150 +     * reinitialized by invoking its {@link #initialValue} method,
 150.151 +     * unless its value is {@linkplain #set set} by the current thread
 150.152 +     * in the interim.  This may result in multiple invocations of the
 150.153 +     * <tt>initialValue</tt> method in the current thread.
 150.154 +     *
 150.155 +     * @since 1.5
 150.156 +     */
 150.157 +     public void remove() {
 150.158 +         this.value = NONE;
 150.159 +     }
 150.160 +}
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/Annotation.java	Wed Apr 30 15:04:10 2014 +0200
   151.3 @@ -0,0 +1,131 @@
   151.4 +/*
   151.5 + * Copyright (c) 2003, 2009, 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.lang.annotation;
  151.30 +
  151.31 +/**
  151.32 + * The common interface extended by all annotation types.  Note that an
  151.33 + * interface that manually extends this one does <i>not</i> define
  151.34 + * an annotation type.  Also note that this interface does not itself
  151.35 + * define an annotation type.
  151.36 + *
  151.37 + * More information about annotation types can be found in section 9.6 of
  151.38 + * <cite>The Java&trade; Language Specification</cite>.
  151.39 + *
  151.40 + * @author  Josh Bloch
  151.41 + * @since   1.5
  151.42 + */
  151.43 +public interface Annotation {
  151.44 +    /**
  151.45 +     * Returns true if the specified object represents an annotation
  151.46 +     * that is logically equivalent to this one.  In other words,
  151.47 +     * returns true if the specified object is an instance of the same
  151.48 +     * annotation type as this instance, all of whose members are equal
  151.49 +     * to the corresponding member of this annotation, as defined below:
  151.50 +     * <ul>
  151.51 +     *    <li>Two corresponding primitive typed members whose values are
  151.52 +     *    <tt>x</tt> and <tt>y</tt> are considered equal if <tt>x == y</tt>,
  151.53 +     *    unless their type is <tt>float</tt> or <tt>double</tt>.
  151.54 +     *
  151.55 +     *    <li>Two corresponding <tt>float</tt> members whose values
  151.56 +     *    are <tt>x</tt> and <tt>y</tt> are considered equal if
  151.57 +     *    <tt>Float.valueOf(x).equals(Float.valueOf(y))</tt>.
  151.58 +     *    (Unlike the <tt>==</tt> operator, NaN is considered equal
  151.59 +     *    to itself, and <tt>0.0f</tt> unequal to <tt>-0.0f</tt>.)
  151.60 +     *
  151.61 +     *    <li>Two corresponding <tt>double</tt> members whose values
  151.62 +     *    are <tt>x</tt> and <tt>y</tt> are considered equal if
  151.63 +     *    <tt>Double.valueOf(x).equals(Double.valueOf(y))</tt>.
  151.64 +     *    (Unlike the <tt>==</tt> operator, NaN is considered equal
  151.65 +     *    to itself, and <tt>0.0</tt> unequal to <tt>-0.0</tt>.)
  151.66 +     *
  151.67 +     *    <li>Two corresponding <tt>String</tt>, <tt>Class</tt>, enum, or
  151.68 +     *    annotation typed members whose values are <tt>x</tt> and <tt>y</tt>
  151.69 +     *    are considered equal if <tt>x.equals(y)</tt>.  (Note that this
  151.70 +     *    definition is recursive for annotation typed members.)
  151.71 +     *
  151.72 +     *    <li>Two corresponding array typed members <tt>x</tt> and <tt>y</tt>
  151.73 +     *    are considered equal if <tt>Arrays.equals(x, y)</tt>, for the
  151.74 +     *    appropriate overloading of {@link java.util.Arrays#equals}.
  151.75 +     * </ul>
  151.76 +     *
  151.77 +     * @return true if the specified object represents an annotation
  151.78 +     *     that is logically equivalent to this one, otherwise false
  151.79 +     */
  151.80 +    boolean equals(Object obj);
  151.81 +
  151.82 +    /**
  151.83 +     * Returns the hash code of this annotation, as defined below:
  151.84 +     *
  151.85 +     * <p>The hash code of an annotation is the sum of the hash codes
  151.86 +     * of its members (including those with default values), as defined
  151.87 +     * below:
  151.88 +     *
  151.89 +     * The hash code of an annotation member is (127 times the hash code
  151.90 +     * of the member-name as computed by {@link String#hashCode()}) XOR
  151.91 +     * the hash code of the member-value, as defined below:
  151.92 +     *
  151.93 +     * <p>The hash code of a member-value depends on its type:
  151.94 +     * <ul>
  151.95 +     * <li>The hash code of a primitive value <tt><i>v</i></tt> is equal to
  151.96 +     *     <tt><i>WrapperType</i>.valueOf(<i>v</i>).hashCode()</tt>, where
  151.97 +     *     <tt><i>WrapperType</i></tt> is the wrapper type corresponding
  151.98 +     *     to the primitive type of <tt><i>v</i></tt> ({@link Byte},
  151.99 +     *     {@link Character}, {@link Double}, {@link Float}, {@link Integer},
 151.100 +     *     {@link Long}, {@link Short}, or {@link Boolean}).
 151.101 +     *
 151.102 +     * <li>The hash code of a string, enum, class, or annotation member-value
 151.103 +     I     <tt><i>v</i></tt> is computed as by calling
 151.104 +     *     <tt><i>v</i>.hashCode()</tt>.  (In the case of annotation
 151.105 +     *     member values, this is a recursive definition.)
 151.106 +     *
 151.107 +     * <li>The hash code of an array member-value is computed by calling
 151.108 +     *     the appropriate overloading of
 151.109 +     *     {@link java.util.Arrays#hashCode(long[]) Arrays.hashCode}
 151.110 +     *     on the value.  (There is one overloading for each primitive
 151.111 +     *     type, and one for object reference types.)
 151.112 +     * </ul>
 151.113 +     *
 151.114 +     * @return the hash code of this annotation
 151.115 +     */
 151.116 +    int hashCode();
 151.117 +
 151.118 +    /**
 151.119 +     * Returns a string representation of this annotation.  The details
 151.120 +     * of the representation are implementation-dependent, but the following
 151.121 +     * may be regarded as typical:
 151.122 +     * <pre>
 151.123 +     *   &#064;com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
 151.124 +     * </pre>
 151.125 +     *
 151.126 +     * @return a string representation of this annotation
 151.127 +     */
 151.128 +    String toString();
 151.129 +
 151.130 +    /**
 151.131 +     * Returns the annotation type of this annotation.
 151.132 +     */
 151.133 +    Class<? extends Annotation> annotationType();
 151.134 +}
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/AnnotationFormatError.java	Wed Apr 30 15:04:10 2014 +0200
   152.3 @@ -0,0 +1,79 @@
   152.4 +/*
   152.5 + * Copyright (c) 2004, 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.lang.annotation;
  152.30 +
  152.31 +/**
  152.32 + * Thrown when the annotation parser attempts to read an annotation
  152.33 + * from a class file and determines that the annotation is malformed.
  152.34 + * This error can be thrown by the {@linkplain
  152.35 + * java.lang.reflect.AnnotatedElement API used to read annotations
  152.36 + * reflectively}.
  152.37 + *
  152.38 + * @author  Josh Bloch
  152.39 + * @see     java.lang.reflect.AnnotatedElement
  152.40 + * @since   1.5
  152.41 + */
  152.42 +public class AnnotationFormatError extends Error {
  152.43 +    private static final long serialVersionUID = -4256701562333669892L;
  152.44 +
  152.45 +    /**
  152.46 +     * Constructs a new <tt>AnnotationFormatError</tt> with the specified
  152.47 +     * detail message.
  152.48 +     *
  152.49 +     * @param   message   the detail message.
  152.50 +     */
  152.51 +    public AnnotationFormatError(String message) {
  152.52 +        super(message);
  152.53 +    }
  152.54 +
  152.55 +    /**
  152.56 +     * Constructs a new <tt>AnnotationFormatError</tt> with the specified
  152.57 +     * detail message and cause.  Note that the detail message associated
  152.58 +     * with <code>cause</code> is <i>not</i> automatically incorporated in
  152.59 +     * this error's detail message.
  152.60 +     *
  152.61 +     * @param  message the detail message
  152.62 +     * @param  cause the cause (A <tt>null</tt> value is permitted, and
  152.63 +     *     indicates that the cause is nonexistent or unknown.)
  152.64 +     */
  152.65 +    public AnnotationFormatError(String message, Throwable cause) {
  152.66 +        super(message, cause);
  152.67 +    }
  152.68 +
  152.69 +
  152.70 +    /**
  152.71 +     * Constructs a new <tt>AnnotationFormatError</tt> with the specified
  152.72 +     * cause and a detail message of
  152.73 +     * <tt>(cause == null ? null : cause.toString())</tt> (which
  152.74 +     * typically contains the class and detail message of <tt>cause</tt>).
  152.75 +     *
  152.76 +     * @param  cause the cause (A <tt>null</tt> value is permitted, and
  152.77 +     *     indicates that the cause is nonexistent or unknown.)
  152.78 +     */
  152.79 +    public AnnotationFormatError(Throwable cause) {
  152.80 +        super(cause);
  152.81 +    }
  152.82 +}
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java	Wed Apr 30 15:04:10 2014 +0200
   153.3 @@ -0,0 +1,91 @@
   153.4 +/*
   153.5 + * Copyright (c) 2003, 2008, 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.lang.annotation;
  153.30 +import java.lang.reflect.Method;
  153.31 +
  153.32 +/**
  153.33 + * Thrown to indicate that a program has attempted to access an element of
  153.34 + * an annotation whose type has changed after the annotation was compiled
  153.35 + * (or serialized).
  153.36 + * This exception can be thrown by the {@linkplain
  153.37 + * java.lang.reflect.AnnotatedElement API used to read annotations
  153.38 + * reflectively}.
  153.39 + *
  153.40 + * @author  Josh Bloch
  153.41 + * @see     java.lang.reflect.AnnotatedElement
  153.42 + * @since 1.5
  153.43 + */
  153.44 +public class AnnotationTypeMismatchException extends RuntimeException {
  153.45 +    private static final long serialVersionUID = 8125925355765570191L;
  153.46 +
  153.47 +    /**
  153.48 +     * The <tt>Method</tt> object for the annotation element.
  153.49 +     */
  153.50 +    private final Method element;
  153.51 +
  153.52 +    /**
  153.53 +     * The (erroneous) type of data found in the annotation.  This string
  153.54 +     * may, but is not required to, contain the value as well.  The exact
  153.55 +     * format of the string is unspecified.
  153.56 +     */
  153.57 +    private final String foundType;
  153.58 +
  153.59 +    /**
  153.60 +     * Constructs an AnnotationTypeMismatchException for the specified
  153.61 +     * annotation type element and found data type.
  153.62 +     *
  153.63 +     * @param element the <tt>Method</tt> object for the annotation element
  153.64 +     * @param foundType the (erroneous) type of data found in the annotation.
  153.65 +     *        This string may, but is not required to, contain the value
  153.66 +     *        as well.  The exact format of the string is unspecified.
  153.67 +     */
  153.68 +    public AnnotationTypeMismatchException(Method element, String foundType) {
  153.69 +        super("Incorrectly typed data found for annotation element " + element
  153.70 +              + " (Found data of type " + foundType + ")");
  153.71 +        this.element = element;
  153.72 +        this.foundType = foundType;
  153.73 +    }
  153.74 +
  153.75 +    /**
  153.76 +     * Returns the <tt>Method</tt> object for the incorrectly typed element.
  153.77 +     *
  153.78 +     * @return the <tt>Method</tt> object for the incorrectly typed element
  153.79 +     */
  153.80 +    public Method element() {
  153.81 +        return this.element;
  153.82 +    }
  153.83 +
  153.84 +    /**
  153.85 +     * Returns the type of data found in the incorrectly typed element.
  153.86 +     * The returned string may, but is not required to, contain the value
  153.87 +     * as well.  The exact format of the string is unspecified.
  153.88 +     *
  153.89 +     * @return the type of data found in the incorrectly typed element
  153.90 +     */
  153.91 +    public String foundType() {
  153.92 +        return this.foundType;
  153.93 +    }
  153.94 +}
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/Documented.java	Wed Apr 30 15:04:10 2014 +0200
   154.3 @@ -0,0 +1,43 @@
   154.4 +/*
   154.5 + * Copyright (c) 2003, 2004, 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.lang.annotation;
  154.30 +
  154.31 +/**
  154.32 + * Indicates that annotations with a type are to be documented by javadoc
  154.33 + * and similar tools by default.  This type should be used to annotate the
  154.34 + * declarations of types whose annotations affect the use of annotated
  154.35 + * elements by their clients.  If a type declaration is annotated with
  154.36 + * Documented, its annotations become part of the public API
  154.37 + * of the annotated elements.
  154.38 + *
  154.39 + * @author  Joshua Bloch
  154.40 + * @since 1.5
  154.41 + */
  154.42 +@Documented
  154.43 +@Retention(RetentionPolicy.RUNTIME)
  154.44 +@Target(ElementType.ANNOTATION_TYPE)
  154.45 +public @interface Documented {
  154.46 +}
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/ElementType.java	Wed Apr 30 15:04:10 2014 +0200
   155.3 @@ -0,0 +1,63 @@
   155.4 +/*
   155.5 + * Copyright (c) 2003, 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.lang.annotation;
  155.30 +
  155.31 +/**
  155.32 + * A program element type.  The constants of this enumerated type
  155.33 + * provide a simple classification of the declared elements in a
  155.34 + * Java program.
  155.35 + *
  155.36 + * <p>These constants are used with the {@link Target} meta-annotation type
  155.37 + * to specify where it is legal to use an annotation type.
  155.38 + *
  155.39 + * @author  Joshua Bloch
  155.40 + * @since 1.5
  155.41 + */
  155.42 +public enum ElementType {
  155.43 +    /** Class, interface (including annotation type), or enum declaration */
  155.44 +    TYPE,
  155.45 +
  155.46 +    /** Field declaration (includes enum constants) */
  155.47 +    FIELD,
  155.48 +
  155.49 +    /** Method declaration */
  155.50 +    METHOD,
  155.51 +
  155.52 +    /** Parameter declaration */
  155.53 +    PARAMETER,
  155.54 +
  155.55 +    /** Constructor declaration */
  155.56 +    CONSTRUCTOR,
  155.57 +
  155.58 +    /** Local variable declaration */
  155.59 +    LOCAL_VARIABLE,
  155.60 +
  155.61 +    /** Annotation type declaration */
  155.62 +    ANNOTATION_TYPE,
  155.63 +
  155.64 +    /** Package declaration */
  155.65 +    PACKAGE
  155.66 +}
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/IncompleteAnnotationException.java	Wed Apr 30 15:04:10 2014 +0200
   156.3 @@ -0,0 +1,83 @@
   156.4 +/*
   156.5 + * Copyright (c) 2003, 2008, 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.lang.annotation;
  156.30 +
  156.31 +/**
  156.32 + * Thrown to indicate that a program has attempted to access an element of
  156.33 + * an annotation type that was added to the annotation type definition after
  156.34 + * the annotation was compiled (or serialized).  This exception will not be
  156.35 + * thrown if the new element has a default value.
  156.36 + * This exception can be thrown by the {@linkplain
  156.37 + * java.lang.reflect.AnnotatedElement API used to read annotations
  156.38 + * reflectively}.
  156.39 + *
  156.40 + * @author  Josh Bloch
  156.41 + * @see     java.lang.reflect.AnnotatedElement
  156.42 + * @since 1.5
  156.43 + */
  156.44 +public class IncompleteAnnotationException extends RuntimeException {
  156.45 +    private static final long serialVersionUID = 8445097402741811912L;
  156.46 +
  156.47 +    private Class annotationType;
  156.48 +    private String elementName;
  156.49 +
  156.50 +
  156.51 +    /**
  156.52 +     * Constructs an IncompleteAnnotationException to indicate that
  156.53 +     * the named element was missing from the specified annotation type.
  156.54 +     *
  156.55 +     * @param annotationType the Class object for the annotation type
  156.56 +     * @param elementName the name of the missing element
  156.57 +     */
  156.58 +    public IncompleteAnnotationException(
  156.59 +            Class<? extends Annotation> annotationType,
  156.60 +            String elementName) {
  156.61 +        super(annotationType.getName() + " missing element " + elementName);
  156.62 +
  156.63 +        this.annotationType = annotationType;
  156.64 +        this.elementName = elementName;
  156.65 +    }
  156.66 +
  156.67 +    /**
  156.68 +     * Returns the Class object for the annotation type with the
  156.69 +     * missing element.
  156.70 +     *
  156.71 +     * @return the Class object for the annotation type with the
  156.72 +     *     missing element
  156.73 +     */
  156.74 +    public Class<? extends Annotation> annotationType() {
  156.75 +        return annotationType;
  156.76 +    }
  156.77 +
  156.78 +    /**
  156.79 +     * Returns the name of the missing element.
  156.80 +     *
  156.81 +     * @return the name of the missing element
  156.82 +     */
  156.83 +    public String elementName() {
  156.84 +        return elementName;
  156.85 +    }
  156.86 +}
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/Inherited.java	Wed Apr 30 15:04:10 2014 +0200
   157.3 @@ -0,0 +1,52 @@
   157.4 +/*
   157.5 + * Copyright (c) 2003, 2004, 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.lang.annotation;
  157.30 +
  157.31 +/**
  157.32 + * Indicates that an annotation type is automatically inherited.  If
  157.33 + * an Inherited meta-annotation is present on an annotation type
  157.34 + * declaration, and the user queries the annotation type on a class
  157.35 + * declaration, and the class declaration has no annotation for this type,
  157.36 + * then the class's superclass will automatically be queried for the
  157.37 + * annotation type.  This process will be repeated until an annotation for this
  157.38 + * type is found, or the top of the class hierarchy (Object)
  157.39 + * is reached.  If no superclass has an annotation for this type, then
  157.40 + * the query will indicate that the class in question has no such annotation.
  157.41 + *
  157.42 + * <p>Note that this meta-annotation type has no effect if the annotated
  157.43 + * type is used to annotate anything other than a class.  Note also
  157.44 + * that this meta-annotation only causes annotations to be inherited
  157.45 + * from superclasses; annotations on implemented interfaces have no
  157.46 + * effect.
  157.47 + *
  157.48 + * @author  Joshua Bloch
  157.49 + * @since 1.5
  157.50 + */
  157.51 +@Documented
  157.52 +@Retention(RetentionPolicy.RUNTIME)
  157.53 +@Target(ElementType.ANNOTATION_TYPE)
  157.54 +public @interface Inherited {
  157.55 +}
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/Retention.java	Wed Apr 30 15:04:10 2014 +0200
   158.3 @@ -0,0 +1,47 @@
   158.4 +/*
   158.5 + * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
   158.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   158.7 + *
   158.8 + * This code is free software; you can redistribute it and/or modify it
   158.9 + * under the terms of the GNU General Public License version 2 only, as
  158.10 + * published by the Free Software Foundation.  Oracle designates this
  158.11 + * particular file as subject to the "Classpath" exception as provided
  158.12 + * by Oracle in the LICENSE file that accompanied this code.
  158.13 + *
  158.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  158.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  158.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  158.17 + * version 2 for more details (a copy is included in the LICENSE file that
  158.18 + * accompanied this code).
  158.19 + *
  158.20 + * You should have received a copy of the GNU General Public License version
  158.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  158.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  158.23 + *
  158.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  158.25 + * or visit www.oracle.com if you need additional information or have any
  158.26 + * questions.
  158.27 + */
  158.28 +
  158.29 +package java.lang.annotation;
  158.30 +
  158.31 +/**
  158.32 + * Indicates how long annotations with the annotated type are to
  158.33 + * be retained.  If no Retention annotation is present on
  158.34 + * an annotation type declaration, the retention policy defaults to
  158.35 + * {@code RetentionPolicy.CLASS}.
  158.36 + *
  158.37 + * <p>A Retention meta-annotation has effect only if the
  158.38 + * meta-annotated type is used directly for annotation.  It has no
  158.39 + * effect if the meta-annotated type is used as a member type in
  158.40 + * another annotation type.
  158.41 + *
  158.42 + * @author  Joshua Bloch
  158.43 + * @since 1.5
  158.44 + */
  158.45 +@Documented
  158.46 +@Retention(RetentionPolicy.RUNTIME)
  158.47 +@Target(ElementType.ANNOTATION_TYPE)
  158.48 +public @interface Retention {
  158.49 +    RetentionPolicy value();
  158.50 +}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/RetentionPolicy.java	Wed Apr 30 15:04:10 2014 +0200
   159.3 @@ -0,0 +1,57 @@
   159.4 +/*
   159.5 + * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
   159.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   159.7 + *
   159.8 + * This code is free software; you can redistribute it and/or modify it
   159.9 + * under the terms of the GNU General Public License version 2 only, as
  159.10 + * published by the Free Software Foundation.  Oracle designates this
  159.11 + * particular file as subject to the "Classpath" exception as provided
  159.12 + * by Oracle in the LICENSE file that accompanied this code.
  159.13 + *
  159.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  159.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  159.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  159.17 + * version 2 for more details (a copy is included in the LICENSE file that
  159.18 + * accompanied this code).
  159.19 + *
  159.20 + * You should have received a copy of the GNU General Public License version
  159.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  159.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  159.23 + *
  159.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  159.25 + * or visit www.oracle.com if you need additional information or have any
  159.26 + * questions.
  159.27 + */
  159.28 +
  159.29 +package java.lang.annotation;
  159.30 +
  159.31 +/**
  159.32 + * Annotation retention policy.  The constants of this enumerated type
  159.33 + * describe the various policies for retaining annotations.  They are used
  159.34 + * in conjunction with the {@link Retention} meta-annotation type to specify
  159.35 + * how long annotations are to be retained.
  159.36 + *
  159.37 + * @author  Joshua Bloch
  159.38 + * @since 1.5
  159.39 + */
  159.40 +public enum RetentionPolicy {
  159.41 +    /**
  159.42 +     * Annotations are to be discarded by the compiler.
  159.43 +     */
  159.44 +    SOURCE,
  159.45 +
  159.46 +    /**
  159.47 +     * Annotations are to be recorded in the class file by the compiler
  159.48 +     * but need not be retained by the VM at run time.  This is the default
  159.49 +     * behavior.
  159.50 +     */
  159.51 +    CLASS,
  159.52 +
  159.53 +    /**
  159.54 +     * Annotations are to be recorded in the class file by the compiler and
  159.55 +     * retained by the VM at run time, so they may be read reflectively.
  159.56 +     *
  159.57 +     * @see java.lang.reflect.AnnotatedElement
  159.58 +     */
  159.59 +    RUNTIME
  159.60 +}
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/Target.java	Wed Apr 30 15:04:10 2014 +0200
   160.3 @@ -0,0 +1,68 @@
   160.4 +/*
   160.5 + * Copyright (c) 2003, 2004, 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.lang.annotation;
  160.30 +
  160.31 +/**
  160.32 + * Indicates the kinds of program element to which an annotation type
  160.33 + * is applicable.  If a Target meta-annotation is not present on an
  160.34 + * annotation type declaration, the declared type may be used on any
  160.35 + * program element.  If such a meta-annotation is present, the compiler
  160.36 + * will enforce the specified usage restriction.
  160.37 + *
  160.38 + * For example, this meta-annotation indicates that the declared type is
  160.39 + * itself a meta-annotation type.  It can only be used on annotation type
  160.40 + * declarations:
  160.41 + * <pre>
  160.42 + *    &#064;Target(ElementType.ANNOTATION_TYPE)
  160.43 + *    public &#064;interface MetaAnnotationType {
  160.44 + *        ...
  160.45 + *    }
  160.46 + * </pre>
  160.47 + * This meta-annotation indicates that the declared type is intended solely
  160.48 + * for use as a member type in complex annotation type declarations.  It
  160.49 + * cannot be used to annotate anything directly:
  160.50 + * <pre>
  160.51 + *    &#064;Target({})
  160.52 + *    public &#064;interface MemberType {
  160.53 + *        ...
  160.54 + *    }
  160.55 + * </pre>
  160.56 + * It is a compile-time error for a single ElementType constant to
  160.57 + * appear more than once in a Target annotation.  For example, the
  160.58 + * following meta-annotation is illegal:
  160.59 + * <pre>
  160.60 + *    &#064;Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
  160.61 + *    public &#064;interface Bogus {
  160.62 + *        ...
  160.63 + *    }
  160.64 + * </pre>
  160.65 + */
  160.66 +@Documented
  160.67 +@Retention(RetentionPolicy.RUNTIME)
  160.68 +@Target(ElementType.ANNOTATION_TYPE)
  160.69 +public @interface Target {
  160.70 +    ElementType[] value();
  160.71 +}
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/rt/emul/compact/src/main/java/java/lang/annotation/package-info.java	Wed Apr 30 15:04:10 2014 +0200
   161.3 @@ -0,0 +1,33 @@
   161.4 +/*
   161.5 + * Copyright (c) 2004, 2006, 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 +/**
  161.30 + * Provides library support for the Java programming language
  161.31 + * annotation facility.
  161.32 + *
  161.33 + * @author Josh Bloch
  161.34 + * @since 1.5
  161.35 + */
  161.36 +package java.lang.annotation;
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/rt/emul/compact/src/main/java/java/math/BigDecimal.java	Wed Apr 30 15:04:10 2014 +0200
   162.3 @@ -0,0 +1,3842 @@
   162.4 +/*
   162.5 + * Copyright (c) 1996, 2011, 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 +/*
  162.30 + * Portions Copyright IBM Corporation, 2001. All Rights Reserved.
  162.31 + */
  162.32 +
  162.33 +package java.math;
  162.34 +
  162.35 +import java.util.Arrays;
  162.36 +import static java.math.BigInteger.LONG_MASK;
  162.37 +
  162.38 +/**
  162.39 + * Immutable, arbitrary-precision signed decimal numbers.  A
  162.40 + * {@code BigDecimal} consists of an arbitrary precision integer
  162.41 + * <i>unscaled value</i> and a 32-bit integer <i>scale</i>.  If zero
  162.42 + * or positive, the scale is the number of digits to the right of the
  162.43 + * decimal point.  If negative, the unscaled value of the number is
  162.44 + * multiplied by ten to the power of the negation of the scale.  The
  162.45 + * value of the number represented by the {@code BigDecimal} is
  162.46 + * therefore <tt>(unscaledValue &times; 10<sup>-scale</sup>)</tt>.
  162.47 + *
  162.48 + * <p>The {@code BigDecimal} class provides operations for
  162.49 + * arithmetic, scale manipulation, rounding, comparison, hashing, and
  162.50 + * format conversion.  The {@link #toString} method provides a
  162.51 + * canonical representation of a {@code BigDecimal}.
  162.52 + *
  162.53 + * <p>The {@code BigDecimal} class gives its user complete control
  162.54 + * over rounding behavior.  If no rounding mode is specified and the
  162.55 + * exact result cannot be represented, an exception is thrown;
  162.56 + * otherwise, calculations can be carried out to a chosen precision
  162.57 + * and rounding mode by supplying an appropriate {@link MathContext}
  162.58 + * object to the operation.  In either case, eight <em>rounding
  162.59 + * modes</em> are provided for the control of rounding.  Using the
  162.60 + * integer fields in this class (such as {@link #ROUND_HALF_UP}) to
  162.61 + * represent rounding mode is largely obsolete; the enumeration values
  162.62 + * of the {@code RoundingMode} {@code enum}, (such as {@link
  162.63 + * RoundingMode#HALF_UP}) should be used instead.
  162.64 + *
  162.65 + * <p>When a {@code MathContext} object is supplied with a precision
  162.66 + * setting of 0 (for example, {@link MathContext#UNLIMITED}),
  162.67 + * arithmetic operations are exact, as are the arithmetic methods
  162.68 + * which take no {@code MathContext} object.  (This is the only
  162.69 + * behavior that was supported in releases prior to 5.)  As a
  162.70 + * corollary of computing the exact result, the rounding mode setting
  162.71 + * of a {@code MathContext} object with a precision setting of 0 is
  162.72 + * not used and thus irrelevant.  In the case of divide, the exact
  162.73 + * quotient could have an infinitely long decimal expansion; for
  162.74 + * example, 1 divided by 3.  If the quotient has a nonterminating
  162.75 + * decimal expansion and the operation is specified to return an exact
  162.76 + * result, an {@code ArithmeticException} is thrown.  Otherwise, the
  162.77 + * exact result of the division is returned, as done for other
  162.78 + * operations.
  162.79 + *
  162.80 + * <p>When the precision setting is not 0, the rules of
  162.81 + * {@code BigDecimal} arithmetic are broadly compatible with selected
  162.82 + * modes of operation of the arithmetic defined in ANSI X3.274-1996
  162.83 + * and ANSI X3.274-1996/AM 1-2000 (section 7.4).  Unlike those
  162.84 + * standards, {@code BigDecimal} includes many rounding modes, which
  162.85 + * were mandatory for division in {@code BigDecimal} releases prior
  162.86 + * to 5.  Any conflicts between these ANSI standards and the
  162.87 + * {@code BigDecimal} specification are resolved in favor of
  162.88 + * {@code BigDecimal}.
  162.89 + *
  162.90 + * <p>Since the same numerical value can have different
  162.91 + * representations (with different scales), the rules of arithmetic
  162.92 + * and rounding must specify both the numerical result and the scale
  162.93 + * used in the result's representation.
  162.94 + *
  162.95 + *
  162.96 + * <p>In general the rounding modes and precision setting determine
  162.97 + * how operations return results with a limited number of digits when
  162.98 + * the exact result has more digits (perhaps infinitely many in the
  162.99 + * case of division) than the number of digits returned.
 162.100 + *
 162.101 + * First, the
 162.102 + * total number of digits to return is specified by the
 162.103 + * {@code MathContext}'s {@code precision} setting; this determines
 162.104 + * the result's <i>precision</i>.  The digit count starts from the
 162.105 + * leftmost nonzero digit of the exact result.  The rounding mode
 162.106 + * determines how any discarded trailing digits affect the returned
 162.107 + * result.
 162.108 + *
 162.109 + * <p>For all arithmetic operators , the operation is carried out as
 162.110 + * though an exact intermediate result were first calculated and then
 162.111 + * rounded to the number of digits specified by the precision setting
 162.112 + * (if necessary), using the selected rounding mode.  If the exact
 162.113 + * result is not returned, some digit positions of the exact result
 162.114 + * are discarded.  When rounding increases the magnitude of the
 162.115 + * returned result, it is possible for a new digit position to be
 162.116 + * created by a carry propagating to a leading {@literal "9"} digit.
 162.117 + * For example, rounding the value 999.9 to three digits rounding up
 162.118 + * would be numerically equal to one thousand, represented as
 162.119 + * 100&times;10<sup>1</sup>.  In such cases, the new {@literal "1"} is
 162.120 + * the leading digit position of the returned result.
 162.121 + *
 162.122 + * <p>Besides a logical exact result, each arithmetic operation has a
 162.123 + * preferred scale for representing a result.  The preferred
 162.124 + * scale for each operation is listed in the table below.
 162.125 + *
 162.126 + * <table border>
 162.127 + * <caption><b>Preferred Scales for Results of Arithmetic Operations
 162.128 + * </b></caption>
 162.129 + * <tr><th>Operation</th><th>Preferred Scale of Result</th></tr>
 162.130 + * <tr><td>Add</td><td>max(addend.scale(), augend.scale())</td>
 162.131 + * <tr><td>Subtract</td><td>max(minuend.scale(), subtrahend.scale())</td>
 162.132 + * <tr><td>Multiply</td><td>multiplier.scale() + multiplicand.scale()</td>
 162.133 + * <tr><td>Divide</td><td>dividend.scale() - divisor.scale()</td>
 162.134 + * </table>
 162.135 + *
 162.136 + * These scales are the ones used by the methods which return exact
 162.137 + * arithmetic results; except that an exact divide may have to use a
 162.138 + * larger scale since the exact result may have more digits.  For
 162.139 + * example, {@code 1/32} is {@code 0.03125}.
 162.140 + *
 162.141 + * <p>Before rounding, the scale of the logical exact intermediate
 162.142 + * result is the preferred scale for that operation.  If the exact
 162.143 + * numerical result cannot be represented in {@code precision}
 162.144 + * digits, rounding selects the set of digits to return and the scale
 162.145 + * of the result is reduced from the scale of the intermediate result
 162.146 + * to the least scale which can represent the {@code precision}
 162.147 + * digits actually returned.  If the exact result can be represented
 162.148 + * with at most {@code precision} digits, the representation
 162.149 + * of the result with the scale closest to the preferred scale is
 162.150 + * returned.  In particular, an exactly representable quotient may be
 162.151 + * represented in fewer than {@code precision} digits by removing
 162.152 + * trailing zeros and decreasing the scale.  For example, rounding to
 162.153 + * three digits using the {@linkplain RoundingMode#FLOOR floor}
 162.154 + * rounding mode, <br>
 162.155 + *
 162.156 + * {@code 19/100 = 0.19   // integer=19,  scale=2} <br>
 162.157 + *
 162.158 + * but<br>
 162.159 + *
 162.160 + * {@code 21/110 = 0.190  // integer=190, scale=3} <br>
 162.161 + *
 162.162 + * <p>Note that for add, subtract, and multiply, the reduction in
 162.163 + * scale will equal the number of digit positions of the exact result
 162.164 + * which are discarded. If the rounding causes a carry propagation to
 162.165 + * create a new high-order digit position, an additional digit of the
 162.166 + * result is discarded than when no new digit position is created.
 162.167 + *
 162.168 + * <p>Other methods may have slightly different rounding semantics.
 162.169 + * For example, the result of the {@code pow} method using the
 162.170 + * {@linkplain #pow(int, MathContext) specified algorithm} can
 162.171 + * occasionally differ from the rounded mathematical result by more
 162.172 + * than one unit in the last place, one <i>{@linkplain #ulp() ulp}</i>.
 162.173 + *
 162.174 + * <p>Two types of operations are provided for manipulating the scale
 162.175 + * of a {@code BigDecimal}: scaling/rounding operations and decimal
 162.176 + * point motion operations.  Scaling/rounding operations ({@link
 162.177 + * #setScale setScale} and {@link #round round}) return a
 162.178 + * {@code BigDecimal} whose value is approximately (or exactly) equal
 162.179 + * to that of the operand, but whose scale or precision is the
 162.180 + * specified value; that is, they increase or decrease the precision
 162.181 + * of the stored number with minimal effect on its value.  Decimal
 162.182 + * point motion operations ({@link #movePointLeft movePointLeft} and
 162.183 + * {@link #movePointRight movePointRight}) return a
 162.184 + * {@code BigDecimal} created from the operand by moving the decimal
 162.185 + * point a specified distance in the specified direction.
 162.186 + *
 162.187 + * <p>For the sake of brevity and clarity, pseudo-code is used
 162.188 + * throughout the descriptions of {@code BigDecimal} methods.  The
 162.189 + * pseudo-code expression {@code (i + j)} is shorthand for "a
 162.190 + * {@code BigDecimal} whose value is that of the {@code BigDecimal}
 162.191 + * {@code i} added to that of the {@code BigDecimal}
 162.192 + * {@code j}." The pseudo-code expression {@code (i == j)} is
 162.193 + * shorthand for "{@code true} if and only if the
 162.194 + * {@code BigDecimal} {@code i} represents the same value as the
 162.195 + * {@code BigDecimal} {@code j}." Other pseudo-code expressions
 162.196 + * are interpreted similarly.  Square brackets are used to represent
 162.197 + * the particular {@code BigInteger} and scale pair defining a
 162.198 + * {@code BigDecimal} value; for example [19, 2] is the
 162.199 + * {@code BigDecimal} numerically equal to 0.19 having a scale of 2.
 162.200 + *
 162.201 + * <p>Note: care should be exercised if {@code BigDecimal} objects
 162.202 + * are used as keys in a {@link java.util.SortedMap SortedMap} or
 162.203 + * elements in a {@link java.util.SortedSet SortedSet} since
 162.204 + * {@code BigDecimal}'s <i>natural ordering</i> is <i>inconsistent
 162.205 + * with equals</i>.  See {@link Comparable}, {@link
 162.206 + * java.util.SortedMap} or {@link java.util.SortedSet} for more
 162.207 + * information.
 162.208 + *
 162.209 + * <p>All methods and constructors for this class throw
 162.210 + * {@code NullPointerException} when passed a {@code null} object
 162.211 + * reference for any input parameter.
 162.212 + *
 162.213 + * @see     BigInteger
 162.214 + * @see     MathContext
 162.215 + * @see     RoundingMode
 162.216 + * @see     java.util.SortedMap
 162.217 + * @see     java.util.SortedSet
 162.218 + * @author  Josh Bloch
 162.219 + * @author  Mike Cowlishaw
 162.220 + * @author  Joseph D. Darcy
 162.221 + */
 162.222 +public class BigDecimal extends Number implements Comparable<BigDecimal> {
 162.223 +    /**
 162.224 +     * The unscaled value of this BigDecimal, as returned by {@link
 162.225 +     * #unscaledValue}.
 162.226 +     *
 162.227 +     * @serial
 162.228 +     * @see #unscaledValue
 162.229 +     */
 162.230 +    private volatile BigInteger intVal;
 162.231 +
 162.232 +    /**
 162.233 +     * The scale of this BigDecimal, as returned by {@link #scale}.
 162.234 +     *
 162.235 +     * @serial
 162.236 +     * @see #scale
 162.237 +     */
 162.238 +    private int scale;  // Note: this may have any value, so
 162.239 +                        // calculations must be done in longs
 162.240 +    /**
 162.241 +     * The number of decimal digits in this BigDecimal, or 0 if the
 162.242 +     * number of digits are not known (lookaside information).  If
 162.243 +     * nonzero, the value is guaranteed correct.  Use the precision()
 162.244 +     * method to obtain and set the value if it might be 0.  This
 162.245 +     * field is mutable until set nonzero.
 162.246 +     *
 162.247 +     * @since  1.5
 162.248 +     */
 162.249 +    private transient int precision;
 162.250 +
 162.251 +    /**
 162.252 +     * Used to store the canonical string representation, if computed.
 162.253 +     */
 162.254 +    private transient String stringCache;
 162.255 +
 162.256 +    /**
 162.257 +     * Sentinel value for {@link #intCompact} indicating the
 162.258 +     * significand information is only available from {@code intVal}.
 162.259 +     */
 162.260 +    static final long INFLATED = Long.MIN_VALUE;
 162.261 +
 162.262 +    /**
 162.263 +     * If the absolute value of the significand of this BigDecimal is
 162.264 +     * less than or equal to {@code Long.MAX_VALUE}, the value can be
 162.265 +     * compactly stored in this field and used in computations.
 162.266 +     */
 162.267 +    private transient long intCompact;
 162.268 +
 162.269 +    // All 18-digit base ten strings fit into a long; not all 19-digit
 162.270 +    // strings will
 162.271 +    private static final int MAX_COMPACT_DIGITS = 18;
 162.272 +
 162.273 +    private static final int MAX_BIGINT_BITS = 62;
 162.274 +
 162.275 +    /* Appease the serialization gods */
 162.276 +    private static final long serialVersionUID = 6108874887143696463L;
 162.277 +
 162.278 +    // Cache of common small BigDecimal values.
 162.279 +    private static final BigDecimal zeroThroughTen[] = {
 162.280 +        new BigDecimal(BigInteger.ZERO,         0,  0, 1),
 162.281 +        new BigDecimal(BigInteger.ONE,          1,  0, 1),
 162.282 +        new BigDecimal(BigInteger.valueOf(2),   2,  0, 1),
 162.283 +        new BigDecimal(BigInteger.valueOf(3),   3,  0, 1),
 162.284 +        new BigDecimal(BigInteger.valueOf(4),   4,  0, 1),
 162.285 +        new BigDecimal(BigInteger.valueOf(5),   5,  0, 1),
 162.286 +        new BigDecimal(BigInteger.valueOf(6),   6,  0, 1),
 162.287 +        new BigDecimal(BigInteger.valueOf(7),   7,  0, 1),
 162.288 +        new BigDecimal(BigInteger.valueOf(8),   8,  0, 1),
 162.289 +        new BigDecimal(BigInteger.valueOf(9),   9,  0, 1),
 162.290 +        new BigDecimal(BigInteger.TEN,          10, 0, 2),
 162.291 +    };
 162.292 +
 162.293 +    // Cache of zero scaled by 0 - 15
 162.294 +    private static final BigDecimal[] ZERO_SCALED_BY = {
 162.295 +        zeroThroughTen[0],
 162.296 +        new BigDecimal(BigInteger.ZERO, 0, 1, 1),
 162.297 +        new BigDecimal(BigInteger.ZERO, 0, 2, 1),
 162.298 +        new BigDecimal(BigInteger.ZERO, 0, 3, 1),
 162.299 +        new BigDecimal(BigInteger.ZERO, 0, 4, 1),
 162.300 +        new BigDecimal(BigInteger.ZERO, 0, 5, 1),
 162.301 +        new BigDecimal(BigInteger.ZERO, 0, 6, 1),
 162.302 +        new BigDecimal(BigInteger.ZERO, 0, 7, 1),
 162.303 +        new BigDecimal(BigInteger.ZERO, 0, 8, 1),
 162.304 +        new BigDecimal(BigInteger.ZERO, 0, 9, 1),
 162.305 +        new BigDecimal(BigInteger.ZERO, 0, 10, 1),
 162.306 +        new BigDecimal(BigInteger.ZERO, 0, 11, 1),
 162.307 +        new BigDecimal(BigInteger.ZERO, 0, 12, 1),
 162.308 +        new BigDecimal(BigInteger.ZERO, 0, 13, 1),
 162.309 +        new BigDecimal(BigInteger.ZERO, 0, 14, 1),
 162.310 +        new BigDecimal(BigInteger.ZERO, 0, 15, 1),
 162.311 +    };
 162.312 +
 162.313 +    // Half of Long.MIN_VALUE & Long.MAX_VALUE.
 162.314 +    private static final long HALF_LONG_MAX_VALUE = Long.MAX_VALUE / 2;
 162.315 +    private static final long HALF_LONG_MIN_VALUE = Long.MIN_VALUE / 2;
 162.316 +
 162.317 +    // Constants
 162.318 +    /**
 162.319 +     * The value 0, with a scale of 0.
 162.320 +     *
 162.321 +     * @since  1.5
 162.322 +     */
 162.323 +    public static final BigDecimal ZERO =
 162.324 +        zeroThroughTen[0];
 162.325 +
 162.326 +    /**
 162.327 +     * The value 1, with a scale of 0.
 162.328 +     *
 162.329 +     * @since  1.5
 162.330 +     */
 162.331 +    public static final BigDecimal ONE =
 162.332 +        zeroThroughTen[1];
 162.333 +
 162.334 +    /**
 162.335 +     * The value 10, with a scale of 0.
 162.336 +     *
 162.337 +     * @since  1.5
 162.338 +     */
 162.339 +    public static final BigDecimal TEN =
 162.340 +        zeroThroughTen[10];
 162.341 +
 162.342 +    // Constructors
 162.343 +
 162.344 +    /**
 162.345 +     * Trusted package private constructor.
 162.346 +     * Trusted simply means if val is INFLATED, intVal could not be null and
 162.347 +     * if intVal is null, val could not be INFLATED.
 162.348 +     */
 162.349 +    BigDecimal(BigInteger intVal, long val, int scale, int prec) {
 162.350 +        this.scale = scale;
 162.351 +        this.precision = prec;
 162.352 +        this.intCompact = val;
 162.353 +        this.intVal = intVal;
 162.354 +    }
 162.355 +
 162.356 +    /**
 162.357 +     * Translates a character array representation of a
 162.358 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 162.359 +     * same sequence of characters as the {@link #BigDecimal(String)}
 162.360 +     * constructor, while allowing a sub-array to be specified.
 162.361 +     *
 162.362 +     * <p>Note that if the sequence of characters is already available
 162.363 +     * within a character array, using this constructor is faster than
 162.364 +     * converting the {@code char} array to string and using the
 162.365 +     * {@code BigDecimal(String)} constructor .
 162.366 +     *
 162.367 +     * @param  in {@code char} array that is the source of characters.
 162.368 +     * @param  offset first character in the array to inspect.
 162.369 +     * @param  len number of characters to consider.
 162.370 +     * @throws NumberFormatException if {@code in} is not a valid
 162.371 +     *         representation of a {@code BigDecimal} or the defined subarray
 162.372 +     *         is not wholly within {@code in}.
 162.373 +     * @since  1.5
 162.374 +     */
 162.375 +    public BigDecimal(char[] in, int offset, int len) {
 162.376 +        // protect against huge length.
 162.377 +        if (offset+len > in.length || offset < 0)
 162.378 +            throw new NumberFormatException();
 162.379 +        // This is the primary string to BigDecimal constructor; all
 162.380 +        // incoming strings end up here; it uses explicit (inline)
 162.381 +        // parsing for speed and generates at most one intermediate
 162.382 +        // (temporary) object (a char[] array) for non-compact case.
 162.383 +
 162.384 +        // Use locals for all fields values until completion
 162.385 +        int prec = 0;                 // record precision value
 162.386 +        int scl = 0;                  // record scale value
 162.387 +        long rs = 0;                  // the compact value in long
 162.388 +        BigInteger rb = null;         // the inflated value in BigInteger
 162.389 +
 162.390 +        // use array bounds checking to handle too-long, len == 0,
 162.391 +        // bad offset, etc.
 162.392 +        try {
 162.393 +            // handle the sign
 162.394 +            boolean isneg = false;          // assume positive
 162.395 +            if (in[offset] == '-') {
 162.396 +                isneg = true;               // leading minus means negative
 162.397 +                offset++;
 162.398 +                len--;
 162.399 +            } else if (in[offset] == '+') { // leading + allowed
 162.400 +                offset++;
 162.401 +                len--;
 162.402 +            }
 162.403 +
 162.404 +            // should now be at numeric part of the significand
 162.405 +            boolean dot = false;             // true when there is a '.'
 162.406 +            int cfirst = offset;             // record start of integer
 162.407 +            long exp = 0;                    // exponent
 162.408 +            char c;                          // current character
 162.409 +
 162.410 +            boolean isCompact = (len <= MAX_COMPACT_DIGITS);
 162.411 +            // integer significand array & idx is the index to it. The array
 162.412 +            // is ONLY used when we can't use a compact representation.
 162.413 +            char coeff[] = isCompact ? null : new char[len];
 162.414 +            int idx = 0;
 162.415 +
 162.416 +            for (; len > 0; offset++, len--) {
 162.417 +                c = in[offset];
 162.418 +                // have digit
 162.419 +                if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
 162.420 +                    // First compact case, we need not to preserve the character
 162.421 +                    // and we can just compute the value in place.
 162.422 +                    if (isCompact) {
 162.423 +                        int digit = Character.digit(c, 10);
 162.424 +                        if (digit == 0) {
 162.425 +                            if (prec == 0)
 162.426 +                                prec = 1;
 162.427 +                            else if (rs != 0) {
 162.428 +                                rs *= 10;
 162.429 +                                ++prec;
 162.430 +                            } // else digit is a redundant leading zero
 162.431 +                        } else {
 162.432 +                            if (prec != 1 || rs != 0)
 162.433 +                                ++prec; // prec unchanged if preceded by 0s
 162.434 +                            rs = rs * 10 + digit;
 162.435 +                        }
 162.436 +                    } else { // the unscaled value is likely a BigInteger object.
 162.437 +                        if (c == '0' || Character.digit(c, 10) == 0) {
 162.438 +                            if (prec == 0) {
 162.439 +                                coeff[idx] = c;
 162.440 +                                prec = 1;
 162.441 +                            } else if (idx != 0) {
 162.442 +                                coeff[idx++] = c;
 162.443 +                                ++prec;
 162.444 +                            } // else c must be a redundant leading zero
 162.445 +                        } else {
 162.446 +                            if (prec != 1 || idx != 0)
 162.447 +                                ++prec; // prec unchanged if preceded by 0s
 162.448 +                            coeff[idx++] = c;
 162.449 +                        }
 162.450 +                    }
 162.451 +                    if (dot)
 162.452 +                        ++scl;
 162.453 +                    continue;
 162.454 +                }
 162.455 +                // have dot
 162.456 +                if (c == '.') {
 162.457 +                    // have dot
 162.458 +                    if (dot)         // two dots
 162.459 +                        throw new NumberFormatException();
 162.460 +                    dot = true;
 162.461 +                    continue;
 162.462 +                }
 162.463 +                // exponent expected
 162.464 +                if ((c != 'e') && (c != 'E'))
 162.465 +                    throw new NumberFormatException();
 162.466 +                offset++;
 162.467 +                c = in[offset];
 162.468 +                len--;
 162.469 +                boolean negexp = (c == '-');
 162.470 +                // optional sign
 162.471 +                if (negexp || c == '+') {
 162.472 +                    offset++;
 162.473 +                    c = in[offset];
 162.474 +                    len--;
 162.475 +                }
 162.476 +                if (len <= 0)    // no exponent digits
 162.477 +                    throw new NumberFormatException();
 162.478 +                // skip leading zeros in the exponent
 162.479 +                while (len > 10 && Character.digit(c, 10) == 0) {
 162.480 +                    offset++;
 162.481 +                    c = in[offset];
 162.482 +                    len--;
 162.483 +                }
 162.484 +                if (len > 10)  // too many nonzero exponent digits
 162.485 +                    throw new NumberFormatException();
 162.486 +                // c now holds first digit of exponent
 162.487 +                for (;; len--) {
 162.488 +                    int v;
 162.489 +                    if (c >= '0' && c <= '9') {
 162.490 +                        v = c - '0';
 162.491 +                    } else {
 162.492 +                        v = Character.digit(c, 10);
 162.493 +                        if (v < 0)            // not a digit
 162.494 +                            throw new NumberFormatException();
 162.495 +                    }
 162.496 +                    exp = exp * 10 + v;
 162.497 +                    if (len == 1)
 162.498 +                        break;               // that was final character
 162.499 +                    offset++;
 162.500 +                    c = in[offset];
 162.501 +                }
 162.502 +                if (negexp)                  // apply sign
 162.503 +                    exp = -exp;
 162.504 +                // Next test is required for backwards compatibility
 162.505 +                if ((int)exp != exp)         // overflow
 162.506 +                    throw new NumberFormatException();
 162.507 +                break;                       // [saves a test]
 162.508 +            }
 162.509 +            // here when no characters left
 162.510 +            if (prec == 0)              // no digits found
 162.511 +                throw new NumberFormatException();
 162.512 +
 162.513 +            // Adjust scale if exp is not zero.
 162.514 +            if (exp != 0) {                  // had significant exponent
 162.515 +                // Can't call checkScale which relies on proper fields value
 162.516 +                long adjustedScale = scl - exp;
 162.517 +                if (adjustedScale > Integer.MAX_VALUE ||
 162.518 +                    adjustedScale < Integer.MIN_VALUE)
 162.519 +                    throw new NumberFormatException("Scale out of range.");
 162.520 +                scl = (int)adjustedScale;
 162.521 +            }
 162.522 +
 162.523 +            // Remove leading zeros from precision (digits count)
 162.524 +            if (isCompact) {
 162.525 +                rs = isneg ? -rs : rs;
 162.526 +            } else {
 162.527 +                char quick[];
 162.528 +                if (!isneg) {
 162.529 +                    quick = (coeff.length != prec) ?
 162.530 +                        Arrays.copyOf(coeff, prec) : coeff;
 162.531 +                } else {
 162.532 +                    quick = new char[prec + 1];
 162.533 +                    quick[0] = '-';
 162.534 +                    System.arraycopy(coeff, 0, quick, 1, prec);
 162.535 +                }
 162.536 +                rb = new BigInteger(quick);
 162.537 +                rs = compactValFor(rb);
 162.538 +            }
 162.539 +        } catch (ArrayIndexOutOfBoundsException e) {
 162.540 +            throw new NumberFormatException();
 162.541 +        } catch (NegativeArraySizeException e) {
 162.542 +            throw new NumberFormatException();
 162.543 +        }
 162.544 +        this.scale = scl;
 162.545 +        this.precision = prec;
 162.546 +        this.intCompact = rs;
 162.547 +        this.intVal = (rs != INFLATED) ? null : rb;
 162.548 +    }
 162.549 +
 162.550 +    /**
 162.551 +     * Translates a character array representation of a
 162.552 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 162.553 +     * same sequence of characters as the {@link #BigDecimal(String)}
 162.554 +     * constructor, while allowing a sub-array to be specified and
 162.555 +     * with rounding according to the context settings.
 162.556 +     *
 162.557 +     * <p>Note that if the sequence of characters is already available
 162.558 +     * within a character array, using this constructor is faster than
 162.559 +     * converting the {@code char} array to string and using the
 162.560 +     * {@code BigDecimal(String)} constructor .
 162.561 +     *
 162.562 +     * @param  in {@code char} array that is the source of characters.
 162.563 +     * @param  offset first character in the array to inspect.
 162.564 +     * @param  len number of characters to consider..
 162.565 +     * @param  mc the context to use.
 162.566 +     * @throws ArithmeticException if the result is inexact but the
 162.567 +     *         rounding mode is {@code UNNECESSARY}.
 162.568 +     * @throws NumberFormatException if {@code in} is not a valid
 162.569 +     *         representation of a {@code BigDecimal} or the defined subarray
 162.570 +     *         is not wholly within {@code in}.
 162.571 +     * @since  1.5
 162.572 +     */
 162.573 +    public BigDecimal(char[] in, int offset, int len, MathContext mc) {
 162.574 +        this(in, offset, len);
 162.575 +        if (mc.precision > 0)
 162.576 +            roundThis(mc);
 162.577 +    }
 162.578 +
 162.579 +    /**
 162.580 +     * Translates a character array representation of a
 162.581 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 162.582 +     * same sequence of characters as the {@link #BigDecimal(String)}
 162.583 +     * constructor.
 162.584 +     *
 162.585 +     * <p>Note that if the sequence of characters is already available
 162.586 +     * as a character array, using this constructor is faster than
 162.587 +     * converting the {@code char} array to string and using the
 162.588 +     * {@code BigDecimal(String)} constructor .
 162.589 +     *
 162.590 +     * @param in {@code char} array that is the source of characters.
 162.591 +     * @throws NumberFormatException if {@code in} is not a valid
 162.592 +     *         representation of a {@code BigDecimal}.
 162.593 +     * @since  1.5
 162.594 +     */
 162.595 +    public BigDecimal(char[] in) {
 162.596 +        this(in, 0, in.length);
 162.597 +    }
 162.598 +
 162.599 +    /**
 162.600 +     * Translates a character array representation of a
 162.601 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 162.602 +     * same sequence of characters as the {@link #BigDecimal(String)}
 162.603 +     * constructor and with rounding according to the context
 162.604 +     * settings.
 162.605 +     *
 162.606 +     * <p>Note that if the sequence of characters is already available
 162.607 +     * as a character array, using this constructor is faster than
 162.608 +     * converting the {@code char} array to string and using the
 162.609 +     * {@code BigDecimal(String)} constructor .
 162.610 +     *
 162.611 +     * @param  in {@code char} array that is the source of characters.
 162.612 +     * @param  mc the context to use.
 162.613 +     * @throws ArithmeticException if the result is inexact but the
 162.614 +     *         rounding mode is {@code UNNECESSARY}.
 162.615 +     * @throws NumberFormatException if {@code in} is not a valid
 162.616 +     *         representation of a {@code BigDecimal}.
 162.617 +     * @since  1.5
 162.618 +     */
 162.619 +    public BigDecimal(char[] in, MathContext mc) {
 162.620 +        this(in, 0, in.length, mc);
 162.621 +    }
 162.622 +
 162.623 +    /**
 162.624 +     * Translates the string representation of a {@code BigDecimal}
 162.625 +     * into a {@code BigDecimal}.  The string representation consists
 162.626 +     * of an optional sign, {@code '+'} (<tt> '&#92;u002B'</tt>) or
 162.627 +     * {@code '-'} (<tt>'&#92;u002D'</tt>), followed by a sequence of
 162.628 +     * zero or more decimal digits ("the integer"), optionally
 162.629 +     * followed by a fraction, optionally followed by an exponent.
 162.630 +     *
 162.631 +     * <p>The fraction consists of a decimal point followed by zero
 162.632 +     * or more decimal digits.  The string must contain at least one
 162.633 +     * digit in either the integer or the fraction.  The number formed
 162.634 +     * by the sign, the integer and the fraction is referred to as the
 162.635 +     * <i>significand</i>.
 162.636 +     *
 162.637 +     * <p>The exponent consists of the character {@code 'e'}
 162.638 +     * (<tt>'&#92;u0065'</tt>) or {@code 'E'} (<tt>'&#92;u0045'</tt>)
 162.639 +     * followed by one or more decimal digits.  The value of the
 162.640 +     * exponent must lie between -{@link Integer#MAX_VALUE} ({@link
 162.641 +     * Integer#MIN_VALUE}+1) and {@link Integer#MAX_VALUE}, inclusive.
 162.642 +     *
 162.643 +     * <p>More formally, the strings this constructor accepts are
 162.644 +     * described by the following grammar:
 162.645 +     * <blockquote>
 162.646 +     * <dl>
 162.647 +     * <dt><i>BigDecimalString:</i>
 162.648 +     * <dd><i>Sign<sub>opt</sub> Significand Exponent<sub>opt</sub></i>
 162.649 +     * <p>
 162.650 +     * <dt><i>Sign:</i>
 162.651 +     * <dd>{@code +}
 162.652 +     * <dd>{@code -}
 162.653 +     * <p>
 162.654 +     * <dt><i>Significand:</i>
 162.655 +     * <dd><i>IntegerPart</i> {@code .} <i>FractionPart<sub>opt</sub></i>
 162.656 +     * <dd>{@code .} <i>FractionPart</i>
 162.657 +     * <dd><i>IntegerPart</i>
 162.658 +     * <p>
 162.659 +     * <dt><i>IntegerPart:</i>
 162.660 +     * <dd><i>Digits</i>
 162.661 +     * <p>
 162.662 +     * <dt><i>FractionPart:</i>
 162.663 +     * <dd><i>Digits</i>
 162.664 +     * <p>
 162.665 +     * <dt><i>Exponent:</i>
 162.666 +     * <dd><i>ExponentIndicator SignedInteger</i>
 162.667 +     * <p>
 162.668 +     * <dt><i>ExponentIndicator:</i>
 162.669 +     * <dd>{@code e}
 162.670 +     * <dd>{@code E}
 162.671 +     * <p>
 162.672 +     * <dt><i>SignedInteger:</i>
 162.673 +     * <dd><i>Sign<sub>opt</sub> Digits</i>
 162.674 +     * <p>
 162.675 +     * <dt><i>Digits:</i>
 162.676 +     * <dd><i>Digit</i>
 162.677 +     * <dd><i>Digits Digit</i>
 162.678 +     * <p>
 162.679 +     * <dt><i>Digit:</i>
 162.680 +     * <dd>any character for which {@link Character#isDigit}
 162.681 +     * returns {@code true}, including 0, 1, 2 ...
 162.682 +     * </dl>
 162.683 +     * </blockquote>
 162.684 +     *
 162.685 +     * <p>The scale of the returned {@code BigDecimal} will be the
 162.686 +     * number of digits in the fraction, or zero if the string
 162.687 +     * contains no decimal point, subject to adjustment for any
 162.688 +     * exponent; if the string contains an exponent, the exponent is
 162.689 +     * subtracted from the scale.  The value of the resulting scale
 162.690 +     * must lie between {@code Integer.MIN_VALUE} and
 162.691 +     * {@code Integer.MAX_VALUE}, inclusive.
 162.692 +     *
 162.693 +     * <p>The character-to-digit mapping is provided by {@link
 162.694 +     * java.lang.Character#digit} set to convert to radix 10.  The
 162.695 +     * String may not contain any extraneous characters (whitespace,
 162.696 +     * for example).
 162.697 +     *
 162.698 +     * <p><b>Examples:</b><br>
 162.699 +     * The value of the returned {@code BigDecimal} is equal to
 162.700 +     * <i>significand</i> &times; 10<sup>&nbsp;<i>exponent</i></sup>.
 162.701 +     * For each string on the left, the resulting representation
 162.702 +     * [{@code BigInteger}, {@code scale}] is shown on the right.
 162.703 +     * <pre>
 162.704 +     * "0"            [0,0]
 162.705 +     * "0.00"         [0,2]
 162.706 +     * "123"          [123,0]
 162.707 +     * "-123"         [-123,0]
 162.708 +     * "1.23E3"       [123,-1]
 162.709 +     * "1.23E+3"      [123,-1]
 162.710 +     * "12.3E+7"      [123,-6]
 162.711 +     * "12.0"         [120,1]
 162.712 +     * "12.3"         [123,1]
 162.713 +     * "0.00123"      [123,5]
 162.714 +     * "-1.23E-12"    [-123,14]
 162.715 +     * "1234.5E-4"    [12345,5]
 162.716 +     * "0E+7"         [0,-7]
 162.717 +     * "-0"           [0,0]
 162.718 +     * </pre>
 162.719 +     *
 162.720 +     * <p>Note: For values other than {@code float} and
 162.721 +     * {@code double} NaN and &plusmn;Infinity, this constructor is
 162.722 +     * compatible with the values returned by {@link Float#toString}
 162.723 +     * and {@link Double#toString}.  This is generally the preferred
 162.724 +     * way to convert a {@code float} or {@code double} into a
 162.725 +     * BigDecimal, as it doesn't suffer from the unpredictability of
 162.726 +     * the {@link #BigDecimal(double)} constructor.
 162.727 +     *
 162.728 +     * @param val String representation of {@code BigDecimal}.
 162.729 +     *
 162.730 +     * @throws NumberFormatException if {@code val} is not a valid
 162.731 +     *         representation of a {@code BigDecimal}.
 162.732 +     */
 162.733 +    public BigDecimal(String val) {
 162.734 +        this(val.toCharArray(), 0, val.length());
 162.735 +    }
 162.736 +
 162.737 +    /**
 162.738 +     * Translates the string representation of a {@code BigDecimal}
 162.739 +     * into a {@code BigDecimal}, accepting the same strings as the
 162.740 +     * {@link #BigDecimal(String)} constructor, with rounding
 162.741 +     * according to the context settings.
 162.742 +     *
 162.743 +     * @param  val string representation of a {@code BigDecimal}.
 162.744 +     * @param  mc the context to use.
 162.745 +     * @throws ArithmeticException if the result is inexact but the
 162.746 +     *         rounding mode is {@code UNNECESSARY}.
 162.747 +     * @throws NumberFormatException if {@code val} is not a valid
 162.748 +     *         representation of a BigDecimal.
 162.749 +     * @since  1.5
 162.750 +     */
 162.751 +    public BigDecimal(String val, MathContext mc) {
 162.752 +        this(val.toCharArray(), 0, val.length());
 162.753 +        if (mc.precision > 0)
 162.754 +            roundThis(mc);
 162.755 +    }
 162.756 +
 162.757 +    /**
 162.758 +     * Translates a {@code double} into a {@code BigDecimal} which
 162.759 +     * is the exact decimal representation of the {@code double}'s
 162.760 +     * binary floating-point value.  The scale of the returned
 162.761 +     * {@code BigDecimal} is the smallest value such that
 162.762 +     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
 162.763 +     * <p>
 162.764 +     * <b>Notes:</b>
 162.765 +     * <ol>
 162.766 +     * <li>
 162.767 +     * The results of this constructor can be somewhat unpredictable.
 162.768 +     * One might assume that writing {@code new BigDecimal(0.1)} in
 162.769 +     * Java creates a {@code BigDecimal} which is exactly equal to
 162.770 +     * 0.1 (an unscaled value of 1, with a scale of 1), but it is
 162.771 +     * actually equal to
 162.772 +     * 0.1000000000000000055511151231257827021181583404541015625.
 162.773 +     * This is because 0.1 cannot be represented exactly as a
 162.774 +     * {@code double} (or, for that matter, as a binary fraction of
 162.775 +     * any finite length).  Thus, the value that is being passed
 162.776 +     * <i>in</i> to the constructor is not exactly equal to 0.1,
 162.777 +     * appearances notwithstanding.
 162.778 +     *
 162.779 +     * <li>
 162.780 +     * The {@code String} constructor, on the other hand, is
 162.781 +     * perfectly predictable: writing {@code new BigDecimal("0.1")}
 162.782 +     * creates a {@code BigDecimal} which is <i>exactly</i> equal to
 162.783 +     * 0.1, as one would expect.  Therefore, it is generally
 162.784 +     * recommended that the {@linkplain #BigDecimal(String)
 162.785 +     * <tt>String</tt> constructor} be used in preference to this one.
 162.786 +     *
 162.787 +     * <li>
 162.788 +     * When a {@code double} must be used as a source for a
 162.789 +     * {@code BigDecimal}, note that this constructor provides an
 162.790 +     * exact conversion; it does not give the same result as
 162.791 +     * converting the {@code double} to a {@code String} using the
 162.792 +     * {@link Double#toString(double)} method and then using the
 162.793 +     * {@link #BigDecimal(String)} constructor.  To get that result,
 162.794 +     * use the {@code static} {@link #valueOf(double)} method.
 162.795 +     * </ol>
 162.796 +     *
 162.797 +     * @param val {@code double} value to be converted to
 162.798 +     *        {@code BigDecimal}.
 162.799 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
 162.800 +     */
 162.801 +    public BigDecimal(double val) {
 162.802 +        if (Double.isInfinite(val) || Double.isNaN(val))
 162.803 +            throw new NumberFormatException("Infinite or NaN");
 162.804 +
 162.805 +        // Translate the double into sign, exponent and significand, according
 162.806 +        // to the formulae in JLS, Section 20.10.22.
 162.807 +        long valBits = Double.doubleToLongBits(val);
 162.808 +        int sign = ((valBits >> 63)==0 ? 1 : -1);
 162.809 +        int exponent = (int) ((valBits >> 52) & 0x7ffL);
 162.810 +        long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
 162.811 +                            : (valBits & ((1L<<52) - 1)) | (1L<<52));
 162.812 +        exponent -= 1075;
 162.813 +        // At this point, val == sign * significand * 2**exponent.
 162.814 +
 162.815 +        /*
 162.816 +         * Special case zero to supress nonterminating normalization
 162.817 +         * and bogus scale calculation.
 162.818 +         */
 162.819 +        if (significand == 0) {
 162.820 +            intVal = BigInteger.ZERO;
 162.821 +            intCompact = 0;
 162.822 +            precision = 1;
 162.823 +            return;
 162.824 +        }
 162.825 +
 162.826 +        // Normalize
 162.827 +        while((significand & 1) == 0) {    //  i.e., significand is even
 162.828 +            significand >>= 1;
 162.829 +            exponent++;
 162.830 +        }
 162.831 +
 162.832 +        // Calculate intVal and scale
 162.833 +        long s = sign * significand;
 162.834 +        BigInteger b;
 162.835 +        if (exponent < 0) {
 162.836 +            b = BigInteger.valueOf(5).pow(-exponent).multiply(s);
 162.837 +            scale = -exponent;
 162.838 +        } else if (exponent > 0) {
 162.839 +            b = BigInteger.valueOf(2).pow(exponent).multiply(s);
 162.840 +        } else {
 162.841 +            b = BigInteger.valueOf(s);
 162.842 +        }
 162.843 +        intCompact = compactValFor(b);
 162.844 +        intVal = (intCompact != INFLATED) ? null : b;
 162.845 +    }
 162.846 +
 162.847 +    /**
 162.848 +     * Translates a {@code double} into a {@code BigDecimal}, with
 162.849 +     * rounding according to the context settings.  The scale of the
 162.850 +     * {@code BigDecimal} is the smallest value such that
 162.851 +     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
 162.852 +     *
 162.853 +     * <p>The results of this constructor can be somewhat unpredictable
 162.854 +     * and its use is generally not recommended; see the notes under
 162.855 +     * the {@link #BigDecimal(double)} constructor.
 162.856 +     *
 162.857 +     * @param  val {@code double} value to be converted to
 162.858 +     *         {@code BigDecimal}.
 162.859 +     * @param  mc the context to use.
 162.860 +     * @throws ArithmeticException if the result is inexact but the
 162.861 +     *         RoundingMode is UNNECESSARY.
 162.862 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
 162.863 +     * @since  1.5
 162.864 +     */
 162.865 +    public BigDecimal(double val, MathContext mc) {
 162.866 +        this(val);
 162.867 +        if (mc.precision > 0)
 162.868 +            roundThis(mc);
 162.869 +    }
 162.870 +
 162.871 +    /**
 162.872 +     * Translates a {@code BigInteger} into a {@code BigDecimal}.
 162.873 +     * The scale of the {@code BigDecimal} is zero.
 162.874 +     *
 162.875 +     * @param val {@code BigInteger} value to be converted to
 162.876 +     *            {@code BigDecimal}.
 162.877 +     */
 162.878 +    public BigDecimal(BigInteger val) {
 162.879 +        intCompact = compactValFor(val);
 162.880 +        intVal = (intCompact != INFLATED) ? null : val;
 162.881 +    }
 162.882 +
 162.883 +    /**
 162.884 +     * Translates a {@code BigInteger} into a {@code BigDecimal}
 162.885 +     * rounding according to the context settings.  The scale of the
 162.886 +     * {@code BigDecimal} is zero.
 162.887 +     *
 162.888 +     * @param val {@code BigInteger} value to be converted to
 162.889 +     *            {@code BigDecimal}.
 162.890 +     * @param  mc the context to use.
 162.891 +     * @throws ArithmeticException if the result is inexact but the
 162.892 +     *         rounding mode is {@code UNNECESSARY}.
 162.893 +     * @since  1.5
 162.894 +     */
 162.895 +    public BigDecimal(BigInteger val, MathContext mc) {
 162.896 +        this(val);
 162.897 +        if (mc.precision > 0)
 162.898 +            roundThis(mc);
 162.899 +    }
 162.900 +
 162.901 +    /**
 162.902 +     * Translates a {@code BigInteger} unscaled value and an
 162.903 +     * {@code int} scale into a {@code BigDecimal}.  The value of
 162.904 +     * the {@code BigDecimal} is
 162.905 +     * <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
 162.906 +     *
 162.907 +     * @param unscaledVal unscaled value of the {@code BigDecimal}.
 162.908 +     * @param scale scale of the {@code BigDecimal}.
 162.909 +     */
 162.910 +    public BigDecimal(BigInteger unscaledVal, int scale) {
 162.911 +        // Negative scales are now allowed
 162.912 +        this(unscaledVal);
 162.913 +        this.scale = scale;
 162.914 +    }
 162.915 +
 162.916 +    /**
 162.917 +     * Translates a {@code BigInteger} unscaled value and an
 162.918 +     * {@code int} scale into a {@code BigDecimal}, with rounding
 162.919 +     * according to the context settings.  The value of the
 162.920 +     * {@code BigDecimal} is <tt>(unscaledVal &times;
 162.921 +     * 10<sup>-scale</sup>)</tt>, rounded according to the
 162.922 +     * {@code precision} and rounding mode settings.
 162.923 +     *
 162.924 +     * @param  unscaledVal unscaled value of the {@code BigDecimal}.
 162.925 +     * @param  scale scale of the {@code BigDecimal}.
 162.926 +     * @param  mc the context to use.
 162.927 +     * @throws ArithmeticException if the result is inexact but the
 162.928 +     *         rounding mode is {@code UNNECESSARY}.
 162.929 +     * @since  1.5
 162.930 +     */
 162.931 +    public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
 162.932 +        this(unscaledVal);
 162.933 +        this.scale = scale;
 162.934 +        if (mc.precision > 0)
 162.935 +            roundThis(mc);
 162.936 +    }
 162.937 +
 162.938 +    /**
 162.939 +     * Translates an {@code int} into a {@code BigDecimal}.  The
 162.940 +     * scale of the {@code BigDecimal} is zero.
 162.941 +     *
 162.942 +     * @param val {@code int} value to be converted to
 162.943 +     *            {@code BigDecimal}.
 162.944 +     * @since  1.5
 162.945 +     */
 162.946 +    public BigDecimal(int val) {
 162.947 +        intCompact = val;
 162.948 +    }
 162.949 +
 162.950 +    /**
 162.951 +     * Translates an {@code int} into a {@code BigDecimal}, with
 162.952 +     * rounding according to the context settings.  The scale of the
 162.953 +     * {@code BigDecimal}, before any rounding, is zero.
 162.954 +     *
 162.955 +     * @param  val {@code int} value to be converted to {@code BigDecimal}.
 162.956 +     * @param  mc the context to use.
 162.957 +     * @throws ArithmeticException if the result is inexact but the
 162.958 +     *         rounding mode is {@code UNNECESSARY}.
 162.959 +     * @since  1.5
 162.960 +     */
 162.961 +    public BigDecimal(int val, MathContext mc) {
 162.962 +        intCompact = val;
 162.963 +        if (mc.precision > 0)
 162.964 +            roundThis(mc);
 162.965 +    }
 162.966 +
 162.967 +    /**
 162.968 +     * Translates a {@code long} into a {@code BigDecimal}.  The
 162.969 +     * scale of the {@code BigDecimal} is zero.
 162.970 +     *
 162.971 +     * @param val {@code long} value to be converted to {@code BigDecimal}.
 162.972 +     * @since  1.5
 162.973 +     */
 162.974 +    public BigDecimal(long val) {
 162.975 +        this.intCompact = val;
 162.976 +        this.intVal = (val == INFLATED) ? BigInteger.valueOf(val) : null;
 162.977 +    }
 162.978 +
 162.979 +    /**
 162.980 +     * Translates a {@code long} into a {@code BigDecimal}, with
 162.981 +     * rounding according to the context settings.  The scale of the
 162.982 +     * {@code BigDecimal}, before any rounding, is zero.
 162.983 +     *
 162.984 +     * @param  val {@code long} value to be converted to {@code BigDecimal}.
 162.985 +     * @param  mc the context to use.
 162.986 +     * @throws ArithmeticException if the result is inexact but the
 162.987 +     *         rounding mode is {@code UNNECESSARY}.
 162.988 +     * @since  1.5
 162.989 +     */
 162.990 +    public BigDecimal(long val, MathContext mc) {
 162.991 +        this(val);
 162.992 +        if (mc.precision > 0)
 162.993 +            roundThis(mc);
 162.994 +    }
 162.995 +
 162.996 +    // Static Factory Methods
 162.997 +
 162.998 +    /**
 162.999 +     * Translates a {@code long} unscaled value and an
162.1000 +     * {@code int} scale into a {@code BigDecimal}.  This
162.1001 +     * {@literal "static factory method"} is provided in preference to
162.1002 +     * a ({@code long}, {@code int}) constructor because it
162.1003 +     * allows for reuse of frequently used {@code BigDecimal} values..
162.1004 +     *
162.1005 +     * @param unscaledVal unscaled value of the {@code BigDecimal}.
162.1006 +     * @param scale scale of the {@code BigDecimal}.
162.1007 +     * @return a {@code BigDecimal} whose value is
162.1008 +     *         <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
162.1009 +     */
162.1010 +    public static BigDecimal valueOf(long unscaledVal, int scale) {
162.1011 +        if (scale == 0)
162.1012 +            return valueOf(unscaledVal);
162.1013 +        else if (unscaledVal == 0) {
162.1014 +            if (scale > 0 && scale < ZERO_SCALED_BY.length)
162.1015 +                return ZERO_SCALED_BY[scale];
162.1016 +            else
162.1017 +                return new BigDecimal(BigInteger.ZERO, 0, scale, 1);
162.1018 +        }
162.1019 +        return new BigDecimal(unscaledVal == INFLATED ?
162.1020 +                              BigInteger.valueOf(unscaledVal) : null,
162.1021 +                              unscaledVal, scale, 0);
162.1022 +    }
162.1023 +
162.1024 +    /**
162.1025 +     * Translates a {@code long} value into a {@code BigDecimal}
162.1026 +     * with a scale of zero.  This {@literal "static factory method"}
162.1027 +     * is provided in preference to a ({@code long}) constructor
162.1028 +     * because it allows for reuse of frequently used
162.1029 +     * {@code BigDecimal} values.
162.1030 +     *
162.1031 +     * @param val value of the {@code BigDecimal}.
162.1032 +     * @return a {@code BigDecimal} whose value is {@code val}.
162.1033 +     */
162.1034 +    public static BigDecimal valueOf(long val) {
162.1035 +        if (val >= 0 && val < zeroThroughTen.length)
162.1036 +            return zeroThroughTen[(int)val];
162.1037 +        else if (val != INFLATED)
162.1038 +            return new BigDecimal(null, val, 0, 0);
162.1039 +        return new BigDecimal(BigInteger.valueOf(val), val, 0, 0);
162.1040 +    }
162.1041 +
162.1042 +    /**
162.1043 +     * Translates a {@code double} into a {@code BigDecimal}, using
162.1044 +     * the {@code double}'s canonical string representation provided
162.1045 +     * by the {@link Double#toString(double)} method.
162.1046 +     *
162.1047 +     * <p><b>Note:</b> This is generally the preferred way to convert
162.1048 +     * a {@code double} (or {@code float}) into a
162.1049 +     * {@code BigDecimal}, as the value returned is equal to that
162.1050 +     * resulting from constructing a {@code BigDecimal} from the
162.1051 +     * result of using {@link Double#toString(double)}.
162.1052 +     *
162.1053 +     * @param  val {@code double} to convert to a {@code BigDecimal}.
162.1054 +     * @return a {@code BigDecimal} whose value is equal to or approximately
162.1055 +     *         equal to the value of {@code val}.
162.1056 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
162.1057 +     * @since  1.5
162.1058 +     */
162.1059 +    public static BigDecimal valueOf(double val) {
162.1060 +        // Reminder: a zero double returns '0.0', so we cannot fastpath
162.1061 +        // to use the constant ZERO.  This might be important enough to
162.1062 +        // justify a factory approach, a cache, or a few private
162.1063 +        // constants, later.
162.1064 +        return new BigDecimal(Double.toString(val));
162.1065 +    }
162.1066 +
162.1067 +    // Arithmetic Operations
162.1068 +    /**
162.1069 +     * Returns a {@code BigDecimal} whose value is {@code (this +
162.1070 +     * augend)}, and whose scale is {@code max(this.scale(),
162.1071 +     * augend.scale())}.
162.1072 +     *
162.1073 +     * @param  augend value to be added to this {@code BigDecimal}.
162.1074 +     * @return {@code this + augend}
162.1075 +     */
162.1076 +    public BigDecimal add(BigDecimal augend) {
162.1077 +        long xs = this.intCompact;
162.1078 +        long ys = augend.intCompact;
162.1079 +        BigInteger fst = (xs != INFLATED) ? null : this.intVal;
162.1080 +        BigInteger snd = (ys != INFLATED) ? null : augend.intVal;
162.1081 +        int rscale = this.scale;
162.1082 +
162.1083 +        long sdiff = (long)rscale - augend.scale;
162.1084 +        if (sdiff != 0) {
162.1085 +            if (sdiff < 0) {
162.1086 +                int raise = checkScale(-sdiff);
162.1087 +                rscale = augend.scale;
162.1088 +                if (xs == INFLATED ||
162.1089 +                    (xs = longMultiplyPowerTen(xs, raise)) == INFLATED)
162.1090 +                    fst = bigMultiplyPowerTen(raise);
162.1091 +            } else {
162.1092 +                int raise = augend.checkScale(sdiff);
162.1093 +                if (ys == INFLATED ||
162.1094 +                    (ys = longMultiplyPowerTen(ys, raise)) == INFLATED)
162.1095 +                    snd = augend.bigMultiplyPowerTen(raise);
162.1096 +            }
162.1097 +        }
162.1098 +        if (xs != INFLATED && ys != INFLATED) {
162.1099 +            long sum = xs + ys;
162.1100 +            // See "Hacker's Delight" section 2-12 for explanation of
162.1101 +            // the overflow test.
162.1102 +            if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) // not overflowed
162.1103 +                return BigDecimal.valueOf(sum, rscale);
162.1104 +        }
162.1105 +        if (fst == null)
162.1106 +            fst = BigInteger.valueOf(xs);
162.1107 +        if (snd == null)
162.1108 +            snd = BigInteger.valueOf(ys);
162.1109 +        BigInteger sum = fst.add(snd);
162.1110 +        return (fst.signum == snd.signum) ?
162.1111 +            new BigDecimal(sum, INFLATED, rscale, 0) :
162.1112 +            new BigDecimal(sum, rscale);
162.1113 +    }
162.1114 +
162.1115 +    /**
162.1116 +     * Returns a {@code BigDecimal} whose value is {@code (this + augend)},
162.1117 +     * with rounding according to the context settings.
162.1118 +     *
162.1119 +     * If either number is zero and the precision setting is nonzero then
162.1120 +     * the other number, rounded if necessary, is used as the result.
162.1121 +     *
162.1122 +     * @param  augend value to be added to this {@code BigDecimal}.
162.1123 +     * @param  mc the context to use.
162.1124 +     * @return {@code this + augend}, rounded as necessary.
162.1125 +     * @throws ArithmeticException if the result is inexact but the
162.1126 +     *         rounding mode is {@code UNNECESSARY}.
162.1127 +     * @since  1.5
162.1128 +     */
162.1129 +    public BigDecimal add(BigDecimal augend, MathContext mc) {
162.1130 +        if (mc.precision == 0)
162.1131 +            return add(augend);
162.1132 +        BigDecimal lhs = this;
162.1133 +
162.1134 +        // Could optimize if values are compact
162.1135 +        this.inflate();
162.1136 +        augend.inflate();
162.1137 +
162.1138 +        // If either number is zero then the other number, rounded and
162.1139 +        // scaled if necessary, is used as the result.
162.1140 +        {
162.1141 +            boolean lhsIsZero = lhs.signum() == 0;
162.1142 +            boolean augendIsZero = augend.signum() == 0;
162.1143 +
162.1144 +            if (lhsIsZero || augendIsZero) {
162.1145 +                int preferredScale = Math.max(lhs.scale(), augend.scale());
162.1146 +                BigDecimal result;
162.1147 +
162.1148 +                // Could use a factory for zero instead of a new object
162.1149 +                if (lhsIsZero && augendIsZero)
162.1150 +                    return new BigDecimal(BigInteger.ZERO, 0, preferredScale, 0);
162.1151 +
162.1152 +                result = lhsIsZero ? doRound(augend, mc) : doRound(lhs, mc);
162.1153 +
162.1154 +                if (result.scale() == preferredScale)
162.1155 +                    return result;
162.1156 +                else if (result.scale() > preferredScale) {
162.1157 +                    BigDecimal scaledResult =
162.1158 +                        new BigDecimal(result.intVal, result.intCompact,
162.1159 +                                       result.scale, 0);
162.1160 +                    scaledResult.stripZerosToMatchScale(preferredScale);
162.1161 +                    return scaledResult;
162.1162 +                } else { // result.scale < preferredScale
162.1163 +                    int precisionDiff = mc.precision - result.precision();
162.1164 +                    int scaleDiff     = preferredScale - result.scale();
162.1165 +
162.1166 +                    if (precisionDiff >= scaleDiff)
162.1167 +                        return result.setScale(preferredScale); // can achieve target scale
162.1168 +                    else
162.1169 +                        return result.setScale(result.scale() + precisionDiff);
162.1170 +                }
162.1171 +            }
162.1172 +        }
162.1173 +
162.1174 +        long padding = (long)lhs.scale - augend.scale;
162.1175 +        if (padding != 0) {        // scales differ; alignment needed
162.1176 +            BigDecimal arg[] = preAlign(lhs, augend, padding, mc);
162.1177 +            matchScale(arg);
162.1178 +            lhs    = arg[0];
162.1179 +            augend = arg[1];
162.1180 +        }
162.1181 +
162.1182 +        BigDecimal d = new BigDecimal(lhs.inflate().add(augend.inflate()),
162.1183 +                                      lhs.scale);
162.1184 +        return doRound(d, mc);
162.1185 +    }
162.1186 +
162.1187 +    /**
162.1188 +     * Returns an array of length two, the sum of whose entries is
162.1189 +     * equal to the rounded sum of the {@code BigDecimal} arguments.
162.1190 +     *
162.1191 +     * <p>If the digit positions of the arguments have a sufficient
162.1192 +     * gap between them, the value smaller in magnitude can be
162.1193 +     * condensed into a {@literal "sticky bit"} and the end result will
162.1194 +     * round the same way <em>if</em> the precision of the final
162.1195 +     * result does not include the high order digit of the small
162.1196 +     * magnitude operand.
162.1197 +     *
162.1198 +     * <p>Note that while strictly speaking this is an optimization,
162.1199 +     * it makes a much wider range of additions practical.
162.1200 +     *
162.1201 +     * <p>This corresponds to a pre-shift operation in a fixed
162.1202 +     * precision floating-point adder; this method is complicated by
162.1203 +     * variable precision of the result as determined by the
162.1204 +     * MathContext.  A more nuanced operation could implement a
162.1205 +     * {@literal "right shift"} on the smaller magnitude operand so
162.1206 +     * that the number of digits of the smaller operand could be
162.1207 +     * reduced even though the significands partially overlapped.
162.1208 +     */
162.1209 +    private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend,
162.1210 +                                  long padding, MathContext mc) {
162.1211 +        assert padding != 0;
162.1212 +        BigDecimal big;
162.1213 +        BigDecimal small;
162.1214 +
162.1215 +        if (padding < 0) {     // lhs is big;   augend is small
162.1216 +            big   = lhs;
162.1217 +            small = augend;
162.1218 +        } else {               // lhs is small; augend is big
162.1219 +            big   = augend;
162.1220 +            small = lhs;
162.1221 +        }
162.1222 +
162.1223 +        /*
162.1224 +         * This is the estimated scale of an ulp of the result; it
162.1225 +         * assumes that the result doesn't have a carry-out on a true
162.1226 +         * add (e.g. 999 + 1 => 1000) or any subtractive cancellation
162.1227 +         * on borrowing (e.g. 100 - 1.2 => 98.8)
162.1228 +         */
162.1229 +        long estResultUlpScale = (long)big.scale - big.precision() + mc.precision;
162.1230 +
162.1231 +        /*
162.1232 +         * The low-order digit position of big is big.scale().  This
162.1233 +         * is true regardless of whether big has a positive or
162.1234 +         * negative scale.  The high-order digit position of small is
162.1235 +         * small.scale - (small.precision() - 1).  To do the full
162.1236 +         * condensation, the digit positions of big and small must be
162.1237 +         * disjoint *and* the digit positions of small should not be
162.1238 +         * directly visible in the result.
162.1239 +         */
162.1240 +        long smallHighDigitPos = (long)small.scale - small.precision() + 1;
162.1241 +        if (smallHighDigitPos > big.scale + 2 &&         // big and small disjoint
162.1242 +            smallHighDigitPos > estResultUlpScale + 2) { // small digits not visible
162.1243 +            small = BigDecimal.valueOf(small.signum(),
162.1244 +                                       this.checkScale(Math.max(big.scale, estResultUlpScale) + 3));
162.1245 +        }
162.1246 +
162.1247 +        // Since addition is symmetric, preserving input order in
162.1248 +        // returned operands doesn't matter
162.1249 +        BigDecimal[] result = {big, small};
162.1250 +        return result;
162.1251 +    }
162.1252 +
162.1253 +    /**
162.1254 +     * Returns a {@code BigDecimal} whose value is {@code (this -
162.1255 +     * subtrahend)}, and whose scale is {@code max(this.scale(),
162.1256 +     * subtrahend.scale())}.
162.1257 +     *
162.1258 +     * @param  subtrahend value to be subtracted from this {@code BigDecimal}.
162.1259 +     * @return {@code this - subtrahend}
162.1260 +     */
162.1261 +    public BigDecimal subtract(BigDecimal subtrahend) {
162.1262 +        return add(subtrahend.negate());
162.1263 +    }
162.1264 +
162.1265 +    /**
162.1266 +     * Returns a {@code BigDecimal} whose value is {@code (this - subtrahend)},
162.1267 +     * with rounding according to the context settings.
162.1268 +     *
162.1269 +     * If {@code subtrahend} is zero then this, rounded if necessary, is used as the
162.1270 +     * result.  If this is zero then the result is {@code subtrahend.negate(mc)}.
162.1271 +     *
162.1272 +     * @param  subtrahend value to be subtracted from this {@code BigDecimal}.
162.1273 +     * @param  mc the context to use.
162.1274 +     * @return {@code this - subtrahend}, rounded as necessary.
162.1275 +     * @throws ArithmeticException if the result is inexact but the
162.1276 +     *         rounding mode is {@code UNNECESSARY}.
162.1277 +     * @since  1.5
162.1278 +     */
162.1279 +    public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
162.1280 +        BigDecimal nsubtrahend = subtrahend.negate();
162.1281 +        if (mc.precision == 0)
162.1282 +            return add(nsubtrahend);
162.1283 +        // share the special rounding code in add()
162.1284 +        return add(nsubtrahend, mc);
162.1285 +    }
162.1286 +
162.1287 +    /**
162.1288 +     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
162.1289 +     * multiplicand)</tt>, and whose scale is {@code (this.scale() +
162.1290 +     * multiplicand.scale())}.
162.1291 +     *
162.1292 +     * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
162.1293 +     * @return {@code this * multiplicand}
162.1294 +     */
162.1295 +    public BigDecimal multiply(BigDecimal multiplicand) {
162.1296 +        long x = this.intCompact;
162.1297 +        long y = multiplicand.intCompact;
162.1298 +        int productScale = checkScale((long)scale + multiplicand.scale);
162.1299 +
162.1300 +        // Might be able to do a more clever check incorporating the
162.1301 +        // inflated check into the overflow computation.
162.1302 +        if (x != INFLATED && y != INFLATED) {
162.1303 +            /*
162.1304 +             * If the product is not an overflowed value, continue
162.1305 +             * to use the compact representation.  if either of x or y
162.1306 +             * is INFLATED, the product should also be regarded as
162.1307 +             * an overflow. Before using the overflow test suggested in
162.1308 +             * "Hacker's Delight" section 2-12, we perform quick checks
162.1309 +             * using the precision information to see whether the overflow
162.1310 +             * would occur since division is expensive on most CPUs.
162.1311 +             */
162.1312 +            long product = x * y;
162.1313 +            long prec = this.precision() + multiplicand.precision();
162.1314 +            if (prec < 19 || (prec < 21 && (y == 0 || product / y == x)))
162.1315 +                return BigDecimal.valueOf(product, productScale);
162.1316 +            return new BigDecimal(BigInteger.valueOf(x).multiply(y), INFLATED,
162.1317 +                                  productScale, 0);
162.1318 +        }
162.1319 +        BigInteger rb;
162.1320 +        if (x == INFLATED && y == INFLATED)
162.1321 +            rb = this.intVal.multiply(multiplicand.intVal);
162.1322 +        else if (x != INFLATED)
162.1323 +            rb = multiplicand.intVal.multiply(x);
162.1324 +        else
162.1325 +            rb = this.intVal.multiply(y);
162.1326 +        return new BigDecimal(rb, INFLATED, productScale, 0);
162.1327 +    }
162.1328 +
162.1329 +    /**
162.1330 +     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
162.1331 +     * multiplicand)</tt>, with rounding according to the context settings.
162.1332 +     *
162.1333 +     * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
162.1334 +     * @param  mc the context to use.
162.1335 +     * @return {@code this * multiplicand}, rounded as necessary.
162.1336 +     * @throws ArithmeticException if the result is inexact but the
162.1337 +     *         rounding mode is {@code UNNECESSARY}.
162.1338 +     * @since  1.5
162.1339 +     */
162.1340 +    public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
162.1341 +        if (mc.precision == 0)
162.1342 +            return multiply(multiplicand);
162.1343 +        return doRound(this.multiply(multiplicand), mc);
162.1344 +    }
162.1345 +
162.1346 +    /**
162.1347 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1348 +     * divisor)}, and whose scale is as specified.  If rounding must
162.1349 +     * be performed to generate a result with the specified scale, the
162.1350 +     * specified rounding mode is applied.
162.1351 +     *
162.1352 +     * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
162.1353 +     * should be used in preference to this legacy method.
162.1354 +     *
162.1355 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1356 +     * @param  scale scale of the {@code BigDecimal} quotient to be returned.
162.1357 +     * @param  roundingMode rounding mode to apply.
162.1358 +     * @return {@code this / divisor}
162.1359 +     * @throws ArithmeticException if {@code divisor} is zero,
162.1360 +     *         {@code roundingMode==ROUND_UNNECESSARY} and
162.1361 +     *         the specified scale is insufficient to represent the result
162.1362 +     *         of the division exactly.
162.1363 +     * @throws IllegalArgumentException if {@code roundingMode} does not
162.1364 +     *         represent a valid rounding mode.
162.1365 +     * @see    #ROUND_UP
162.1366 +     * @see    #ROUND_DOWN
162.1367 +     * @see    #ROUND_CEILING
162.1368 +     * @see    #ROUND_FLOOR
162.1369 +     * @see    #ROUND_HALF_UP
162.1370 +     * @see    #ROUND_HALF_DOWN
162.1371 +     * @see    #ROUND_HALF_EVEN
162.1372 +     * @see    #ROUND_UNNECESSARY
162.1373 +     */
162.1374 +    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
162.1375 +        /*
162.1376 +         * IMPLEMENTATION NOTE: This method *must* return a new object
162.1377 +         * since divideAndRound uses divide to generate a value whose
162.1378 +         * scale is then modified.
162.1379 +         */
162.1380 +        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
162.1381 +            throw new IllegalArgumentException("Invalid rounding mode");
162.1382 +        /*
162.1383 +         * Rescale dividend or divisor (whichever can be "upscaled" to
162.1384 +         * produce correctly scaled quotient).
162.1385 +         * Take care to detect out-of-range scales
162.1386 +         */
162.1387 +        BigDecimal dividend = this;
162.1388 +        if (checkScale((long)scale + divisor.scale) > this.scale)
162.1389 +            dividend = this.setScale(scale + divisor.scale, ROUND_UNNECESSARY);
162.1390 +        else
162.1391 +            divisor = divisor.setScale(checkScale((long)this.scale - scale),
162.1392 +                                       ROUND_UNNECESSARY);
162.1393 +        return divideAndRound(dividend.intCompact, dividend.intVal,
162.1394 +                              divisor.intCompact, divisor.intVal,
162.1395 +                              scale, roundingMode, scale);
162.1396 +    }
162.1397 +
162.1398 +    /**
162.1399 +     * Internally used for division operation. The dividend and divisor are
162.1400 +     * passed both in {@code long} format and {@code BigInteger} format. The
162.1401 +     * returned {@code BigDecimal} object is the quotient whose scale is set to
162.1402 +     * the passed in scale. If the remainder is not zero, it will be rounded
162.1403 +     * based on the passed in roundingMode. Also, if the remainder is zero and
162.1404 +     * the last parameter, i.e. preferredScale is NOT equal to scale, the
162.1405 +     * trailing zeros of the result is stripped to match the preferredScale.
162.1406 +     */
162.1407 +    private static BigDecimal divideAndRound(long ldividend, BigInteger bdividend,
162.1408 +                                             long ldivisor,  BigInteger bdivisor,
162.1409 +                                             int scale, int roundingMode,
162.1410 +                                             int preferredScale) {
162.1411 +        boolean isRemainderZero;       // record remainder is zero or not
162.1412 +        int qsign;                     // quotient sign
162.1413 +        long q = 0, r = 0;             // store quotient & remainder in long
162.1414 +        MutableBigInteger mq = null;   // store quotient
162.1415 +        MutableBigInteger mr = null;   // store remainder
162.1416 +        MutableBigInteger mdivisor = null;
162.1417 +        boolean isLongDivision = (ldividend != INFLATED && ldivisor != INFLATED);
162.1418 +        if (isLongDivision) {
162.1419 +            q = ldividend / ldivisor;
162.1420 +            if (roundingMode == ROUND_DOWN && scale == preferredScale)
162.1421 +                return new BigDecimal(null, q, scale, 0);
162.1422 +            r = ldividend % ldivisor;
162.1423 +            isRemainderZero = (r == 0);
162.1424 +            qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
162.1425 +        } else {
162.1426 +            if (bdividend == null)
162.1427 +                bdividend = BigInteger.valueOf(ldividend);
162.1428 +            // Descend into mutables for faster remainder checks
162.1429 +            MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
162.1430 +            mq = new MutableBigInteger();
162.1431 +            if (ldivisor != INFLATED) {
162.1432 +                r = mdividend.divide(ldivisor, mq);
162.1433 +                isRemainderZero = (r == 0);
162.1434 +                qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
162.1435 +            } else {
162.1436 +                mdivisor = new MutableBigInteger(bdivisor.mag);
162.1437 +                mr = mdividend.divide(mdivisor, mq);
162.1438 +                isRemainderZero = mr.isZero();
162.1439 +                qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
162.1440 +            }
162.1441 +        }
162.1442 +        boolean increment = false;
162.1443 +        if (!isRemainderZero) {
162.1444 +            int cmpFracHalf;
162.1445 +            /* Round as appropriate */
162.1446 +            if (roundingMode == ROUND_UNNECESSARY) {  // Rounding prohibited
162.1447 +                throw new ArithmeticException("Rounding necessary");
162.1448 +            } else if (roundingMode == ROUND_UP) {      // Away from zero
162.1449 +                increment = true;
162.1450 +            } else if (roundingMode == ROUND_DOWN) {    // Towards zero
162.1451 +                increment = false;
162.1452 +            } else if (roundingMode == ROUND_CEILING) { // Towards +infinity
162.1453 +                increment = (qsign > 0);
162.1454 +            } else if (roundingMode == ROUND_FLOOR) {   // Towards -infinity
162.1455 +                increment = (qsign < 0);
162.1456 +            } else {
162.1457 +                if (isLongDivision || ldivisor != INFLATED) {
162.1458 +                    if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
162.1459 +                        cmpFracHalf = 1;    // 2 * r can't fit into long
162.1460 +                    } else {
162.1461 +                        cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
162.1462 +                    }
162.1463 +                } else {
162.1464 +                    cmpFracHalf = mr.compareHalf(mdivisor);
162.1465 +                }
162.1466 +                if (cmpFracHalf < 0)
162.1467 +                    increment = false;     // We're closer to higher digit
162.1468 +                else if (cmpFracHalf > 0)  // We're closer to lower digit
162.1469 +                    increment = true;
162.1470 +                else if (roundingMode == ROUND_HALF_UP)
162.1471 +                    increment = true;
162.1472 +                else if (roundingMode == ROUND_HALF_DOWN)
162.1473 +                    increment = false;
162.1474 +                else  // roundingMode == ROUND_HALF_EVEN, true iff quotient is odd
162.1475 +                    increment = isLongDivision ? (q & 1L) != 0L : mq.isOdd();
162.1476 +            }
162.1477 +        }
162.1478 +        BigDecimal res;
162.1479 +        if (isLongDivision)
162.1480 +            res = new BigDecimal(null, (increment ? q + qsign : q), scale, 0);
162.1481 +        else {
162.1482 +            if (increment)
162.1483 +                mq.add(MutableBigInteger.ONE);
162.1484 +            res = mq.toBigDecimal(qsign, scale);
162.1485 +        }
162.1486 +        if (isRemainderZero && preferredScale != scale)
162.1487 +            res.stripZerosToMatchScale(preferredScale);
162.1488 +        return res;
162.1489 +    }
162.1490 +
162.1491 +    /**
162.1492 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1493 +     * divisor)}, and whose scale is as specified.  If rounding must
162.1494 +     * be performed to generate a result with the specified scale, the
162.1495 +     * specified rounding mode is applied.
162.1496 +     *
162.1497 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1498 +     * @param  scale scale of the {@code BigDecimal} quotient to be returned.
162.1499 +     * @param  roundingMode rounding mode to apply.
162.1500 +     * @return {@code this / divisor}
162.1501 +     * @throws ArithmeticException if {@code divisor} is zero,
162.1502 +     *         {@code roundingMode==RoundingMode.UNNECESSARY} and
162.1503 +     *         the specified scale is insufficient to represent the result
162.1504 +     *         of the division exactly.
162.1505 +     * @since 1.5
162.1506 +     */
162.1507 +    public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
162.1508 +        return divide(divisor, scale, roundingMode.oldMode);
162.1509 +    }
162.1510 +
162.1511 +    /**
162.1512 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1513 +     * divisor)}, and whose scale is {@code this.scale()}.  If
162.1514 +     * rounding must be performed to generate a result with the given
162.1515 +     * scale, the specified rounding mode is applied.
162.1516 +     *
162.1517 +     * <p>The new {@link #divide(BigDecimal, RoundingMode)} method
162.1518 +     * should be used in preference to this legacy method.
162.1519 +     *
162.1520 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1521 +     * @param  roundingMode rounding mode to apply.
162.1522 +     * @return {@code this / divisor}
162.1523 +     * @throws ArithmeticException if {@code divisor==0}, or
162.1524 +     *         {@code roundingMode==ROUND_UNNECESSARY} and
162.1525 +     *         {@code this.scale()} is insufficient to represent the result
162.1526 +     *         of the division exactly.
162.1527 +     * @throws IllegalArgumentException if {@code roundingMode} does not
162.1528 +     *         represent a valid rounding mode.
162.1529 +     * @see    #ROUND_UP
162.1530 +     * @see    #ROUND_DOWN
162.1531 +     * @see    #ROUND_CEILING
162.1532 +     * @see    #ROUND_FLOOR
162.1533 +     * @see    #ROUND_HALF_UP
162.1534 +     * @see    #ROUND_HALF_DOWN
162.1535 +     * @see    #ROUND_HALF_EVEN
162.1536 +     * @see    #ROUND_UNNECESSARY
162.1537 +     */
162.1538 +    public BigDecimal divide(BigDecimal divisor, int roundingMode) {
162.1539 +            return this.divide(divisor, scale, roundingMode);
162.1540 +    }
162.1541 +
162.1542 +    /**
162.1543 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1544 +     * divisor)}, and whose scale is {@code this.scale()}.  If
162.1545 +     * rounding must be performed to generate a result with the given
162.1546 +     * scale, the specified rounding mode is applied.
162.1547 +     *
162.1548 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1549 +     * @param  roundingMode rounding mode to apply.
162.1550 +     * @return {@code this / divisor}
162.1551 +     * @throws ArithmeticException if {@code divisor==0}, or
162.1552 +     *         {@code roundingMode==RoundingMode.UNNECESSARY} and
162.1553 +     *         {@code this.scale()} is insufficient to represent the result
162.1554 +     *         of the division exactly.
162.1555 +     * @since 1.5
162.1556 +     */
162.1557 +    public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
162.1558 +        return this.divide(divisor, scale, roundingMode.oldMode);
162.1559 +    }
162.1560 +
162.1561 +    /**
162.1562 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1563 +     * divisor)}, and whose preferred scale is {@code (this.scale() -
162.1564 +     * divisor.scale())}; if the exact quotient cannot be
162.1565 +     * represented (because it has a non-terminating decimal
162.1566 +     * expansion) an {@code ArithmeticException} is thrown.
162.1567 +     *
162.1568 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1569 +     * @throws ArithmeticException if the exact quotient does not have a
162.1570 +     *         terminating decimal expansion
162.1571 +     * @return {@code this / divisor}
162.1572 +     * @since 1.5
162.1573 +     * @author Joseph D. Darcy
162.1574 +     */
162.1575 +    public BigDecimal divide(BigDecimal divisor) {
162.1576 +        /*
162.1577 +         * Handle zero cases first.
162.1578 +         */
162.1579 +        if (divisor.signum() == 0) {   // x/0
162.1580 +            if (this.signum() == 0)    // 0/0
162.1581 +                throw new ArithmeticException("Division undefined");  // NaN
162.1582 +            throw new ArithmeticException("Division by zero");
162.1583 +        }
162.1584 +
162.1585 +        // Calculate preferred scale
162.1586 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
162.1587 +        if (this.signum() == 0)        // 0/y
162.1588 +            return (preferredScale >= 0 &&
162.1589 +                    preferredScale < ZERO_SCALED_BY.length) ?
162.1590 +                ZERO_SCALED_BY[preferredScale] :
162.1591 +                BigDecimal.valueOf(0, preferredScale);
162.1592 +        else {
162.1593 +            this.inflate();
162.1594 +            divisor.inflate();
162.1595 +            /*
162.1596 +             * If the quotient this/divisor has a terminating decimal
162.1597 +             * expansion, the expansion can have no more than
162.1598 +             * (a.precision() + ceil(10*b.precision)/3) digits.
162.1599 +             * Therefore, create a MathContext object with this
162.1600 +             * precision and do a divide with the UNNECESSARY rounding
162.1601 +             * mode.
162.1602 +             */
162.1603 +            MathContext mc = new MathContext( (int)Math.min(this.precision() +
162.1604 +                                                            (long)Math.ceil(10.0*divisor.precision()/3.0),
162.1605 +                                                            Integer.MAX_VALUE),
162.1606 +                                              RoundingMode.UNNECESSARY);
162.1607 +            BigDecimal quotient;
162.1608 +            try {
162.1609 +                quotient = this.divide(divisor, mc);
162.1610 +            } catch (ArithmeticException e) {
162.1611 +                throw new ArithmeticException("Non-terminating decimal expansion; " +
162.1612 +                                              "no exact representable decimal result.");
162.1613 +            }
162.1614 +
162.1615 +            int quotientScale = quotient.scale();
162.1616 +
162.1617 +            // divide(BigDecimal, mc) tries to adjust the quotient to
162.1618 +            // the desired one by removing trailing zeros; since the
162.1619 +            // exact divide method does not have an explicit digit
162.1620 +            // limit, we can add zeros too.
162.1621 +
162.1622 +            if (preferredScale > quotientScale)
162.1623 +                return quotient.setScale(preferredScale, ROUND_UNNECESSARY);
162.1624 +
162.1625 +            return quotient;
162.1626 +        }
162.1627 +    }
162.1628 +
162.1629 +    /**
162.1630 +     * Returns a {@code BigDecimal} whose value is {@code (this /
162.1631 +     * divisor)}, with rounding according to the context settings.
162.1632 +     *
162.1633 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1634 +     * @param  mc the context to use.
162.1635 +     * @return {@code this / divisor}, rounded as necessary.
162.1636 +     * @throws ArithmeticException if the result is inexact but the
162.1637 +     *         rounding mode is {@code UNNECESSARY} or
162.1638 +     *         {@code mc.precision == 0} and the quotient has a
162.1639 +     *         non-terminating decimal expansion.
162.1640 +     * @since  1.5
162.1641 +     */
162.1642 +    public BigDecimal divide(BigDecimal divisor, MathContext mc) {
162.1643 +        int mcp = mc.precision;
162.1644 +        if (mcp == 0)
162.1645 +            return divide(divisor);
162.1646 +
162.1647 +        BigDecimal dividend = this;
162.1648 +        long preferredScale = (long)dividend.scale - divisor.scale;
162.1649 +        // Now calculate the answer.  We use the existing
162.1650 +        // divide-and-round method, but as this rounds to scale we have
162.1651 +        // to normalize the values here to achieve the desired result.
162.1652 +        // For x/y we first handle y=0 and x=0, and then normalize x and
162.1653 +        // y to give x' and y' with the following constraints:
162.1654 +        //   (a) 0.1 <= x' < 1
162.1655 +        //   (b)  x' <= y' < 10*x'
162.1656 +        // Dividing x'/y' with the required scale set to mc.precision then
162.1657 +        // will give a result in the range 0.1 to 1 rounded to exactly
162.1658 +        // the right number of digits (except in the case of a result of
162.1659 +        // 1.000... which can arise when x=y, or when rounding overflows
162.1660 +        // The 1.000... case will reduce properly to 1.
162.1661 +        if (divisor.signum() == 0) {      // x/0
162.1662 +            if (dividend.signum() == 0)    // 0/0
162.1663 +                throw new ArithmeticException("Division undefined");  // NaN
162.1664 +            throw new ArithmeticException("Division by zero");
162.1665 +        }
162.1666 +        if (dividend.signum() == 0)        // 0/y
162.1667 +            return new BigDecimal(BigInteger.ZERO, 0,
162.1668 +                                  saturateLong(preferredScale), 1);
162.1669 +
162.1670 +        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
162.1671 +        int xscale = dividend.precision();
162.1672 +        int yscale = divisor.precision();
162.1673 +        dividend = new BigDecimal(dividend.intVal, dividend.intCompact,
162.1674 +                                  xscale, xscale);
162.1675 +        divisor = new BigDecimal(divisor.intVal, divisor.intCompact,
162.1676 +                                 yscale, yscale);
162.1677 +        if (dividend.compareMagnitude(divisor) > 0) // satisfy constraint (b)
162.1678 +            yscale = divisor.scale -= 1;            // [that is, divisor *= 10]
162.1679 +
162.1680 +        // In order to find out whether the divide generates the exact result,
162.1681 +        // we avoid calling the above divide method. 'quotient' holds the
162.1682 +        // return BigDecimal object whose scale will be set to 'scl'.
162.1683 +        BigDecimal quotient;
162.1684 +        int scl = checkScale(preferredScale + yscale - xscale + mcp);
162.1685 +        if (checkScale((long)mcp + yscale) > xscale)
162.1686 +            dividend = dividend.setScale(mcp + yscale, ROUND_UNNECESSARY);
162.1687 +        else
162.1688 +            divisor = divisor.setScale(checkScale((long)xscale - mcp),
162.1689 +                                       ROUND_UNNECESSARY);
162.1690 +        quotient = divideAndRound(dividend.intCompact, dividend.intVal,
162.1691 +                                  divisor.intCompact, divisor.intVal,
162.1692 +                                  scl, mc.roundingMode.oldMode,
162.1693 +                                  checkScale(preferredScale));
162.1694 +        // doRound, here, only affects 1000000000 case.
162.1695 +        quotient = doRound(quotient, mc);
162.1696 +
162.1697 +        return quotient;
162.1698 +    }
162.1699 +
162.1700 +    /**
162.1701 +     * Returns a {@code BigDecimal} whose value is the integer part
162.1702 +     * of the quotient {@code (this / divisor)} rounded down.  The
162.1703 +     * preferred scale of the result is {@code (this.scale() -
162.1704 +     * divisor.scale())}.
162.1705 +     *
162.1706 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1707 +     * @return The integer part of {@code this / divisor}.
162.1708 +     * @throws ArithmeticException if {@code divisor==0}
162.1709 +     * @since  1.5
162.1710 +     */
162.1711 +    public BigDecimal divideToIntegralValue(BigDecimal divisor) {
162.1712 +        // Calculate preferred scale
162.1713 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
162.1714 +        if (this.compareMagnitude(divisor) < 0) {
162.1715 +            // much faster when this << divisor
162.1716 +            return BigDecimal.valueOf(0, preferredScale);
162.1717 +        }
162.1718 +
162.1719 +        if(this.signum() == 0 && divisor.signum() != 0)
162.1720 +            return this.setScale(preferredScale, ROUND_UNNECESSARY);
162.1721 +
162.1722 +        // Perform a divide with enough digits to round to a correct
162.1723 +        // integer value; then remove any fractional digits
162.1724 +
162.1725 +        int maxDigits = (int)Math.min(this.precision() +
162.1726 +                                      (long)Math.ceil(10.0*divisor.precision()/3.0) +
162.1727 +                                      Math.abs((long)this.scale() - divisor.scale()) + 2,
162.1728 +                                      Integer.MAX_VALUE);
162.1729 +        BigDecimal quotient = this.divide(divisor, new MathContext(maxDigits,
162.1730 +                                                                   RoundingMode.DOWN));
162.1731 +        if (quotient.scale > 0) {
162.1732 +            quotient = quotient.setScale(0, RoundingMode.DOWN);
162.1733 +            quotient.stripZerosToMatchScale(preferredScale);
162.1734 +        }
162.1735 +
162.1736 +        if (quotient.scale < preferredScale) {
162.1737 +            // pad with zeros if necessary
162.1738 +            quotient = quotient.setScale(preferredScale, ROUND_UNNECESSARY);
162.1739 +        }
162.1740 +        return quotient;
162.1741 +    }
162.1742 +
162.1743 +    /**
162.1744 +     * Returns a {@code BigDecimal} whose value is the integer part
162.1745 +     * of {@code (this / divisor)}.  Since the integer part of the
162.1746 +     * exact quotient does not depend on the rounding mode, the
162.1747 +     * rounding mode does not affect the values returned by this
162.1748 +     * method.  The preferred scale of the result is
162.1749 +     * {@code (this.scale() - divisor.scale())}.  An
162.1750 +     * {@code ArithmeticException} is thrown if the integer part of
162.1751 +     * the exact quotient needs more than {@code mc.precision}
162.1752 +     * digits.
162.1753 +     *
162.1754 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1755 +     * @param  mc the context to use.
162.1756 +     * @return The integer part of {@code this / divisor}.
162.1757 +     * @throws ArithmeticException if {@code divisor==0}
162.1758 +     * @throws ArithmeticException if {@code mc.precision} {@literal >} 0 and the result
162.1759 +     *         requires a precision of more than {@code mc.precision} digits.
162.1760 +     * @since  1.5
162.1761 +     * @author Joseph D. Darcy
162.1762 +     */
162.1763 +    public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
162.1764 +        if (mc.precision == 0 ||                        // exact result
162.1765 +            (this.compareMagnitude(divisor) < 0) )      // zero result
162.1766 +            return divideToIntegralValue(divisor);
162.1767 +
162.1768 +        // Calculate preferred scale
162.1769 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
162.1770 +
162.1771 +        /*
162.1772 +         * Perform a normal divide to mc.precision digits.  If the
162.1773 +         * remainder has absolute value less than the divisor, the
162.1774 +         * integer portion of the quotient fits into mc.precision
162.1775 +         * digits.  Next, remove any fractional digits from the
162.1776 +         * quotient and adjust the scale to the preferred value.
162.1777 +         */
162.1778 +        BigDecimal result = this.
162.1779 +            divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN));
162.1780 +
162.1781 +        if (result.scale() < 0) {
162.1782 +            /*
162.1783 +             * Result is an integer. See if quotient represents the
162.1784 +             * full integer portion of the exact quotient; if it does,
162.1785 +             * the computed remainder will be less than the divisor.
162.1786 +             */
162.1787 +            BigDecimal product = result.multiply(divisor);
162.1788 +            // If the quotient is the full integer value,
162.1789 +            // |dividend-product| < |divisor|.
162.1790 +            if (this.subtract(product).compareMagnitude(divisor) >= 0) {
162.1791 +                throw new ArithmeticException("Division impossible");
162.1792 +            }
162.1793 +        } else if (result.scale() > 0) {
162.1794 +            /*
162.1795 +             * Integer portion of quotient will fit into precision
162.1796 +             * digits; recompute quotient to scale 0 to avoid double
162.1797 +             * rounding and then try to adjust, if necessary.
162.1798 +             */
162.1799 +            result = result.setScale(0, RoundingMode.DOWN);
162.1800 +        }
162.1801 +        // else result.scale() == 0;
162.1802 +
162.1803 +        int precisionDiff;
162.1804 +        if ((preferredScale > result.scale()) &&
162.1805 +            (precisionDiff = mc.precision - result.precision()) > 0) {
162.1806 +            return result.setScale(result.scale() +
162.1807 +                                   Math.min(precisionDiff, preferredScale - result.scale) );
162.1808 +        } else {
162.1809 +            result.stripZerosToMatchScale(preferredScale);
162.1810 +            return result;
162.1811 +        }
162.1812 +    }
162.1813 +
162.1814 +    /**
162.1815 +     * Returns a {@code BigDecimal} whose value is {@code (this % divisor)}.
162.1816 +     *
162.1817 +     * <p>The remainder is given by
162.1818 +     * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}.
162.1819 +     * Note that this is not the modulo operation (the result can be
162.1820 +     * negative).
162.1821 +     *
162.1822 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1823 +     * @return {@code this % divisor}.
162.1824 +     * @throws ArithmeticException if {@code divisor==0}
162.1825 +     * @since  1.5
162.1826 +     */
162.1827 +    public BigDecimal remainder(BigDecimal divisor) {
162.1828 +        BigDecimal divrem[] = this.divideAndRemainder(divisor);
162.1829 +        return divrem[1];
162.1830 +    }
162.1831 +
162.1832 +
162.1833 +    /**
162.1834 +     * Returns a {@code BigDecimal} whose value is {@code (this %
162.1835 +     * divisor)}, with rounding according to the context settings.
162.1836 +     * The {@code MathContext} settings affect the implicit divide
162.1837 +     * used to compute the remainder.  The remainder computation
162.1838 +     * itself is by definition exact.  Therefore, the remainder may
162.1839 +     * contain more than {@code mc.getPrecision()} digits.
162.1840 +     *
162.1841 +     * <p>The remainder is given by
162.1842 +     * {@code this.subtract(this.divideToIntegralValue(divisor,
162.1843 +     * mc).multiply(divisor))}.  Note that this is not the modulo
162.1844 +     * operation (the result can be negative).
162.1845 +     *
162.1846 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
162.1847 +     * @param  mc the context to use.
162.1848 +     * @return {@code this % divisor}, rounded as necessary.
162.1849 +     * @throws ArithmeticException if {@code divisor==0}
162.1850 +     * @throws ArithmeticException if the result is inexact but the
162.1851 +     *         rounding mode is {@code UNNECESSARY}, or {@code mc.precision}
162.1852 +     *         {@literal >} 0 and the result of {@code this.divideToIntgralValue(divisor)} would
162.1853 +     *         require a precision of more than {@code mc.precision} digits.
162.1854 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
162.1855 +     * @since  1.5
162.1856 +     */
162.1857 +    public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
162.1858 +        BigDecimal divrem[] = this.divideAndRemainder(divisor, mc);
162.1859 +        return divrem[1];
162.1860 +    }
162.1861 +
162.1862 +    /**
162.1863 +     * Returns a two-element {@code BigDecimal} array containing the
162.1864 +     * result of {@code divideToIntegralValue} followed by the result of
162.1865 +     * {@code remainder} on the two operands.
162.1866 +     *
162.1867 +     * <p>Note that if both the integer quotient and remainder are
162.1868 +     * needed, this method is faster than using the
162.1869 +     * {@code divideToIntegralValue} and {@code remainder} methods
162.1870 +     * separately because the division need only be carried out once.
162.1871 +     *
162.1872 +     * @param  divisor value by which this {@code BigDecimal} is to be divided,
162.1873 +     *         and the remainder computed.
162.1874 +     * @return a two element {@code BigDecimal} array: the quotient
162.1875 +     *         (the result of {@code divideToIntegralValue}) is the initial element
162.1876 +     *         and the remainder is the final element.
162.1877 +     * @throws ArithmeticException if {@code divisor==0}
162.1878 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
162.1879 +     * @see    #remainder(java.math.BigDecimal, java.math.MathContext)
162.1880 +     * @since  1.5
162.1881 +     */
162.1882 +    public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
162.1883 +        // we use the identity  x = i * y + r to determine r
162.1884 +        BigDecimal[] result = new BigDecimal[2];
162.1885 +
162.1886 +        result[0] = this.divideToIntegralValue(divisor);
162.1887 +        result[1] = this.subtract(result[0].multiply(divisor));
162.1888 +        return result;
162.1889 +    }
162.1890 +
162.1891 +    /**
162.1892 +     * Returns a two-element {@code BigDecimal} array containing the
162.1893 +     * result of {@code divideToIntegralValue} followed by the result of
162.1894 +     * {@code remainder} on the two operands calculated with rounding
162.1895 +     * according to the context settings.
162.1896 +     *
162.1897 +     * <p>Note that if both the integer quotient and remainder are
162.1898 +     * needed, this method is faster than using the
162.1899 +     * {@code divideToIntegralValue} and {@code remainder} methods
162.1900 +     * separately because the division need only be carried out once.
162.1901 +     *
162.1902 +     * @param  divisor value by which this {@code BigDecimal} is to be divided,
162.1903 +     *         and the remainder computed.
162.1904 +     * @param  mc the context to use.
162.1905 +     * @return a two element {@code BigDecimal} array: the quotient
162.1906 +     *         (the result of {@code divideToIntegralValue}) is the
162.1907 +     *         initial element and the remainder is the final element.
162.1908 +     * @throws ArithmeticException if {@code divisor==0}
162.1909 +     * @throws ArithmeticException if the result is inexact but the
162.1910 +     *         rounding mode is {@code UNNECESSARY}, or {@code mc.precision}
162.1911 +     *         {@literal >} 0 and the result of {@code this.divideToIntgralValue(divisor)} would
162.1912 +     *         require a precision of more than {@code mc.precision} digits.
162.1913 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
162.1914 +     * @see    #remainder(java.math.BigDecimal, java.math.MathContext)
162.1915 +     * @since  1.5
162.1916 +     */
162.1917 +    public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
162.1918 +        if (mc.precision == 0)
162.1919 +            return divideAndRemainder(divisor);
162.1920 +
162.1921 +        BigDecimal[] result = new BigDecimal[2];
162.1922 +        BigDecimal lhs = this;
162.1923 +
162.1924 +        result[0] = lhs.divideToIntegralValue(divisor, mc);
162.1925 +        result[1] = lhs.subtract(result[0].multiply(divisor));
162.1926 +        return result;
162.1927 +    }
162.1928 +
162.1929 +    /**
162.1930 +     * Returns a {@code BigDecimal} whose value is
162.1931 +     * <tt>(this<sup>n</sup>)</tt>, The power is computed exactly, to
162.1932 +     * unlimited precision.
162.1933 +     *
162.1934 +     * <p>The parameter {@code n} must be in the range 0 through
162.1935 +     * 999999999, inclusive.  {@code ZERO.pow(0)} returns {@link
162.1936 +     * #ONE}.
162.1937 +     *
162.1938 +     * Note that future releases may expand the allowable exponent
162.1939 +     * range of this method.
162.1940 +     *
162.1941 +     * @param  n power to raise this {@code BigDecimal} to.
162.1942 +     * @return <tt>this<sup>n</sup></tt>
162.1943 +     * @throws ArithmeticException if {@code n} is out of range.
162.1944 +     * @since  1.5
162.1945 +     */
162.1946 +    public BigDecimal pow(int n) {
162.1947 +        if (n < 0 || n > 999999999)
162.1948 +            throw new ArithmeticException("Invalid operation");
162.1949 +        // No need to calculate pow(n) if result will over/underflow.
162.1950 +        // Don't attempt to support "supernormal" numbers.
162.1951 +        int newScale = checkScale((long)scale * n);
162.1952 +        this.inflate();
162.1953 +        return new BigDecimal(intVal.pow(n), newScale);
162.1954 +    }
162.1955 +
162.1956 +
162.1957 +    /**
162.1958 +     * Returns a {@code BigDecimal} whose value is
162.1959 +     * <tt>(this<sup>n</sup>)</tt>.  The current implementation uses
162.1960 +     * the core algorithm defined in ANSI standard X3.274-1996 with
162.1961 +     * rounding according to the context settings.  In general, the
162.1962 +     * returned numerical value is within two ulps of the exact
162.1963 +     * numerical value for the chosen precision.  Note that future
162.1964 +     * releases may use a different algorithm with a decreased
162.1965 +     * allowable error bound and increased allowable exponent range.
162.1966 +     *
162.1967 +     * <p>The X3.274-1996 algorithm is:
162.1968 +     *
162.1969 +     * <ul>
162.1970 +     * <li> An {@code ArithmeticException} exception is thrown if
162.1971 +     *  <ul>
162.1972 +     *    <li>{@code abs(n) > 999999999}
162.1973 +     *    <li>{@code mc.precision == 0} and {@code n < 0}
162.1974 +     *    <li>{@code mc.precision > 0} and {@code n} has more than
162.1975 +     *    {@code mc.precision} decimal digits
162.1976 +     *  </ul>
162.1977 +     *
162.1978 +     * <li> if {@code n} is zero, {@link #ONE} is returned even if
162.1979 +     * {@code this} is zero, otherwise
162.1980 +     * <ul>
162.1981 +     *   <li> if {@code n} is positive, the result is calculated via
162.1982 +     *   the repeated squaring technique into a single accumulator.
162.1983 +     *   The individual multiplications with the accumulator use the
162.1984 +     *   same math context settings as in {@code mc} except for a
162.1985 +     *   precision increased to {@code mc.precision + elength + 1}
162.1986 +     *   where {@code elength} is the number of decimal digits in
162.1987 +     *   {@code n}.
162.1988 +     *
162.1989 +     *   <li> if {@code n} is negative, the result is calculated as if
162.1990 +     *   {@code n} were positive; this value is then divided into one
162.1991 +     *   using the working precision specified above.
162.1992 +     *
162.1993 +     *   <li> The final value from either the positive or negative case
162.1994 +     *   is then rounded to the destination precision.
162.1995 +     *   </ul>
162.1996 +     * </ul>
162.1997 +     *
162.1998 +     * @param  n power to raise this {@code BigDecimal} to.
162.1999 +     * @param  mc the context to use.
162.2000 +     * @return <tt>this<sup>n</sup></tt> using the ANSI standard X3.274-1996
162.2001 +     *         algorithm
162.2002 +     * @throws ArithmeticException if the result is inexact but the
162.2003 +     *         rounding mode is {@code UNNECESSARY}, or {@code n} is out
162.2004 +     *         of range.
162.2005 +     * @since  1.5
162.2006 +     */
162.2007 +    public BigDecimal pow(int n, MathContext mc) {
162.2008 +        if (mc.precision == 0)
162.2009 +            return pow(n);
162.2010 +        if (n < -999999999 || n > 999999999)
162.2011 +            throw new ArithmeticException("Invalid operation");
162.2012 +        if (n == 0)
162.2013 +            return ONE;                      // x**0 == 1 in X3.274
162.2014 +        this.inflate();
162.2015 +        BigDecimal lhs = this;
162.2016 +        MathContext workmc = mc;           // working settings
162.2017 +        int mag = Math.abs(n);               // magnitude of n
162.2018 +        if (mc.precision > 0) {
162.2019 +
162.2020 +            int elength = longDigitLength(mag); // length of n in digits
162.2021 +            if (elength > mc.precision)        // X3.274 rule
162.2022 +                throw new ArithmeticException("Invalid operation");
162.2023 +            workmc = new MathContext(mc.precision + elength + 1,
162.2024 +                                      mc.roundingMode);
162.2025 +        }
162.2026 +        // ready to carry out power calculation...
162.2027 +        BigDecimal acc = ONE;           // accumulator
162.2028 +        boolean seenbit = false;        // set once we've seen a 1-bit
162.2029 +        for (int i=1;;i++) {            // for each bit [top bit ignored]
162.2030 +            mag += mag;                 // shift left 1 bit
162.2031 +            if (mag < 0) {              // top bit is set
162.2032 +                seenbit = true;         // OK, we're off
162.2033 +                acc = acc.multiply(lhs, workmc); // acc=acc*x
162.2034 +            }
162.2035 +            if (i == 31)
162.2036 +                break;                  // that was the last bit
162.2037 +            if (seenbit)
162.2038 +                acc=acc.multiply(acc, workmc);   // acc=acc*acc [square]
162.2039 +                // else (!seenbit) no point in squaring ONE
162.2040 +        }
162.2041 +        // if negative n, calculate the reciprocal using working precision
162.2042 +        if (n<0)                          // [hence mc.precision>0]
162.2043 +            acc=ONE.divide(acc, workmc);
162.2044 +        // round to final precision and strip zeros
162.2045 +        return doRound(acc, mc);
162.2046 +    }
162.2047 +
162.2048 +    /**
162.2049 +     * Returns a {@code BigDecimal} whose value is the absolute value
162.2050 +     * of this {@code BigDecimal}, and whose scale is
162.2051 +     * {@code this.scale()}.
162.2052 +     *
162.2053 +     * @return {@code abs(this)}
162.2054 +     */
162.2055 +    public BigDecimal abs() {
162.2056 +        return (signum() < 0 ? negate() : this);
162.2057 +    }
162.2058 +
162.2059 +    /**
162.2060 +     * Returns a {@code BigDecimal} whose value is the absolute value
162.2061 +     * of this {@code BigDecimal}, with rounding according to the
162.2062 +     * context settings.
162.2063 +     *
162.2064 +     * @param mc the context to use.
162.2065 +     * @return {@code abs(this)}, rounded as necessary.
162.2066 +     * @throws ArithmeticException if the result is inexact but the
162.2067 +     *         rounding mode is {@code UNNECESSARY}.
162.2068 +     * @since 1.5
162.2069 +     */
162.2070 +    public BigDecimal abs(MathContext mc) {
162.2071 +        return (signum() < 0 ? negate(mc) : plus(mc));
162.2072 +    }
162.2073 +
162.2074 +    /**
162.2075 +     * Returns a {@code BigDecimal} whose value is {@code (-this)},
162.2076 +     * and whose scale is {@code this.scale()}.
162.2077 +     *
162.2078 +     * @return {@code -this}.
162.2079 +     */
162.2080 +    public BigDecimal negate() {
162.2081 +        BigDecimal result;
162.2082 +        if (intCompact != INFLATED)
162.2083 +            result = BigDecimal.valueOf(-intCompact, scale);
162.2084 +        else {
162.2085 +            result = new BigDecimal(intVal.negate(), scale);
162.2086 +            result.precision = precision;
162.2087 +        }
162.2088 +        return result;
162.2089 +    }
162.2090 +
162.2091 +    /**
162.2092 +     * Returns a {@code BigDecimal} whose value is {@code (-this)},
162.2093 +     * with rounding according to the context settings.
162.2094 +     *
162.2095 +     * @param mc the context to use.
162.2096 +     * @return {@code -this}, rounded as necessary.
162.2097 +     * @throws ArithmeticException if the result is inexact but the
162.2098 +     *         rounding mode is {@code UNNECESSARY}.
162.2099 +     * @since  1.5
162.2100 +     */
162.2101 +    public BigDecimal negate(MathContext mc) {
162.2102 +        return negate().plus(mc);
162.2103 +    }
162.2104 +
162.2105 +    /**
162.2106 +     * Returns a {@code BigDecimal} whose value is {@code (+this)}, and whose
162.2107 +     * scale is {@code this.scale()}.
162.2108 +     *
162.2109 +     * <p>This method, which simply returns this {@code BigDecimal}
162.2110 +     * is included for symmetry with the unary minus method {@link
162.2111 +     * #negate()}.
162.2112 +     *
162.2113 +     * @return {@code this}.
162.2114 +     * @see #negate()
162.2115 +     * @since  1.5
162.2116 +     */
162.2117 +    public BigDecimal plus() {
162.2118 +        return this;
162.2119 +    }
162.2120 +
162.2121 +    /**
162.2122 +     * Returns a {@code BigDecimal} whose value is {@code (+this)},
162.2123 +     * with rounding according to the context settings.
162.2124 +     *
162.2125 +     * <p>The effect of this method is identical to that of the {@link
162.2126 +     * #round(MathContext)} method.
162.2127 +     *
162.2128 +     * @param mc the context to use.
162.2129 +     * @return {@code this}, rounded as necessary.  A zero result will
162.2130 +     *         have a scale of 0.
162.2131 +     * @throws ArithmeticException if the result is inexact but the
162.2132 +     *         rounding mode is {@code UNNECESSARY}.
162.2133 +     * @see    #round(MathContext)
162.2134 +     * @since  1.5
162.2135 +     */
162.2136 +    public BigDecimal plus(MathContext mc) {
162.2137 +        if (mc.precision == 0)                 // no rounding please
162.2138 +            return this;
162.2139 +        return doRound(this, mc);
162.2140 +    }
162.2141 +
162.2142 +    /**
162.2143 +     * Returns the signum function of this {@code BigDecimal}.
162.2144 +     *
162.2145 +     * @return -1, 0, or 1 as the value of this {@code BigDecimal}
162.2146 +     *         is negative, zero, or positive.
162.2147 +     */
162.2148 +    public int signum() {
162.2149 +        return (intCompact != INFLATED)?
162.2150 +            Long.signum(intCompact):
162.2151 +            intVal.signum();
162.2152 +    }
162.2153 +
162.2154 +    /**
162.2155 +     * Returns the <i>scale</i> of this {@code BigDecimal}.  If zero
162.2156 +     * or positive, the scale is the number of digits to the right of
162.2157 +     * the decimal point.  If negative, the unscaled value of the
162.2158 +     * number is multiplied by ten to the power of the negation of the
162.2159 +     * scale.  For example, a scale of {@code -3} means the unscaled
162.2160 +     * value is multiplied by 1000.
162.2161 +     *
162.2162 +     * @return the scale of this {@code BigDecimal}.
162.2163 +     */
162.2164 +    public int scale() {
162.2165 +        return scale;
162.2166 +    }
162.2167 +
162.2168 +    /**
162.2169 +     * Returns the <i>precision</i> of this {@code BigDecimal}.  (The
162.2170 +     * precision is the number of digits in the unscaled value.)
162.2171 +     *
162.2172 +     * <p>The precision of a zero value is 1.
162.2173 +     *
162.2174 +     * @return the precision of this {@code BigDecimal}.
162.2175 +     * @since  1.5
162.2176 +     */
162.2177 +    public int precision() {
162.2178 +        int result = precision;
162.2179 +        if (result == 0) {
162.2180 +            long s = intCompact;
162.2181 +            if (s != INFLATED)
162.2182 +                result = longDigitLength(s);
162.2183 +            else
162.2184 +                result = bigDigitLength(inflate());
162.2185 +            precision = result;
162.2186 +        }
162.2187 +        return result;
162.2188 +    }
162.2189 +
162.2190 +
162.2191 +    /**
162.2192 +     * Returns a {@code BigInteger} whose value is the <i>unscaled
162.2193 +     * value</i> of this {@code BigDecimal}.  (Computes <tt>(this *
162.2194 +     * 10<sup>this.scale()</sup>)</tt>.)
162.2195 +     *
162.2196 +     * @return the unscaled value of this {@code BigDecimal}.
162.2197 +     * @since  1.2
162.2198 +     */
162.2199 +    public BigInteger unscaledValue() {
162.2200 +        return this.inflate();
162.2201 +    }
162.2202 +
162.2203 +    // Rounding Modes
162.2204 +
162.2205 +    /**
162.2206 +     * Rounding mode to round away from zero.  Always increments the
162.2207 +     * digit prior to a nonzero discarded fraction.  Note that this rounding
162.2208 +     * mode never decreases the magnitude of the calculated value.
162.2209 +     */
162.2210 +    public final static int ROUND_UP =           0;
162.2211 +
162.2212 +    /**
162.2213 +     * Rounding mode to round towards zero.  Never increments the digit
162.2214 +     * prior to a discarded fraction (i.e., truncates).  Note that this
162.2215 +     * rounding mode never increases the magnitude of the calculated value.
162.2216 +     */
162.2217 +    public final static int ROUND_DOWN =         1;
162.2218 +
162.2219 +    /**
162.2220 +     * Rounding mode to round towards positive infinity.  If the
162.2221 +     * {@code BigDecimal} is positive, behaves as for
162.2222 +     * {@code ROUND_UP}; if negative, behaves as for
162.2223 +     * {@code ROUND_DOWN}.  Note that this rounding mode never
162.2224 +     * decreases the calculated value.
162.2225 +     */
162.2226 +    public final static int ROUND_CEILING =      2;
162.2227 +
162.2228 +    /**
162.2229 +     * Rounding mode to round towards negative infinity.  If the
162.2230 +     * {@code BigDecimal} is positive, behave as for
162.2231 +     * {@code ROUND_DOWN}; if negative, behave as for
162.2232 +     * {@code ROUND_UP}.  Note that this rounding mode never
162.2233 +     * increases the calculated value.
162.2234 +     */
162.2235 +    public final static int ROUND_FLOOR =        3;
162.2236 +
162.2237 +    /**
162.2238 +     * Rounding mode to round towards {@literal "nearest neighbor"}
162.2239 +     * unless both neighbors are equidistant, in which case round up.
162.2240 +     * Behaves as for {@code ROUND_UP} if the discarded fraction is
162.2241 +     * &ge; 0.5; otherwise, behaves as for {@code ROUND_DOWN}.  Note
162.2242 +     * that this is the rounding mode that most of us were taught in
162.2243 +     * grade school.
162.2244 +     */
162.2245 +    public final static int ROUND_HALF_UP =      4;
162.2246 +
162.2247 +    /**
162.2248 +     * Rounding mode to round towards {@literal "nearest neighbor"}
162.2249 +     * unless both neighbors are equidistant, in which case round
162.2250 +     * down.  Behaves as for {@code ROUND_UP} if the discarded
162.2251 +     * fraction is {@literal >} 0.5; otherwise, behaves as for
162.2252 +     * {@code ROUND_DOWN}.
162.2253 +     */
162.2254 +    public final static int ROUND_HALF_DOWN =    5;
162.2255 +
162.2256 +    /**
162.2257 +     * Rounding mode to round towards the {@literal "nearest neighbor"}
162.2258 +     * unless both neighbors are equidistant, in which case, round
162.2259 +     * towards the even neighbor.  Behaves as for
162.2260 +     * {@code ROUND_HALF_UP} if the digit to the left of the
162.2261 +     * discarded fraction is odd; behaves as for
162.2262 +     * {@code ROUND_HALF_DOWN} if it's even.  Note that this is the
162.2263 +     * rounding mode that minimizes cumulative error when applied
162.2264 +     * repeatedly over a sequence of calculations.
162.2265 +     */
162.2266 +    public final static int ROUND_HALF_EVEN =    6;
162.2267 +
162.2268 +    /**
162.2269 +     * Rounding mode to assert that the requested operation has an exact
162.2270 +     * result, hence no rounding is necessary.  If this rounding mode is
162.2271 +     * specified on an operation that yields an inexact result, an
162.2272 +     * {@code ArithmeticException} is thrown.
162.2273 +     */
162.2274 +    public final static int ROUND_UNNECESSARY =  7;
162.2275 +
162.2276 +
162.2277 +    // Scaling/Rounding Operations
162.2278 +
162.2279 +    /**
162.2280 +     * Returns a {@code BigDecimal} rounded according to the
162.2281 +     * {@code MathContext} settings.  If the precision setting is 0 then
162.2282 +     * no rounding takes place.
162.2283 +     *
162.2284 +     * <p>The effect of this method is identical to that of the
162.2285 +     * {@link #plus(MathContext)} method.
162.2286 +     *
162.2287 +     * @param mc the context to use.
162.2288 +     * @return a {@code BigDecimal} rounded according to the
162.2289 +     *         {@code MathContext} settings.
162.2290 +     * @throws ArithmeticException if the rounding mode is
162.2291 +     *         {@code UNNECESSARY} and the
162.2292 +     *         {@code BigDecimal}  operation would require rounding.
162.2293 +     * @see    #plus(MathContext)
162.2294 +     * @since  1.5
162.2295 +     */
162.2296 +    public BigDecimal round(MathContext mc) {
162.2297 +        return plus(mc);
162.2298 +    }
162.2299 +
162.2300 +    /**
162.2301 +     * Returns a {@code BigDecimal} whose scale is the specified
162.2302 +     * value, and whose unscaled value is determined by multiplying or
162.2303 +     * dividing this {@code BigDecimal}'s unscaled value by the
162.2304 +     * appropriate power of ten to maintain its overall value.  If the
162.2305 +     * scale is reduced by the operation, the unscaled value must be
162.2306 +     * divided (rather than multiplied), and the value may be changed;
162.2307 +     * in this case, the specified rounding mode is applied to the
162.2308 +     * division.
162.2309 +     *
162.2310 +     * <p>Note that since BigDecimal objects are immutable, calls of
162.2311 +     * this method do <i>not</i> result in the original object being
162.2312 +     * modified, contrary to the usual convention of having methods
162.2313 +     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
162.2314 +     * Instead, {@code setScale} returns an object with the proper
162.2315 +     * scale; the returned object may or may not be newly allocated.
162.2316 +     *
162.2317 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
162.2318 +     * @param  roundingMode The rounding mode to apply.
162.2319 +     * @return a {@code BigDecimal} whose scale is the specified value,
162.2320 +     *         and whose unscaled value is determined by multiplying or
162.2321 +     *         dividing this {@code BigDecimal}'s unscaled value by the
162.2322 +     *         appropriate power of ten to maintain its overall value.
162.2323 +     * @throws ArithmeticException if {@code roundingMode==UNNECESSARY}
162.2324 +     *         and the specified scaling operation would require
162.2325 +     *         rounding.
162.2326 +     * @see    RoundingMode
162.2327 +     * @since  1.5
162.2328 +     */
162.2329 +    public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
162.2330 +        return setScale(newScale, roundingMode.oldMode);
162.2331 +    }
162.2332 +
162.2333 +    /**
162.2334 +     * Returns a {@code BigDecimal} whose scale is the specified
162.2335 +     * value, and whose unscaled value is determined by multiplying or
162.2336 +     * dividing this {@code BigDecimal}'s unscaled value by the
162.2337 +     * appropriate power of ten to maintain its overall value.  If the
162.2338 +     * scale is reduced by the operation, the unscaled value must be
162.2339 +     * divided (rather than multiplied), and the value may be changed;
162.2340 +     * in this case, the specified rounding mode is applied to the
162.2341 +     * division.
162.2342 +     *
162.2343 +     * <p>Note that since BigDecimal objects are immutable, calls of
162.2344 +     * this method do <i>not</i> result in the original object being
162.2345 +     * modified, contrary to the usual convention of having methods
162.2346 +     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
162.2347 +     * Instead, {@code setScale} returns an object with the proper
162.2348 +     * scale; the returned object may or may not be newly allocated.
162.2349 +     *
162.2350 +     * <p>The new {@link #setScale(int, RoundingMode)} method should
162.2351 +     * be used in preference to this legacy method.
162.2352 +     *
162.2353 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
162.2354 +     * @param  roundingMode The rounding mode to apply.
162.2355 +     * @return a {@code BigDecimal} whose scale is the specified value,
162.2356 +     *         and whose unscaled value is determined by multiplying or
162.2357 +     *         dividing this {@code BigDecimal}'s unscaled value by the
162.2358 +     *         appropriate power of ten to maintain its overall value.
162.2359 +     * @throws ArithmeticException if {@code roundingMode==ROUND_UNNECESSARY}
162.2360 +     *         and the specified scaling operation would require
162.2361 +     *         rounding.
162.2362 +     * @throws IllegalArgumentException if {@code roundingMode} does not
162.2363 +     *         represent a valid rounding mode.
162.2364 +     * @see    #ROUND_UP
162.2365 +     * @see    #ROUND_DOWN
162.2366 +     * @see    #ROUND_CEILING
162.2367 +     * @see    #ROUND_FLOOR
162.2368 +     * @see    #ROUND_HALF_UP
162.2369 +     * @see    #ROUND_HALF_DOWN
162.2370 +     * @see    #ROUND_HALF_EVEN
162.2371 +     * @see    #ROUND_UNNECESSARY
162.2372 +     */
162.2373 +    public BigDecimal setScale(int newScale, int roundingMode) {
162.2374 +        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
162.2375 +            throw new IllegalArgumentException("Invalid rounding mode");
162.2376 +
162.2377 +        int oldScale = this.scale;
162.2378 +        if (newScale == oldScale)        // easy case
162.2379 +            return this;
162.2380 +        if (this.signum() == 0)            // zero can have any scale
162.2381 +            return BigDecimal.valueOf(0, newScale);
162.2382 +
162.2383 +        long rs = this.intCompact;
162.2384 +        if (newScale > oldScale) {
162.2385 +            int raise = checkScale((long)newScale - oldScale);
162.2386 +            BigInteger rb = null;
162.2387 +            if (rs == INFLATED ||
162.2388 +                (rs = longMultiplyPowerTen(rs, raise)) == INFLATED)
162.2389 +                rb = bigMultiplyPowerTen(raise);
162.2390 +            return new BigDecimal(rb, rs, newScale,
162.2391 +                                  (precision > 0) ? precision + raise : 0);
162.2392 +        } else {
162.2393 +            // newScale < oldScale -- drop some digits
162.2394 +            // Can't predict the precision due to the effect of rounding.
162.2395 +            int drop = checkScale((long)oldScale - newScale);
162.2396 +            if (drop < LONG_TEN_POWERS_TABLE.length)
162.2397 +                return divideAndRound(rs, this.intVal,
162.2398 +                                      LONG_TEN_POWERS_TABLE[drop], null,
162.2399 +                                      newScale, roundingMode, newScale);
162.2400 +            else
162.2401 +                return divideAndRound(rs, this.intVal,
162.2402 +                                      INFLATED, bigTenToThe(drop),
162.2403 +                                      newScale, roundingMode, newScale);
162.2404 +        }
162.2405 +    }
162.2406 +
162.2407 +    /**
162.2408 +     * Returns a {@code BigDecimal} whose scale is the specified
162.2409 +     * value, and whose value is numerically equal to this
162.2410 +     * {@code BigDecimal}'s.  Throws an {@code ArithmeticException}
162.2411 +     * if this is not possible.
162.2412 +     *
162.2413 +     * <p>This call is typically used to increase the scale, in which
162.2414 +     * case it is guaranteed that there exists a {@code BigDecimal}
162.2415 +     * of the specified scale and the correct value.  The call can
162.2416 +     * also be used to reduce the scale if the caller knows that the
162.2417 +     * {@code BigDecimal} has sufficiently many zeros at the end of
162.2418 +     * its fractional part (i.e., factors of ten in its integer value)
162.2419 +     * to allow for the rescaling without changing its value.
162.2420 +     *
162.2421 +     * <p>This method returns the same result as the two-argument
162.2422 +     * versions of {@code setScale}, but saves the caller the trouble
162.2423 +     * of specifying a rounding mode in cases where it is irrelevant.
162.2424 +     *
162.2425 +     * <p>Note that since {@code BigDecimal} objects are immutable,
162.2426 +     * calls of this method do <i>not</i> result in the original
162.2427 +     * object being modified, contrary to the usual convention of
162.2428 +     * having methods named <tt>set<i>X</i></tt> mutate field
162.2429 +     * <i>{@code X}</i>.  Instead, {@code setScale} returns an
162.2430 +     * object with the proper scale; the returned object may or may
162.2431 +     * not be newly allocated.
162.2432 +     *
162.2433 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
162.2434 +     * @return a {@code BigDecimal} whose scale is the specified value, and
162.2435 +     *         whose unscaled value is determined by multiplying or dividing
162.2436 +     *         this {@code BigDecimal}'s unscaled value by the appropriate
162.2437 +     *         power of ten to maintain its overall value.
162.2438 +     * @throws ArithmeticException if the specified scaling operation would
162.2439 +     *         require rounding.
162.2440 +     * @see    #setScale(int, int)
162.2441 +     * @see    #setScale(int, RoundingMode)
162.2442 +     */
162.2443 +    public BigDecimal setScale(int newScale) {
162.2444 +        return setScale(newScale, ROUND_UNNECESSARY);
162.2445 +    }
162.2446 +
162.2447 +    // Decimal Point Motion Operations
162.2448 +
162.2449 +    /**
162.2450 +     * Returns a {@code BigDecimal} which is equivalent to this one
162.2451 +     * with the decimal point moved {@code n} places to the left.  If
162.2452 +     * {@code n} is non-negative, the call merely adds {@code n} to
162.2453 +     * the scale.  If {@code n} is negative, the call is equivalent
162.2454 +     * to {@code movePointRight(-n)}.  The {@code BigDecimal}
162.2455 +     * returned by this call has value <tt>(this &times;
162.2456 +     * 10<sup>-n</sup>)</tt> and scale {@code max(this.scale()+n,
162.2457 +     * 0)}.
162.2458 +     *
162.2459 +     * @param  n number of places to move the decimal point to the left.
162.2460 +     * @return a {@code BigDecimal} which is equivalent to this one with the
162.2461 +     *         decimal point moved {@code n} places to the left.
162.2462 +     * @throws ArithmeticException if scale overflows.
162.2463 +     */
162.2464 +    public BigDecimal movePointLeft(int n) {
162.2465 +        // Cannot use movePointRight(-n) in case of n==Integer.MIN_VALUE
162.2466 +        int newScale = checkScale((long)scale + n);
162.2467 +        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
162.2468 +        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
162.2469 +    }
162.2470 +
162.2471 +    /**
162.2472 +     * Returns a {@code BigDecimal} which is equivalent to this one
162.2473 +     * with the decimal point moved {@code n} places to the right.
162.2474 +     * If {@code n} is non-negative, the call merely subtracts
162.2475 +     * {@code n} from the scale.  If {@code n} is negative, the call
162.2476 +     * is equivalent to {@code movePointLeft(-n)}.  The
162.2477 +     * {@code BigDecimal} returned by this call has value <tt>(this
162.2478 +     * &times; 10<sup>n</sup>)</tt> and scale {@code max(this.scale()-n,
162.2479 +     * 0)}.
162.2480 +     *
162.2481 +     * @param  n number of places to move the decimal point to the right.
162.2482 +     * @return a {@code BigDecimal} which is equivalent to this one
162.2483 +     *         with the decimal point moved {@code n} places to the right.
162.2484 +     * @throws ArithmeticException if scale overflows.
162.2485 +     */
162.2486 +    public BigDecimal movePointRight(int n) {
162.2487 +        // Cannot use movePointLeft(-n) in case of n==Integer.MIN_VALUE
162.2488 +        int newScale = checkScale((long)scale - n);
162.2489 +        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
162.2490 +        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
162.2491 +    }
162.2492 +
162.2493 +    /**
162.2494 +     * Returns a BigDecimal whose numerical value is equal to
162.2495 +     * ({@code this} * 10<sup>n</sup>).  The scale of
162.2496 +     * the result is {@code (this.scale() - n)}.
162.2497 +     *
162.2498 +     * @throws ArithmeticException if the scale would be
162.2499 +     *         outside the range of a 32-bit integer.
162.2500 +     *
162.2501 +     * @since 1.5
162.2502 +     */
162.2503 +    public BigDecimal scaleByPowerOfTen(int n) {
162.2504 +        return new BigDecimal(intVal, intCompact,
162.2505 +                              checkScale((long)scale - n), precision);
162.2506 +    }
162.2507 +
162.2508 +    /**
162.2509 +     * Returns a {@code BigDecimal} which is numerically equal to
162.2510 +     * this one but with any trailing zeros removed from the
162.2511 +     * representation.  For example, stripping the trailing zeros from
162.2512 +     * the {@code BigDecimal} value {@code 600.0}, which has
162.2513 +     * [{@code BigInteger}, {@code scale}] components equals to
162.2514 +     * [6000, 1], yields {@code 6E2} with [{@code BigInteger},
162.2515 +     * {@code scale}] components equals to [6, -2]
162.2516 +     *
162.2517 +     * @return a numerically equal {@code BigDecimal} with any
162.2518 +     * trailing zeros removed.
162.2519 +     * @since 1.5
162.2520 +     */
162.2521 +    public BigDecimal stripTrailingZeros() {
162.2522 +        this.inflate();
162.2523 +        BigDecimal result = new BigDecimal(intVal, scale);
162.2524 +        result.stripZerosToMatchScale(Long.MIN_VALUE);
162.2525 +        return result;
162.2526 +    }
162.2527 +
162.2528 +    // Comparison Operations
162.2529 +
162.2530 +    /**
162.2531 +     * Compares this {@code BigDecimal} with the specified
162.2532 +     * {@code BigDecimal}.  Two {@code BigDecimal} objects that are
162.2533 +     * equal in value but have a different scale (like 2.0 and 2.00)
162.2534 +     * are considered equal by this method.  This method is provided
162.2535 +     * in preference to individual methods for each of the six boolean
162.2536 +     * comparison operators ({@literal <}, ==,
162.2537 +     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The
162.2538 +     * suggested idiom for performing these comparisons is:
162.2539 +     * {@code (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
162.2540 +     * &lt;<i>op</i>&gt; is one of the six comparison operators.
162.2541 +     *
162.2542 +     * @param  val {@code BigDecimal} to which this {@code BigDecimal} is
162.2543 +     *         to be compared.
162.2544 +     * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
162.2545 +     *          less than, equal to, or greater than {@code val}.
162.2546 +     */
162.2547 +    public int compareTo(BigDecimal val) {
162.2548 +        // Quick path for equal scale and non-inflated case.
162.2549 +        if (scale == val.scale) {
162.2550 +            long xs = intCompact;
162.2551 +            long ys = val.intCompact;
162.2552 +            if (xs != INFLATED && ys != INFLATED)
162.2553 +                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
162.2554 +        }
162.2555 +        int xsign = this.signum();
162.2556 +        int ysign = val.signum();
162.2557 +        if (xsign != ysign)
162.2558 +            return (xsign > ysign) ? 1 : -1;
162.2559 +        if (xsign == 0)
162.2560 +            return 0;
162.2561 +        int cmp = compareMagnitude(val);
162.2562 +        return (xsign > 0) ? cmp : -cmp;
162.2563 +    }
162.2564 +
162.2565 +    /**
162.2566 +     * Version of compareTo that ignores sign.
162.2567 +     */
162.2568 +    private int compareMagnitude(BigDecimal val) {
162.2569 +        // Match scales, avoid unnecessary inflation
162.2570 +        long ys = val.intCompact;
162.2571 +        long xs = this.intCompact;
162.2572 +        if (xs == 0)
162.2573 +            return (ys == 0) ? 0 : -1;
162.2574 +        if (ys == 0)
162.2575 +            return 1;
162.2576 +
162.2577 +        int sdiff = this.scale - val.scale;
162.2578 +        if (sdiff != 0) {
162.2579 +            // Avoid matching scales if the (adjusted) exponents differ
162.2580 +            int xae = this.precision() - this.scale;   // [-1]
162.2581 +            int yae = val.precision() - val.scale;     // [-1]
162.2582 +            if (xae < yae)
162.2583 +                return -1;
162.2584 +            if (xae > yae)
162.2585 +                return 1;
162.2586 +            BigInteger rb = null;
162.2587 +            if (sdiff < 0) {
162.2588 +                if ( (xs == INFLATED ||
162.2589 +                      (xs = longMultiplyPowerTen(xs, -sdiff)) == INFLATED) &&
162.2590 +                     ys == INFLATED) {
162.2591 +                    rb = bigMultiplyPowerTen(-sdiff);
162.2592 +                    return rb.compareMagnitude(val.intVal);
162.2593 +                }
162.2594 +            } else { // sdiff > 0
162.2595 +                if ( (ys == INFLATED ||
162.2596 +                      (ys = longMultiplyPowerTen(ys, sdiff)) == INFLATED) &&
162.2597 +                     xs == INFLATED) {
162.2598 +                    rb = val.bigMultiplyPowerTen(sdiff);
162.2599 +                    return this.intVal.compareMagnitude(rb);
162.2600 +                }
162.2601 +            }
162.2602 +        }
162.2603 +        if (xs != INFLATED)
162.2604 +            return (ys != INFLATED) ? longCompareMagnitude(xs, ys) : -1;
162.2605 +        else if (ys != INFLATED)
162.2606 +            return 1;
162.2607 +        else
162.2608 +            return this.intVal.compareMagnitude(val.intVal);
162.2609 +    }
162.2610 +
162.2611 +    /**
162.2612 +     * Compares this {@code BigDecimal} with the specified
162.2613 +     * {@code Object} for equality.  Unlike {@link
162.2614 +     * #compareTo(BigDecimal) compareTo}, this method considers two
162.2615 +     * {@code BigDecimal} objects equal only if they are equal in
162.2616 +     * value and scale (thus 2.0 is not equal to 2.00 when compared by
162.2617 +     * this method).
162.2618 +     *
162.2619 +     * @param  x {@code Object} to which this {@code BigDecimal} is
162.2620 +     *         to be compared.
162.2621 +     * @return {@code true} if and only if the specified {@code Object} is a
162.2622 +     *         {@code BigDecimal} whose value and scale are equal to this
162.2623 +     *         {@code BigDecimal}'s.
162.2624 +     * @see    #compareTo(java.math.BigDecimal)
162.2625 +     * @see    #hashCode
162.2626 +     */
162.2627 +    @Override
162.2628 +    public boolean equals(Object x) {
162.2629 +        if (!(x instanceof BigDecimal))
162.2630 +            return false;
162.2631 +        BigDecimal xDec = (BigDecimal) x;
162.2632 +        if (x == this)
162.2633 +            return true;
162.2634 +        if (scale != xDec.scale)
162.2635 +            return false;
162.2636 +        long s = this.intCompact;
162.2637 +        long xs = xDec.intCompact;
162.2638 +        if (s != INFLATED) {
162.2639 +            if (xs == INFLATED)
162.2640 +                xs = compactValFor(xDec.intVal);
162.2641 +            return xs == s;
162.2642 +        } else if (xs != INFLATED)
162.2643 +            return xs == compactValFor(this.intVal);
162.2644 +
162.2645 +        return this.inflate().equals(xDec.inflate());
162.2646 +    }
162.2647 +
162.2648 +    /**
162.2649 +     * Returns the minimum of this {@code BigDecimal} and
162.2650 +     * {@code val}.
162.2651 +     *
162.2652 +     * @param  val value with which the minimum is to be computed.
162.2653 +     * @return the {@code BigDecimal} whose value is the lesser of this
162.2654 +     *         {@code BigDecimal} and {@code val}.  If they are equal,
162.2655 +     *         as defined by the {@link #compareTo(BigDecimal) compareTo}
162.2656 +     *         method, {@code this} is returned.
162.2657 +     * @see    #compareTo(java.math.BigDecimal)
162.2658 +     */
162.2659 +    public BigDecimal min(BigDecimal val) {
162.2660 +        return (compareTo(val) <= 0 ? this : val);
162.2661 +    }
162.2662 +
162.2663 +    /**
162.2664 +     * Returns the maximum of this {@code BigDecimal} and {@code val}.
162.2665 +     *
162.2666 +     * @param  val value with which the maximum is to be computed.
162.2667 +     * @return the {@code BigDecimal} whose value is the greater of this
162.2668 +     *         {@code BigDecimal} and {@code val}.  If they are equal,
162.2669 +     *         as defined by the {@link #compareTo(BigDecimal) compareTo}
162.2670 +     *         method, {@code this} is returned.
162.2671 +     * @see    #compareTo(java.math.BigDecimal)
162.2672 +     */
162.2673 +    public BigDecimal max(BigDecimal val) {
162.2674 +        return (compareTo(val) >= 0 ? this : val);
162.2675 +    }
162.2676 +
162.2677 +    // Hash Function
162.2678 +
162.2679 +    /**
162.2680 +     * Returns the hash code for this {@code BigDecimal}.  Note that
162.2681 +     * two {@code BigDecimal} objects that are numerically equal but
162.2682 +     * differ in scale (like 2.0 and 2.00) will generally <i>not</i>
162.2683 +     * have the same hash code.
162.2684 +     *
162.2685 +     * @return hash code for this {@code BigDecimal}.
162.2686 +     * @see #equals(Object)
162.2687 +     */
162.2688 +    @Override
162.2689 +    public int hashCode() {
162.2690 +        if (intCompact != INFLATED) {
162.2691 +            long val2 = (intCompact < 0)? -intCompact : intCompact;
162.2692 +            int temp = (int)( ((int)(val2 >>> 32)) * 31  +
162.2693 +                              (val2 & LONG_MASK));
162.2694 +            return 31*((intCompact < 0) ?-temp:temp) + scale;
162.2695 +        } else
162.2696 +            return 31*intVal.hashCode() + scale;
162.2697 +    }
162.2698 +
162.2699 +    // Format Converters
162.2700 +
162.2701 +    /**
162.2702 +     * Returns the string representation of this {@code BigDecimal},
162.2703 +     * using scientific notation if an exponent is needed.
162.2704 +     *
162.2705 +     * <p>A standard canonical string form of the {@code BigDecimal}
162.2706 +     * is created as though by the following steps: first, the
162.2707 +     * absolute value of the unscaled value of the {@code BigDecimal}
162.2708 +     * is converted to a string in base ten using the characters
162.2709 +     * {@code '0'} through {@code '9'} with no leading zeros (except
162.2710 +     * if its value is zero, in which case a single {@code '0'}
162.2711 +     * character is used).
162.2712 +     *
162.2713 +     * <p>Next, an <i>adjusted exponent</i> is calculated; this is the
162.2714 +     * negated scale, plus the number of characters in the converted
162.2715 +     * unscaled value, less one.  That is,
162.2716 +     * {@code -scale+(ulength-1)}, where {@code ulength} is the
162.2717 +     * length of the absolute value of the unscaled value in decimal
162.2718 +     * digits (its <i>precision</i>).
162.2719 +     *
162.2720 +     * <p>If the scale is greater than or equal to zero and the
162.2721 +     * adjusted exponent is greater than or equal to {@code -6}, the
162.2722 +     * number will be converted to a character form without using
162.2723 +     * exponential notation.  In this case, if the scale is zero then
162.2724 +     * no decimal point is added and if the scale is positive a
162.2725 +     * decimal point will be inserted with the scale specifying the
162.2726 +     * number of characters to the right of the decimal point.
162.2727 +     * {@code '0'} characters are added to the left of the converted
162.2728 +     * unscaled value as necessary.  If no character precedes the
162.2729 +     * decimal point after this insertion then a conventional
162.2730 +     * {@code '0'} character is prefixed.
162.2731 +     *
162.2732 +     * <p>Otherwise (that is, if the scale is negative, or the
162.2733 +     * adjusted exponent is less than {@code -6}), the number will be
162.2734 +     * converted to a character form using exponential notation.  In
162.2735 +     * this case, if the converted {@code BigInteger} has more than
162.2736 +     * one digit a decimal point is inserted after the first digit.
162.2737 +     * An exponent in character form is then suffixed to the converted
162.2738 +     * unscaled value (perhaps with inserted decimal point); this
162.2739 +     * comprises the letter {@code 'E'} followed immediately by the
162.2740 +     * adjusted exponent converted to a character form.  The latter is
162.2741 +     * in base ten, using the characters {@code '0'} through
162.2742 +     * {@code '9'} with no leading zeros, and is always prefixed by a
162.2743 +     * sign character {@code '-'} (<tt>'&#92;u002D'</tt>) if the
162.2744 +     * adjusted exponent is negative, {@code '+'}
162.2745 +     * (<tt>'&#92;u002B'</tt>) otherwise).
162.2746 +     *
162.2747 +     * <p>Finally, the entire string is prefixed by a minus sign
162.2748 +     * character {@code '-'} (<tt>'&#92;u002D'</tt>) if the unscaled
162.2749 +     * value is less than zero.  No sign character is prefixed if the
162.2750 +     * unscaled value is zero or positive.
162.2751 +     *
162.2752 +     * <p><b>Examples:</b>
162.2753 +     * <p>For each representation [<i>unscaled value</i>, <i>scale</i>]
162.2754 +     * on the left, the resulting string is shown on the right.
162.2755 +     * <pre>
162.2756 +     * [123,0]      "123"
162.2757 +     * [-123,0]     "-123"
162.2758 +     * [123,-1]     "1.23E+3"
162.2759 +     * [123,-3]     "1.23E+5"
162.2760 +     * [123,1]      "12.3"
162.2761 +     * [123,5]      "0.00123"
162.2762 +     * [123,10]     "1.23E-8"
162.2763 +     * [-123,12]    "-1.23E-10"
162.2764 +     * </pre>
162.2765 +     *
162.2766 +     * <b>Notes:</b>
162.2767 +     * <ol>
162.2768 +     *
162.2769 +     * <li>There is a one-to-one mapping between the distinguishable
162.2770 +     * {@code BigDecimal} values and the result of this conversion.
162.2771 +     * That is, every distinguishable {@code BigDecimal} value
162.2772 +     * (unscaled value and scale) has a unique string representation
162.2773 +     * as a result of using {@code toString}.  If that string
162.2774 +     * representation is converted back to a {@code BigDecimal} using
162.2775 +     * the {@link #BigDecimal(String)} constructor, then the original
162.2776 +     * value will be recovered.
162.2777 +     *
162.2778 +     * <li>The string produced for a given number is always the same;
162.2779 +     * it is not affected by locale.  This means that it can be used
162.2780 +     * as a canonical string representation for exchanging decimal
162.2781 +     * data, or as a key for a Hashtable, etc.  Locale-sensitive
162.2782 +     * number formatting and parsing is handled by the {@link
162.2783 +     * java.text.NumberFormat} class and its subclasses.
162.2784 +     *
162.2785 +     * <li>The {@link #toEngineeringString} method may be used for
162.2786 +     * presenting numbers with exponents in engineering notation, and the
162.2787 +     * {@link #setScale(int,RoundingMode) setScale} method may be used for
162.2788 +     * rounding a {@code BigDecimal} so it has a known number of digits after
162.2789 +     * the decimal point.
162.2790 +     *
162.2791 +     * <li>The digit-to-character mapping provided by
162.2792 +     * {@code Character.forDigit} is used.
162.2793 +     *
162.2794 +     * </ol>
162.2795 +     *
162.2796 +     * @return string representation of this {@code BigDecimal}.
162.2797 +     * @see    Character#forDigit
162.2798 +     * @see    #BigDecimal(java.lang.String)
162.2799 +     */
162.2800 +    @Override
162.2801 +    public String toString() {
162.2802 +        String sc = stringCache;
162.2803 +        if (sc == null)
162.2804 +            stringCache = sc = layoutChars(true);
162.2805 +        return sc;
162.2806 +    }
162.2807 +
162.2808 +    /**
162.2809 +     * Returns a string representation of this {@code BigDecimal},
162.2810 +     * using engineering notation if an exponent is needed.
162.2811 +     *
162.2812 +     * <p>Returns a string that represents the {@code BigDecimal} as
162.2813 +     * described in the {@link #toString()} method, except that if
162.2814 +     * exponential notation is used, the power of ten is adjusted to
162.2815 +     * be a multiple of three (engineering notation) such that the
162.2816 +     * integer part of nonzero values will be in the range 1 through
162.2817 +     * 999.  If exponential notation is used for zero values, a
162.2818 +     * decimal point and one or two fractional zero digits are used so
162.2819 +     * that the scale of the zero value is preserved.  Note that
162.2820 +     * unlike the output of {@link #toString()}, the output of this
162.2821 +     * method is <em>not</em> guaranteed to recover the same [integer,
162.2822 +     * scale] pair of this {@code BigDecimal} if the output string is
162.2823 +     * converting back to a {@code BigDecimal} using the {@linkplain
162.2824 +     * #BigDecimal(String) string constructor}.  The result of this method meets
162.2825 +     * the weaker constraint of always producing a numerically equal
162.2826 +     * result from applying the string constructor to the method's output.
162.2827 +     *
162.2828 +     * @return string representation of this {@code BigDecimal}, using
162.2829 +     *         engineering notation if an exponent is needed.
162.2830 +     * @since  1.5
162.2831 +     */
162.2832 +    public String toEngineeringString() {
162.2833 +        return layoutChars(false);
162.2834 +    }
162.2835 +
162.2836 +    /**
162.2837 +     * Returns a string representation of this {@code BigDecimal}
162.2838 +     * without an exponent field.  For values with a positive scale,
162.2839 +     * the number of digits to the right of the decimal point is used
162.2840 +     * to indicate scale.  For values with a zero or negative scale,
162.2841 +     * the resulting string is generated as if the value were
162.2842 +     * converted to a numerically equal value with zero scale and as
162.2843 +     * if all the trailing zeros of the zero scale value were present
162.2844 +     * in the result.
162.2845 +     *
162.2846 +     * The entire string is prefixed by a minus sign character '-'
162.2847 +     * (<tt>'&#92;u002D'</tt>) if the unscaled value is less than
162.2848 +     * zero. No sign character is prefixed if the unscaled value is
162.2849 +     * zero or positive.
162.2850 +     *
162.2851 +     * Note that if the result of this method is passed to the
162.2852 +     * {@linkplain #BigDecimal(String) string constructor}, only the
162.2853 +     * numerical value of this {@code BigDecimal} will necessarily be
162.2854 +     * recovered; the representation of the new {@code BigDecimal}
162.2855 +     * may have a different scale.  In particular, if this
162.2856 +     * {@code BigDecimal} has a negative scale, the string resulting
162.2857 +     * from this method will have a scale of zero when processed by
162.2858 +     * the string constructor.
162.2859 +     *
162.2860 +     * (This method behaves analogously to the {@code toString}
162.2861 +     * method in 1.4 and earlier releases.)
162.2862 +     *
162.2863 +     * @return a string representation of this {@code BigDecimal}
162.2864 +     * without an exponent field.
162.2865 +     * @since 1.5
162.2866 +     * @see #toString()
162.2867 +     * @see #toEngineeringString()
162.2868 +     */
162.2869 +    public String toPlainString() {
162.2870 +        BigDecimal bd = this;
162.2871 +        if (bd.scale < 0)
162.2872 +            bd = bd.setScale(0);
162.2873 +        bd.inflate();
162.2874 +        if (bd.scale == 0)      // No decimal point
162.2875 +            return bd.intVal.toString();
162.2876 +        return bd.getValueString(bd.signum(), bd.intVal.abs().toString(), bd.scale);
162.2877 +    }
162.2878 +
162.2879 +    /* Returns a digit.digit string */
162.2880 +    private String getValueString(int signum, String intString, int scale) {
162.2881 +        /* Insert decimal point */
162.2882 +        StringBuilder buf;
162.2883 +        int insertionPoint = intString.length() - scale;
162.2884 +        if (insertionPoint == 0) {  /* Point goes right before intVal */
162.2885 +            return (signum<0 ? "-0." : "0.") + intString;
162.2886 +        } else if (insertionPoint > 0) { /* Point goes inside intVal */
162.2887 +            buf = new StringBuilder(intString);
162.2888 +            buf.insert(insertionPoint, '.');
162.2889 +            if (signum < 0)
162.2890 +                buf.insert(0, '-');
162.2891 +        } else { /* We must insert zeros between point and intVal */
162.2892 +            buf = new StringBuilder(3-insertionPoint + intString.length());
162.2893 +            buf.append(signum<0 ? "-0." : "0.");
162.2894 +            for (int i=0; i<-insertionPoint; i++)
162.2895 +                buf.append('0');
162.2896 +            buf.append(intString);
162.2897 +        }
162.2898 +        return buf.toString();
162.2899 +    }
162.2900 +
162.2901 +    /**
162.2902 +     * Converts this {@code BigDecimal} to a {@code BigInteger}.
162.2903 +     * This conversion is analogous to the
162.2904 +     * <i>narrowing primitive conversion</i> from {@code double} to
162.2905 +     * {@code long} as defined in section 5.1.3 of
162.2906 +     * <cite>The Java&trade; Language Specification</cite>:
162.2907 +     * any fractional part of this
162.2908 +     * {@code BigDecimal} will be discarded.  Note that this
162.2909 +     * conversion can lose information about the precision of the
162.2910 +     * {@code BigDecimal} value.
162.2911 +     * <p>
162.2912 +     * To have an exception thrown if the conversion is inexact (in
162.2913 +     * other words if a nonzero fractional part is discarded), use the
162.2914 +     * {@link #toBigIntegerExact()} method.
162.2915 +     *
162.2916 +     * @return this {@code BigDecimal} converted to a {@code BigInteger}.
162.2917 +     */
162.2918 +    public BigInteger toBigInteger() {
162.2919 +        // force to an integer, quietly
162.2920 +        return this.setScale(0, ROUND_DOWN).inflate();
162.2921 +    }
162.2922 +
162.2923 +    /**
162.2924 +     * Converts this {@code BigDecimal} to a {@code BigInteger},
162.2925 +     * checking for lost information.  An exception is thrown if this
162.2926 +     * {@code BigDecimal} has a nonzero fractional part.
162.2927 +     *
162.2928 +     * @return this {@code BigDecimal} converted to a {@code BigInteger}.
162.2929 +     * @throws ArithmeticException if {@code this} has a nonzero
162.2930 +     *         fractional part.
162.2931 +     * @since  1.5
162.2932 +     */
162.2933 +    public BigInteger toBigIntegerExact() {
162.2934 +        // round to an integer, with Exception if decimal part non-0
162.2935 +        return this.setScale(0, ROUND_UNNECESSARY).inflate();
162.2936 +    }
162.2937 +
162.2938 +    /**
162.2939 +     * Converts this {@code BigDecimal} to a {@code long}.
162.2940 +     * This conversion is analogous to the
162.2941 +     * <i>narrowing primitive conversion</i> from {@code double} to
162.2942 +     * {@code short} as defined in section 5.1.3 of
162.2943 +     * <cite>The Java&trade; Language Specification</cite>:
162.2944 +     * any fractional part of this
162.2945 +     * {@code BigDecimal} will be discarded, and if the resulting
162.2946 +     * "{@code BigInteger}" is too big to fit in a
162.2947 +     * {@code long}, only the low-order 64 bits are returned.
162.2948 +     * Note that this conversion can lose information about the
162.2949 +     * overall magnitude and precision of this {@code BigDecimal} value as well
162.2950 +     * as return a result with the opposite sign.
162.2951 +     *
162.2952 +     * @return this {@code BigDecimal} converted to a {@code long}.
162.2953 +     */
162.2954 +    public long longValue(){
162.2955 +        return (intCompact != INFLATED && scale == 0) ?
162.2956 +            intCompact:
162.2957 +            toBigInteger().longValue();
162.2958 +    }
162.2959 +
162.2960 +    /**
162.2961 +     * Converts this {@code BigDecimal} to a {@code long}, checking
162.2962 +     * for lost information.  If this {@code BigDecimal} has a
162.2963 +     * nonzero fractional part or is out of the possible range for a
162.2964 +     * {@code long} result then an {@code ArithmeticException} is
162.2965 +     * thrown.
162.2966 +     *
162.2967 +     * @return this {@code BigDecimal} converted to a {@code long}.
162.2968 +     * @throws ArithmeticException if {@code this} has a nonzero
162.2969 +     *         fractional part, or will not fit in a {@code long}.
162.2970 +     * @since  1.5
162.2971 +     */
162.2972 +    public long longValueExact() {
162.2973 +        if (intCompact != INFLATED && scale == 0)
162.2974 +            return intCompact;
162.2975 +        // If more than 19 digits in integer part it cannot possibly fit
162.2976 +        if ((precision() - scale) > 19) // [OK for negative scale too]
162.2977 +            throw new java.lang.ArithmeticException("Overflow");
162.2978 +        // Fastpath zero and < 1.0 numbers (the latter can be very slow
162.2979 +        // to round if very small)
162.2980 +        if (this.signum() == 0)
162.2981 +            return 0;
162.2982 +        if ((this.precision() - this.scale) <= 0)
162.2983 +            throw new ArithmeticException("Rounding necessary");
162.2984 +        // round to an integer, with Exception if decimal part non-0
162.2985 +        BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
162.2986 +        if (num.precision() >= 19) // need to check carefully
162.2987 +            LongOverflow.check(num);
162.2988 +        return num.inflate().longValue();
162.2989 +    }
162.2990 +
162.2991 +    private static class LongOverflow {
162.2992 +        /** BigInteger equal to Long.MIN_VALUE. */
162.2993 +        private static final BigInteger LONGMIN = BigInteger.valueOf(Long.MIN_VALUE);
162.2994 +
162.2995 +        /** BigInteger equal to Long.MAX_VALUE. */
162.2996 +        private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE);
162.2997 +
162.2998 +        public static void check(BigDecimal num) {
162.2999 +            num.inflate();
162.3000 +            if ((num.intVal.compareTo(LONGMIN) < 0) ||
162.3001 +                (num.intVal.compareTo(LONGMAX) > 0))
162.3002 +                throw new java.lang.ArithmeticException("Overflow");
162.3003 +        }
162.3004 +    }
162.3005 +
162.3006 +    /**
162.3007 +     * Converts this {@code BigDecimal} to an {@code int}.
162.3008 +     * This conversion is analogous to the
162.3009 +     * <i>narrowing primitive conversion</i> from {@code double} to
162.3010 +     * {@code short} as defined in section 5.1.3 of
162.3011 +     * <cite>The Java&trade; Language Specification</cite>:
162.3012 +     * any fractional part of this
162.3013 +     * {@code BigDecimal} will be discarded, and if the resulting
162.3014 +     * "{@code BigInteger}" is too big to fit in an
162.3015 +     * {@code int}, only the low-order 32 bits are returned.
162.3016 +     * Note that this conversion can lose information about the
162.3017 +     * overall magnitude and precision of this {@code BigDecimal}
162.3018 +     * value as well as return a result with the opposite sign.
162.3019 +     *
162.3020 +     * @return this {@code BigDecimal} converted to an {@code int}.
162.3021 +     */
162.3022 +    public int intValue() {
162.3023 +        return  (intCompact != INFLATED && scale == 0) ?
162.3024 +            (int)intCompact :
162.3025 +            toBigInteger().intValue();
162.3026 +    }
162.3027 +
162.3028 +    /**
162.3029 +     * Converts this {@code BigDecimal} to an {@code int}, checking
162.3030 +     * for lost information.  If this {@code BigDecimal} has a
162.3031 +     * nonzero fractional part or is out of the possible range for an
162.3032 +     * {@code int} result then an {@code ArithmeticException} is
162.3033 +     * thrown.
162.3034 +     *
162.3035 +     * @return this {@code BigDecimal} converted to an {@code int}.
162.3036 +     * @throws ArithmeticException if {@code this} has a nonzero
162.3037 +     *         fractional part, or will not fit in an {@code int}.
162.3038 +     * @since  1.5
162.3039 +     */
162.3040 +    public int intValueExact() {
162.3041 +       long num;
162.3042 +       num = this.longValueExact();     // will check decimal part
162.3043 +       if ((int)num != num)
162.3044 +           throw new java.lang.ArithmeticException("Overflow");
162.3045 +       return (int)num;
162.3046 +    }
162.3047 +
162.3048 +    /**
162.3049 +     * Converts this {@code BigDecimal} to a {@code short}, checking
162.3050 +     * for lost information.  If this {@code BigDecimal} has a
162.3051 +     * nonzero fractional part or is out of the possible range for a
162.3052 +     * {@code short} result then an {@code ArithmeticException} is
162.3053 +     * thrown.
162.3054 +     *
162.3055 +     * @return this {@code BigDecimal} converted to a {@code short}.
162.3056 +     * @throws ArithmeticException if {@code this} has a nonzero
162.3057 +     *         fractional part, or will not fit in a {@code short}.
162.3058 +     * @since  1.5
162.3059 +     */
162.3060 +    public short shortValueExact() {
162.3061 +       long num;
162.3062 +       num = this.longValueExact();     // will check decimal part
162.3063 +       if ((short)num != num)
162.3064 +           throw new java.lang.ArithmeticException("Overflow");
162.3065 +       return (short)num;
162.3066 +    }
162.3067 +
162.3068 +    /**
162.3069 +     * Converts this {@code BigDecimal} to a {@code byte}, checking
162.3070 +     * for lost information.  If this {@code BigDecimal} has a
162.3071 +     * nonzero fractional part or is out of the possible range for a
162.3072 +     * {@code byte} result then an {@code ArithmeticException} is
162.3073 +     * thrown.
162.3074 +     *
162.3075 +     * @return this {@code BigDecimal} converted to a {@code byte}.
162.3076 +     * @throws ArithmeticException if {@code this} has a nonzero
162.3077 +     *         fractional part, or will not fit in a {@code byte}.
162.3078 +     * @since  1.5
162.3079 +     */
162.3080 +    public byte byteValueExact() {
162.3081 +       long num;
162.3082 +       num = this.longValueExact();     // will check decimal part
162.3083 +       if ((byte)num != num)
162.3084 +           throw new java.lang.ArithmeticException("Overflow");
162.3085 +       return (byte)num;
162.3086 +    }
162.3087 +
162.3088 +    /**
162.3089 +     * Converts this {@code BigDecimal} to a {@code float}.
162.3090 +     * This conversion is similar to the
162.3091 +     * <i>narrowing primitive conversion</i> from {@code double} to
162.3092 +     * {@code float} as defined in section 5.1.3 of
162.3093 +     * <cite>The Java&trade; Language Specification</cite>:
162.3094 +     * if this {@code BigDecimal} has too great a
162.3095 +     * magnitude to represent as a {@code float}, it will be
162.3096 +     * converted to {@link Float#NEGATIVE_INFINITY} or {@link
162.3097 +     * Float#POSITIVE_INFINITY} as appropriate.  Note that even when
162.3098 +     * the return value is finite, this conversion can lose
162.3099 +     * information about the precision of the {@code BigDecimal}
162.3100 +     * value.
162.3101 +     *
162.3102 +     * @return this {@code BigDecimal} converted to a {@code float}.
162.3103 +     */
162.3104 +    public float floatValue(){
162.3105 +        if (scale == 0 && intCompact != INFLATED)
162.3106 +                return (float)intCompact;
162.3107 +        // Somewhat inefficient, but guaranteed to work.
162.3108 +        return Float.parseFloat(this.toString());
162.3109 +    }
162.3110 +
162.3111 +    /**
162.3112 +     * Converts this {@code BigDecimal} to a {@code double}.
162.3113 +     * This conversion is similar to the
162.3114 +     * <i>narrowing primitive conversion</i> from {@code double} to
162.3115 +     * {@code float} as defined in section 5.1.3 of
162.3116 +     * <cite>The Java&trade; Language Specification</cite>:
162.3117 +     * if this {@code BigDecimal} has too great a
162.3118 +     * magnitude represent as a {@code double}, it will be
162.3119 +     * converted to {@link Double#NEGATIVE_INFINITY} or {@link
162.3120 +     * Double#POSITIVE_INFINITY} as appropriate.  Note that even when
162.3121 +     * the return value is finite, this conversion can lose
162.3122 +     * information about the precision of the {@code BigDecimal}
162.3123 +     * value.
162.3124 +     *
162.3125 +     * @return this {@code BigDecimal} converted to a {@code double}.
162.3126 +     */
162.3127 +    public double doubleValue(){
162.3128 +        if (scale == 0 && intCompact != INFLATED)
162.3129 +            return (double)intCompact;
162.3130 +        // Somewhat inefficient, but guaranteed to work.
162.3131 +        return Double.parseDouble(this.toString());
162.3132 +    }
162.3133 +
162.3134 +    /**
162.3135 +     * Returns the size of an ulp, a unit in the last place, of this
162.3136 +     * {@code BigDecimal}.  An ulp of a nonzero {@code BigDecimal}
162.3137 +     * value is the positive distance between this value and the
162.3138 +     * {@code BigDecimal} value next larger in magnitude with the
162.3139 +     * same number of digits.  An ulp of a zero value is numerically
162.3140 +     * equal to 1 with the scale of {@code this}.  The result is
162.3141 +     * stored with the same scale as {@code this} so the result
162.3142 +     * for zero and nonzero values is equal to {@code [1,
162.3143 +     * this.scale()]}.
162.3144 +     *
162.3145 +     * @return the size of an ulp of {@code this}
162.3146 +     * @since 1.5
162.3147 +     */
162.3148 +    public BigDecimal ulp() {
162.3149 +        return BigDecimal.valueOf(1, this.scale());
162.3150 +    }
162.3151 +
162.3152 +
162.3153 +    // Private class to build a string representation for BigDecimal object.
162.3154 +    // "StringBuilderHelper" is constructed as a thread local variable so it is
162.3155 +    // thread safe. The StringBuilder field acts as a buffer to hold the temporary
162.3156 +    // representation of BigDecimal. The cmpCharArray holds all the characters for
162.3157 +    // the compact representation of BigDecimal (except for '-' sign' if it is
162.3158 +    // negative) if its intCompact field is not INFLATED. It is shared by all
162.3159 +    // calls to toString() and its variants in that particular thread.
162.3160 +    static class StringBuilderHelper {
162.3161 +        private static StringBuilderHelper INSTANCE = new StringBuilderHelper();
162.3162 +        final StringBuilder sb;    // Placeholder for BigDecimal string
162.3163 +        final char[] cmpCharArray; // character array to place the intCompact
162.3164 +
162.3165 +        StringBuilderHelper() {
162.3166 +            sb = new StringBuilder();
162.3167 +            // All non negative longs can be made to fit into 19 character array.
162.3168 +            cmpCharArray = new char[19];
162.3169 +        }
162.3170 +
162.3171 +        // Accessors.
162.3172 +        StringBuilder getStringBuilder() {
162.3173 +            sb.setLength(0);
162.3174 +            return sb;
162.3175 +        }
162.3176 +
162.3177 +        char[] getCompactCharArray() {
162.3178 +            return cmpCharArray;
162.3179 +        }
162.3180 +
162.3181 +        /**
162.3182 +         * Places characters representing the intCompact in {@code long} into
162.3183 +         * cmpCharArray and returns the offset to the array where the
162.3184 +         * representation starts.
162.3185 +         *
162.3186 +         * @param intCompact the number to put into the cmpCharArray.
162.3187 +         * @return offset to the array where the representation starts.
162.3188 +         * Note: intCompact must be greater or equal to zero.
162.3189 +         */
162.3190 +        int putIntCompact(long intCompact) {
162.3191 +            assert intCompact >= 0;
162.3192 +
162.3193 +            long q;
162.3194 +            int r;
162.3195 +            // since we start from the least significant digit, charPos points to
162.3196 +            // the last character in cmpCharArray.
162.3197 +            int charPos = cmpCharArray.length;
162.3198 +
162.3199 +            // Get 2 digits/iteration using longs until quotient fits into an int
162.3200 +            while (intCompact > Integer.MAX_VALUE) {
162.3201 +                q = intCompact / 100;
162.3202 +                r = (int)(intCompact - q * 100);
162.3203 +                intCompact = q;
162.3204 +                cmpCharArray[--charPos] = DIGIT_ONES[r];
162.3205 +                cmpCharArray[--charPos] = DIGIT_TENS[r];
162.3206 +            }
162.3207 +
162.3208 +            // Get 2 digits/iteration using ints when i2 >= 100
162.3209 +            int q2;
162.3210 +            int i2 = (int)intCompact;
162.3211 +            while (i2 >= 100) {
162.3212 +                q2 = i2 / 100;
162.3213 +                r  = i2 - q2 * 100;
162.3214 +                i2 = q2;
162.3215 +                cmpCharArray[--charPos] = DIGIT_ONES[r];
162.3216 +                cmpCharArray[--charPos] = DIGIT_TENS[r];
162.3217 +            }
162.3218 +
162.3219 +            cmpCharArray[--charPos] = DIGIT_ONES[i2];
162.3220 +            if (i2 >= 10)
162.3221 +                cmpCharArray[--charPos] = DIGIT_TENS[i2];
162.3222 +
162.3223 +            return charPos;
162.3224 +        }
162.3225 +
162.3226 +        final static char[] DIGIT_TENS = {
162.3227 +            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
162.3228 +            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
162.3229 +            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
162.3230 +            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
162.3231 +            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
162.3232 +            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
162.3233 +            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
162.3234 +            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
162.3235 +            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
162.3236 +            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
162.3237 +        };
162.3238 +
162.3239 +        final static char[] DIGIT_ONES = {
162.3240 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3241 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3242 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3243 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3244 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3245 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3246 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3247 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3248 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3249 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
162.3250 +        };
162.3251 +    }
162.3252 +
162.3253 +    /**
162.3254 +     * Lay out this {@code BigDecimal} into a {@code char[]} array.
162.3255 +     * The Java 1.2 equivalent to this was called {@code getValueString}.
162.3256 +     *
162.3257 +     * @param  sci {@code true} for Scientific exponential notation;
162.3258 +     *          {@code false} for Engineering
162.3259 +     * @return string with canonical string representation of this
162.3260 +     *         {@code BigDecimal}
162.3261 +     */
162.3262 +    private String layoutChars(boolean sci) {
162.3263 +        if (scale == 0)                      // zero scale is trivial
162.3264 +            return (intCompact != INFLATED) ?
162.3265 +                Long.toString(intCompact):
162.3266 +                intVal.toString();
162.3267 +
162.3268 +        StringBuilderHelper sbHelper = StringBuilderHelper.INSTANCE;
162.3269 +        char[] coeff;
162.3270 +        int offset;  // offset is the starting index for coeff array
162.3271 +        // Get the significand as an absolute value
162.3272 +        if (intCompact != INFLATED) {
162.3273 +            offset = sbHelper.putIntCompact(Math.abs(intCompact));
162.3274 +            coeff  = sbHelper.getCompactCharArray();
162.3275 +        } else {
162.3276 +            offset = 0;
162.3277 +            coeff  = intVal.abs().toString().toCharArray();
162.3278 +        }
162.3279 +
162.3280 +        // Construct a buffer, with sufficient capacity for all cases.
162.3281 +        // If E-notation is needed, length will be: +1 if negative, +1
162.3282 +        // if '.' needed, +2 for "E+", + up to 10 for adjusted exponent.
162.3283 +        // Otherwise it could have +1 if negative, plus leading "0.00000"
162.3284 +        StringBuilder buf = sbHelper.getStringBuilder();
162.3285 +        if (signum() < 0)             // prefix '-' if negative
162.3286 +            buf.append('-');
162.3287 +        int coeffLen = coeff.length - offset;
162.3288 +        long adjusted = -(long)scale + (coeffLen -1);
162.3289 +        if ((scale >= 0) && (adjusted >= -6)) { // plain number
162.3290 +            int pad = scale - coeffLen;         // count of padding zeros
162.3291 +            if (pad >= 0) {                     // 0.xxx form
162.3292 +                buf.append('0');
162.3293 +                buf.append('.');
162.3294 +                for (; pad>0; pad--) {
162.3295 +                    buf.append('0');
162.3296 +                }
162.3297 +                buf.append(coeff, offset, coeffLen);
162.3298 +            } else {                         // xx.xx form
162.3299 +                buf.append(coeff, offset, -pad);
162.3300 +                buf.append('.');
162.3301 +                buf.append(coeff, -pad + offset, scale);
162.3302 +            }
162.3303 +        } else { // E-notation is needed
162.3304 +            if (sci) {                       // Scientific notation
162.3305 +                buf.append(coeff[offset]);   // first character
162.3306 +                if (coeffLen > 1) {          // more to come
162.3307 +                    buf.append('.');
162.3308 +                    buf.append(coeff, offset + 1, coeffLen - 1);
162.3309 +                }
162.3310 +            } else {                         // Engineering notation
162.3311 +                int sig = (int)(adjusted % 3);
162.3312 +                if (sig < 0)
162.3313 +                    sig += 3;                // [adjusted was negative]
162.3314 +                adjusted -= sig;             // now a multiple of 3
162.3315 +                sig++;
162.3316 +                if (signum() == 0) {
162.3317 +                    switch (sig) {
162.3318 +                    case 1:
162.3319 +                        buf.append('0'); // exponent is a multiple of three
162.3320 +                        break;
162.3321 +                    case 2:
162.3322 +                        buf.append("0.00");
162.3323 +                        adjusted += 3;
162.3324 +                        break;
162.3325 +                    case 3:
162.3326 +                        buf.append("0.0");
162.3327 +                        adjusted += 3;
162.3328 +                        break;
162.3329 +                    default:
162.3330 +                        throw new AssertionError("Unexpected sig value " + sig);
162.3331 +                    }
162.3332 +                } else if (sig >= coeffLen) {   // significand all in integer
162.3333 +                    buf.append(coeff, offset, coeffLen);
162.3334 +                    // may need some zeros, too
162.3335 +                    for (int i = sig - coeffLen; i > 0; i--)
162.3336 +                        buf.append('0');
162.3337 +                } else {                     // xx.xxE form
162.3338 +                    buf.append(coeff, offset, sig);
162.3339 +                    buf.append('.');
162.3340 +                    buf.append(coeff, offset + sig, coeffLen - sig);
162.3341 +                }
162.3342 +            }
162.3343 +            if (adjusted != 0) {             // [!sci could have made 0]
162.3344 +                buf.append('E');
162.3345 +                if (adjusted > 0)            // force sign for positive
162.3346 +                    buf.append('+');
162.3347 +                buf.append(adjusted);
162.3348 +            }
162.3349 +        }
162.3350 +        return buf.toString();
162.3351 +    }
162.3352 +
162.3353 +    /**
162.3354 +     * Return 10 to the power n, as a {@code BigInteger}.
162.3355 +     *
162.3356 +     * @param  n the power of ten to be returned (>=0)
162.3357 +     * @return a {@code BigInteger} with the value (10<sup>n</sup>)
162.3358 +     */
162.3359 +    private static BigInteger bigTenToThe(int n) {
162.3360 +        if (n < 0)
162.3361 +            return BigInteger.ZERO;
162.3362 +
162.3363 +        if (n < BIG_TEN_POWERS_TABLE_MAX) {
162.3364 +            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
162.3365 +            if (n < pows.length)
162.3366 +                return pows[n];
162.3367 +            else
162.3368 +                return expandBigIntegerTenPowers(n);
162.3369 +        }
162.3370 +        // BigInteger.pow is slow, so make 10**n by constructing a
162.3371 +        // BigInteger from a character string (still not very fast)
162.3372 +        char tenpow[] = new char[n + 1];
162.3373 +        tenpow[0] = '1';
162.3374 +        for (int i = 1; i <= n; i++)
162.3375 +            tenpow[i] = '0';
162.3376 +        return new BigInteger(tenpow);
162.3377 +    }
162.3378 +
162.3379 +    /**
162.3380 +     * Expand the BIG_TEN_POWERS_TABLE array to contain at least 10**n.
162.3381 +     *
162.3382 +     * @param n the power of ten to be returned (>=0)
162.3383 +     * @return a {@code BigDecimal} with the value (10<sup>n</sup>) and
162.3384 +     *         in the meantime, the BIG_TEN_POWERS_TABLE array gets
162.3385 +     *         expanded to the size greater than n.
162.3386 +     */
162.3387 +    private static BigInteger expandBigIntegerTenPowers(int n) {
162.3388 +        synchronized(BigDecimal.class) {
162.3389 +            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
162.3390 +            int curLen = pows.length;
162.3391 +            // The following comparison and the above synchronized statement is
162.3392 +            // to prevent multiple threads from expanding the same array.
162.3393 +            if (curLen <= n) {
162.3394 +                int newLen = curLen << 1;
162.3395 +                while (newLen <= n)
162.3396 +                    newLen <<= 1;
162.3397 +                pows = Arrays.copyOf(pows, newLen);
162.3398 +                for (int i = curLen; i < newLen; i++)
162.3399 +                    pows[i] = pows[i - 1].multiply(BigInteger.TEN);
162.3400 +                // Based on the following facts:
162.3401 +                // 1. pows is a private local varible;
162.3402 +                // 2. the following store is a volatile store.
162.3403 +                // the newly created array elements can be safely published.
162.3404 +                BIG_TEN_POWERS_TABLE = pows;
162.3405 +            }
162.3406 +            return pows[n];
162.3407 +        }
162.3408 +    }
162.3409 +
162.3410 +    private static final long[] LONG_TEN_POWERS_TABLE = {
162.3411 +        1,                     // 0 / 10^0
162.3412 +        10,                    // 1 / 10^1
162.3413 +        100,                   // 2 / 10^2
162.3414 +        1000,                  // 3 / 10^3
162.3415 +        10000,                 // 4 / 10^4
162.3416 +        100000,                // 5 / 10^5
162.3417 +        1000000,               // 6 / 10^6
162.3418 +        10000000,              // 7 / 10^7
162.3419 +        100000000,             // 8 / 10^8
162.3420 +        1000000000,            // 9 / 10^9
162.3421 +        10000000000L,          // 10 / 10^10
162.3422 +        100000000000L,         // 11 / 10^11
162.3423 +        1000000000000L,        // 12 / 10^12
162.3424 +        10000000000000L,       // 13 / 10^13
162.3425 +        100000000000000L,      // 14 / 10^14
162.3426 +        1000000000000000L,     // 15 / 10^15
162.3427 +        10000000000000000L,    // 16 / 10^16
162.3428 +        100000000000000000L,   // 17 / 10^17
162.3429 +        1000000000000000000L   // 18 / 10^18
162.3430 +    };
162.3431 +
162.3432 +    private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {BigInteger.ONE,
162.3433 +        BigInteger.valueOf(10),       BigInteger.valueOf(100),
162.3434 +        BigInteger.valueOf(1000),     BigInteger.valueOf(10000),
162.3435 +        BigInteger.valueOf(100000),   BigInteger.valueOf(1000000),
162.3436 +        BigInteger.valueOf(10000000), BigInteger.valueOf(100000000),
162.3437 +        BigInteger.valueOf(1000000000),
162.3438 +        BigInteger.valueOf(10000000000L),
162.3439 +        BigInteger.valueOf(100000000000L),
162.3440 +        BigInteger.valueOf(1000000000000L),
162.3441 +        BigInteger.valueOf(10000000000000L),
162.3442 +        BigInteger.valueOf(100000000000000L),
162.3443 +        BigInteger.valueOf(1000000000000000L),
162.3444 +        BigInteger.valueOf(10000000000000000L),
162.3445 +        BigInteger.valueOf(100000000000000000L),
162.3446 +        BigInteger.valueOf(1000000000000000000L)
162.3447 +    };
162.3448 +
162.3449 +    private static final int BIG_TEN_POWERS_TABLE_INITLEN =
162.3450 +        BIG_TEN_POWERS_TABLE.length;
162.3451 +    private static final int BIG_TEN_POWERS_TABLE_MAX =
162.3452 +        16 * BIG_TEN_POWERS_TABLE_INITLEN;
162.3453 +
162.3454 +    private static final long THRESHOLDS_TABLE[] = {
162.3455 +        Long.MAX_VALUE,                     // 0
162.3456 +        Long.MAX_VALUE/10L,                 // 1
162.3457 +        Long.MAX_VALUE/100L,                // 2
162.3458 +        Long.MAX_VALUE/1000L,               // 3
162.3459 +        Long.MAX_VALUE/10000L,              // 4
162.3460 +        Long.MAX_VALUE/100000L,             // 5
162.3461 +        Long.MAX_VALUE/1000000L,            // 6
162.3462 +        Long.MAX_VALUE/10000000L,           // 7
162.3463 +        Long.MAX_VALUE/100000000L,          // 8
162.3464 +        Long.MAX_VALUE/1000000000L,         // 9
162.3465 +        Long.MAX_VALUE/10000000000L,        // 10
162.3466 +        Long.MAX_VALUE/100000000000L,       // 11
162.3467 +        Long.MAX_VALUE/1000000000000L,      // 12
162.3468 +        Long.MAX_VALUE/10000000000000L,     // 13
162.3469 +        Long.MAX_VALUE/100000000000000L,    // 14
162.3470 +        Long.MAX_VALUE/1000000000000000L,   // 15
162.3471 +        Long.MAX_VALUE/10000000000000000L,  // 16
162.3472 +        Long.MAX_VALUE/100000000000000000L, // 17
162.3473 +        Long.MAX_VALUE/1000000000000000000L // 18
162.3474 +    };
162.3475 +
162.3476 +    /**
162.3477 +     * Compute val * 10 ^ n; return this product if it is
162.3478 +     * representable as a long, INFLATED otherwise.
162.3479 +     */
162.3480 +    private static long longMultiplyPowerTen(long val, int n) {
162.3481 +        if (val == 0 || n <= 0)
162.3482 +            return val;
162.3483 +        long[] tab = LONG_TEN_POWERS_TABLE;
162.3484 +        long[] bounds = THRESHOLDS_TABLE;
162.3485 +        if (n < tab.length && n < bounds.length) {
162.3486 +            long tenpower = tab[n];
162.3487 +            if (val == 1)
162.3488 +                return tenpower;
162.3489 +            if (Math.abs(val) <= bounds[n])
162.3490 +                return val * tenpower;
162.3491 +        }
162.3492 +        return INFLATED;
162.3493 +    }
162.3494 +
162.3495 +    /**
162.3496 +     * Compute this * 10 ^ n.
162.3497 +     * Needed mainly to allow special casing to trap zero value
162.3498 +     */
162.3499 +    private BigInteger bigMultiplyPowerTen(int n) {
162.3500 +        if (n <= 0)
162.3501 +            return this.inflate();
162.3502 +
162.3503 +        if (intCompact != INFLATED)
162.3504 +            return bigTenToThe(n).multiply(intCompact);
162.3505 +        else
162.3506 +            return intVal.multiply(bigTenToThe(n));
162.3507 +    }
162.3508 +
162.3509 +    /**
162.3510 +     * Assign appropriate BigInteger to intVal field if intVal is
162.3511 +     * null, i.e. the compact representation is in use.
162.3512 +     */
162.3513 +    private BigInteger inflate() {
162.3514 +        if (intVal == null)
162.3515 +            intVal = BigInteger.valueOf(intCompact);
162.3516 +        return intVal;
162.3517 +    }
162.3518 +
162.3519 +    /**
162.3520 +     * Match the scales of two {@code BigDecimal}s to align their
162.3521 +     * least significant digits.
162.3522 +     *
162.3523 +     * <p>If the scales of val[0] and val[1] differ, rescale
162.3524 +     * (non-destructively) the lower-scaled {@code BigDecimal} so
162.3525 +     * they match.  That is, the lower-scaled reference will be
162.3526 +     * replaced by a reference to a new object with the same scale as
162.3527 +     * the other {@code BigDecimal}.
162.3528 +     *
162.3529 +     * @param  val array of two elements referring to the two
162.3530 +     *         {@code BigDecimal}s to be aligned.
162.3531 +     */
162.3532 +    private static void matchScale(BigDecimal[] val) {
162.3533 +        if (val[0].scale == val[1].scale) {
162.3534 +            return;
162.3535 +        } else if (val[0].scale < val[1].scale) {
162.3536 +            val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
162.3537 +        } else if (val[1].scale < val[0].scale) {
162.3538 +            val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
162.3539 +        }
162.3540 +    }
162.3541 +
162.3542 +    /**
162.3543 +     * Reconstitute the {@code BigDecimal} instance from a stream (that is,
162.3544 +     * deserialize it).
162.3545 +     *
162.3546 +     * @param s the stream being read.
162.3547 +     */
162.3548 +    private void readObject(java.io.ObjectInputStream s)
162.3549 +        throws java.io.IOException, ClassNotFoundException {
162.3550 +        // Read in all fields
162.3551 +        s.defaultReadObject();
162.3552 +        // validate possibly bad fields
162.3553 +        if (intVal == null) {
162.3554 +            String message = "BigDecimal: null intVal in stream";
162.3555 +            throw new java.io.StreamCorruptedException(message);
162.3556 +        // [all values of scale are now allowed]
162.3557 +        }
162.3558 +        intCompact = compactValFor(intVal);
162.3559 +    }
162.3560 +
162.3561 +   /**
162.3562 +    * Serialize this {@code BigDecimal} to the stream in question
162.3563 +    *
162.3564 +    * @param s the stream to serialize to.
162.3565 +    */
162.3566 +   private void writeObject(java.io.ObjectOutputStream s)
162.3567 +       throws java.io.IOException {
162.3568 +       // Must inflate to maintain compatible serial form.
162.3569 +       this.inflate();
162.3570 +
162.3571 +       // Write proper fields
162.3572 +       s.defaultWriteObject();
162.3573 +   }
162.3574 +
162.3575 +
162.3576 +    /**
162.3577 +     * Returns the length of the absolute value of a {@code long}, in decimal
162.3578 +     * digits.
162.3579 +     *
162.3580 +     * @param x the {@code long}
162.3581 +     * @return the length of the unscaled value, in deciaml digits.
162.3582 +     */
162.3583 +    private static int longDigitLength(long x) {
162.3584 +        /*
162.3585 +         * As described in "Bit Twiddling Hacks" by Sean Anderson,
162.3586 +         * (http://graphics.stanford.edu/~seander/bithacks.html)
162.3587 +         * integer log 10 of x is within 1 of
162.3588 +         * (1233/4096)* (1 + integer log 2 of x).
162.3589 +         * The fraction 1233/4096 approximates log10(2). So we first
162.3590 +         * do a version of log2 (a variant of Long class with
162.3591 +         * pre-checks and opposite directionality) and then scale and
162.3592 +         * check against powers table. This is a little simpler in
162.3593 +         * present context than the version in Hacker's Delight sec
162.3594 +         * 11-4.  Adding one to bit length allows comparing downward
162.3595 +         * from the LONG_TEN_POWERS_TABLE that we need anyway.
162.3596 +         */
162.3597 +        assert x != INFLATED;
162.3598 +        if (x < 0)
162.3599 +            x = -x;
162.3600 +        if (x < 10) // must screen for 0, might as well 10
162.3601 +            return 1;
162.3602 +        int n = 64; // not 63, to avoid needing to add 1 later
162.3603 +        int y = (int)(x >>> 32);
162.3604 +        if (y == 0) { n -= 32; y = (int)x; }
162.3605 +        if (y >>> 16 == 0) { n -= 16; y <<= 16; }
162.3606 +        if (y >>> 24 == 0) { n -=  8; y <<=  8; }
162.3607 +        if (y >>> 28 == 0) { n -=  4; y <<=  4; }
162.3608 +        if (y >>> 30 == 0) { n -=  2; y <<=  2; }
162.3609 +        int r = (((y >>> 31) + n) * 1233) >>> 12;
162.3610 +        long[] tab = LONG_TEN_POWERS_TABLE;
162.3611 +        // if r >= length, must have max possible digits for long
162.3612 +        return (r >= tab.length || x < tab[r])? r : r+1;
162.3613 +    }
162.3614 +
162.3615 +    /**
162.3616 +     * Returns the length of the absolute value of a BigInteger, in
162.3617 +     * decimal digits.
162.3618 +     *
162.3619 +     * @param b the BigInteger
162.3620 +     * @return the length of the unscaled value, in decimal digits
162.3621 +     */
162.3622 +    private static int bigDigitLength(BigInteger b) {
162.3623 +        /*
162.3624 +         * Same idea as the long version, but we need a better
162.3625 +         * approximation of log10(2). Using 646456993/2^31
162.3626 +         * is accurate up to max possible reported bitLength.
162.3627 +         */
162.3628 +        if (b.signum == 0)
162.3629 +            return 1;
162.3630 +        int r = (int)((((long)b.bitLength() + 1) * 646456993) >>> 31);
162.3631 +        return b.compareMagnitude(bigTenToThe(r)) < 0? r : r+1;
162.3632 +    }
162.3633 +
162.3634 +
162.3635 +    /**
162.3636 +     * Remove insignificant trailing zeros from this
162.3637 +     * {@code BigDecimal} until the preferred scale is reached or no
162.3638 +     * more zeros can be removed.  If the preferred scale is less than
162.3639 +     * Integer.MIN_VALUE, all the trailing zeros will be removed.
162.3640 +     *
162.3641 +     * {@code BigInteger} assistance could help, here?
162.3642 +     *
162.3643 +     * <p>WARNING: This method should only be called on new objects as
162.3644 +     * it mutates the value fields.
162.3645 +     *
162.3646 +     * @return this {@code BigDecimal} with a scale possibly reduced
162.3647 +     * to be closed to the preferred scale.
162.3648 +     */
162.3649 +    private BigDecimal stripZerosToMatchScale(long preferredScale) {
162.3650 +        this.inflate();
162.3651 +        BigInteger qr[];                // quotient-remainder pair
162.3652 +        while ( intVal.compareMagnitude(BigInteger.TEN) >= 0 &&
162.3653 +                scale > preferredScale) {
162.3654 +            if (intVal.testBit(0))
162.3655 +                break;                  // odd number cannot end in 0
162.3656 +            qr = intVal.divideAndRemainder(BigInteger.TEN);
162.3657 +            if (qr[1].signum() != 0)
162.3658 +                break;                  // non-0 remainder
162.3659 +            intVal=qr[0];
162.3660 +            scale = checkScale((long)scale-1);  // could Overflow
162.3661 +            if (precision > 0)          // adjust precision if known
162.3662 +              precision--;
162.3663 +        }
162.3664 +        if (intVal != null)
162.3665 +            intCompact = compactValFor(intVal);
162.3666 +        return this;
162.3667 +    }
162.3668 +
162.3669 +    /**
162.3670 +     * Check a scale for Underflow or Overflow.  If this BigDecimal is
162.3671 +     * nonzero, throw an exception if the scale is outof range. If this
162.3672 +     * is zero, saturate the scale to the extreme value of the right
162.3673 +     * sign if the scale is out of range.
162.3674 +     *
162.3675 +     * @param val The new scale.
162.3676 +     * @throws ArithmeticException (overflow or underflow) if the new
162.3677 +     *         scale is out of range.
162.3678 +     * @return validated scale as an int.
162.3679 +     */
162.3680 +    private int checkScale(long val) {
162.3681 +        int asInt = (int)val;
162.3682 +        if (asInt != val) {
162.3683 +            asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
162.3684 +            BigInteger b;
162.3685 +            if (intCompact != 0 &&
162.3686 +                ((b = intVal) == null || b.signum() != 0))
162.3687 +                throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
162.3688 +        }
162.3689 +        return asInt;
162.3690 +    }
162.3691 +
162.3692 +    /**
162.3693 +     * Round an operand; used only if digits &gt; 0.  Does not change
162.3694 +     * {@code this}; if rounding is needed a new {@code BigDecimal}
162.3695 +     * is created and returned.
162.3696 +     *
162.3697 +     * @param mc the context to use.
162.3698 +     * @throws ArithmeticException if the result is inexact but the
162.3699 +     *         rounding mode is {@code UNNECESSARY}.
162.3700 +     */
162.3701 +    private BigDecimal roundOp(MathContext mc) {
162.3702 +        BigDecimal rounded = doRound(this, mc);
162.3703 +        return rounded;
162.3704 +    }
162.3705 +
162.3706 +    /** Round this BigDecimal according to the MathContext settings;
162.3707 +     *  used only if precision {@literal >} 0.
162.3708 +     *
162.3709 +     * <p>WARNING: This method should only be called on new objects as
162.3710 +     * it mutates the value fields.
162.3711 +     *
162.3712 +     * @param mc the context to use.
162.3713 +     * @throws ArithmeticException if the rounding mode is
162.3714 +     *         {@code RoundingMode.UNNECESSARY} and the
162.3715 +     *         {@code BigDecimal} operation would require rounding.
162.3716 +     */
162.3717 +    private void roundThis(MathContext mc) {
162.3718 +        BigDecimal rounded = doRound(this, mc);
162.3719 +        if (rounded == this)                 // wasn't rounded
162.3720 +            return;
162.3721 +        this.intVal     = rounded.intVal;
162.3722 +        this.intCompact = rounded.intCompact;
162.3723 +        this.scale      = rounded.scale;
162.3724 +        this.precision  = rounded.precision;
162.3725 +    }
162.3726 +
162.3727 +    /**
162.3728 +     * Returns a {@code BigDecimal} rounded according to the
162.3729 +     * MathContext settings; used only if {@code mc.precision > 0}.
162.3730 +     * Does not change {@code this}; if rounding is needed a new
162.3731 +     * {@code BigDecimal} is created and returned.
162.3732 +     *
162.3733 +     * @param mc the context to use.
162.3734 +     * @return a {@code BigDecimal} rounded according to the MathContext
162.3735 +     *         settings.  May return this, if no rounding needed.
162.3736 +     * @throws ArithmeticException if the rounding mode is
162.3737 +     *         {@code RoundingMode.UNNECESSARY} and the
162.3738 +     *         result is inexact.
162.3739 +     */
162.3740 +    private static BigDecimal doRound(BigDecimal d, MathContext mc) {
162.3741 +        int mcp = mc.precision;
162.3742 +        int drop;
162.3743 +        // This might (rarely) iterate to cover the 999=>1000 case
162.3744 +        while ((drop = d.precision() - mcp) > 0) {
162.3745 +            int newScale = d.checkScale((long)d.scale - drop);
162.3746 +            int mode = mc.roundingMode.oldMode;
162.3747 +            if (drop < LONG_TEN_POWERS_TABLE.length)
162.3748 +                d = divideAndRound(d.intCompact, d.intVal,
162.3749 +                                   LONG_TEN_POWERS_TABLE[drop], null,
162.3750 +                                   newScale, mode, newScale);
162.3751 +            else
162.3752 +                d = divideAndRound(d.intCompact, d.intVal,
162.3753 +                                   INFLATED, bigTenToThe(drop),
162.3754 +                                   newScale, mode, newScale);
162.3755 +        }
162.3756 +        return d;
162.3757 +    }
162.3758 +
162.3759 +    /**
162.3760 +     * Returns the compact value for given {@code BigInteger}, or
162.3761 +     * INFLATED if too big. Relies on internal representation of
162.3762 +     * {@code BigInteger}.
162.3763 +     */
162.3764 +    private static long compactValFor(BigInteger b) {
162.3765 +        int[] m = b.mag;
162.3766 +        int len = m.length;
162.3767 +        if (len == 0)
162.3768 +            return 0;
162.3769 +        int d = m[0];
162.3770 +        if (len > 2 || (len == 2 && d < 0))
162.3771 +            return INFLATED;
162.3772 +
162.3773 +        long u = (len == 2)?
162.3774 +            (((long) m[1] & LONG_MASK) + (((long)d) << 32)) :
162.3775 +            (((long)d)   & LONG_MASK);
162.3776 +        return (b.signum < 0)? -u : u;
162.3777 +    }
162.3778 +
162.3779 +    private static int longCompareMagnitude(long x, long y) {
162.3780 +        if (x < 0)
162.3781 +            x = -x;
162.3782 +        if (y < 0)
162.3783 +            y = -y;
162.3784 +        return (x < y) ? -1 : ((x == y) ? 0 : 1);
162.3785 +    }
162.3786 +
162.3787 +    private static int saturateLong(long s) {
162.3788 +        int i = (int)s;
162.3789 +        return (s == i) ? i : (s < 0 ? Integer.MIN_VALUE : Integer.MAX_VALUE);
162.3790 +    }
162.3791 +
162.3792 +    /*
162.3793 +     * Internal printing routine
162.3794 +     */
162.3795 +    private static void print(String name, BigDecimal bd) {
162.3796 +    }
162.3797 +
162.3798 +    /**
162.3799 +     * Check internal invariants of this BigDecimal.  These invariants
162.3800 +     * include:
162.3801 +     *
162.3802 +     * <ul>
162.3803 +     *
162.3804 +     * <li>The object must be initialized; either intCompact must not be
162.3805 +     * INFLATED or intVal is non-null.  Both of these conditions may
162.3806 +     * be true.
162.3807 +     *
162.3808 +     * <li>If both intCompact and intVal and set, their values must be
162.3809 +     * consistent.
162.3810 +     *
162.3811 +     * <li>If precision is nonzero, it must have the right value.
162.3812 +     * </ul>
162.3813 +     *
162.3814 +     * Note: Since this is an audit method, we are not supposed to change the
162.3815 +     * state of this BigDecimal object.
162.3816 +     */
162.3817 +    private BigDecimal audit() {
162.3818 +        if (intCompact == INFLATED) {
162.3819 +            if (intVal == null) {
162.3820 +                print("audit", this);
162.3821 +                throw new AssertionError("null intVal");
162.3822 +            }
162.3823 +            // Check precision
162.3824 +            if (precision > 0 && precision != bigDigitLength(intVal)) {
162.3825 +                print("audit", this);
162.3826 +                throw new AssertionError("precision mismatch");
162.3827 +            }
162.3828 +        } else {
162.3829 +            if (intVal != null) {
162.3830 +                long val = intVal.longValue();
162.3831 +                if (val != intCompact) {
162.3832 +                    print("audit", this);
162.3833 +                    throw new AssertionError("Inconsistent state, intCompact=" +
162.3834 +                                             intCompact + "\t intVal=" + val);
162.3835 +                }
162.3836 +            }
162.3837 +            // Check precision
162.3838 +            if (precision > 0 && precision != longDigitLength(intCompact)) {
162.3839 +                print("audit", this);
162.3840 +                throw new AssertionError("precision mismatch");
162.3841 +            }
162.3842 +        }
162.3843 +        return this;
162.3844 +    }
162.3845 +}
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/rt/emul/compact/src/main/java/java/math/BigInteger.java	Wed Apr 30 15:04:10 2014 +0200
   163.3 @@ -0,0 +1,3122 @@
   163.4 +/*
   163.5 + * Copyright (c) 1996, 2007, 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 +/*
  163.30 + * Portions Copyright (c) 1995  Colin Plumb.  All rights reserved.
  163.31 + */
  163.32 +
  163.33 +package java.math;
  163.34 +
  163.35 +import java.util.Random;
  163.36 +import java.io.*;
  163.37 +
  163.38 +/**
  163.39 + * Immutable arbitrary-precision integers.  All operations behave as if
  163.40 + * BigIntegers were represented in two's-complement notation (like Java's
  163.41 + * primitive integer types).  BigInteger provides analogues to all of Java's
  163.42 + * primitive integer operators, and all relevant methods from java.lang.Math.
  163.43 + * Additionally, BigInteger provides operations for modular arithmetic, GCD
  163.44 + * calculation, primality testing, prime generation, bit manipulation,
  163.45 + * and a few other miscellaneous operations.
  163.46 + *
  163.47 + * <p>Semantics of arithmetic operations exactly mimic those of Java's integer
  163.48 + * arithmetic operators, as defined in <i>The Java Language Specification</i>.
  163.49 + * For example, division by zero throws an {@code ArithmeticException}, and
  163.50 + * division of a negative by a positive yields a negative (or zero) remainder.
  163.51 + * All of the details in the Spec concerning overflow are ignored, as
  163.52 + * BigIntegers are made as large as necessary to accommodate the results of an
  163.53 + * operation.
  163.54 + *
  163.55 + * <p>Semantics of shift operations extend those of Java's shift operators
  163.56 + * to allow for negative shift distances.  A right-shift with a negative
  163.57 + * shift distance results in a left shift, and vice-versa.  The unsigned
  163.58 + * right shift operator ({@code >>>}) is omitted, as this operation makes
  163.59 + * little sense in combination with the "infinite word size" abstraction
  163.60 + * provided by this class.
  163.61 + *
  163.62 + * <p>Semantics of bitwise logical operations exactly mimic those of Java's
  163.63 + * bitwise integer operators.  The binary operators ({@code and},
  163.64 + * {@code or}, {@code xor}) implicitly perform sign extension on the shorter
  163.65 + * of the two operands prior to performing the operation.
  163.66 + *
  163.67 + * <p>Comparison operations perform signed integer comparisons, analogous to
  163.68 + * those performed by Java's relational and equality operators.
  163.69 + *
  163.70 + * <p>Modular arithmetic operations are provided to compute residues, perform
  163.71 + * exponentiation, and compute multiplicative inverses.  These methods always
  163.72 + * return a non-negative result, between {@code 0} and {@code (modulus - 1)},
  163.73 + * inclusive.
  163.74 + *
  163.75 + * <p>Bit operations operate on a single bit of the two's-complement
  163.76 + * representation of their operand.  If necessary, the operand is sign-
  163.77 + * extended so that it contains the designated bit.  None of the single-bit
  163.78 + * operations can produce a BigInteger with a different sign from the
  163.79 + * BigInteger being operated on, as they affect only a single bit, and the
  163.80 + * "infinite word size" abstraction provided by this class ensures that there
  163.81 + * are infinitely many "virtual sign bits" preceding each BigInteger.
  163.82 + *
  163.83 + * <p>For the sake of brevity and clarity, pseudo-code is used throughout the
  163.84 + * descriptions of BigInteger methods.  The pseudo-code expression
  163.85 + * {@code (i + j)} is shorthand for "a BigInteger whose value is
  163.86 + * that of the BigInteger {@code i} plus that of the BigInteger {@code j}."
  163.87 + * The pseudo-code expression {@code (i == j)} is shorthand for
  163.88 + * "{@code true} if and only if the BigInteger {@code i} represents the same
  163.89 + * value as the BigInteger {@code j}."  Other pseudo-code expressions are
  163.90 + * interpreted similarly.
  163.91 + *
  163.92 + * <p>All methods and constructors in this class throw
  163.93 + * {@code NullPointerException} when passed
  163.94 + * a null object reference for any input parameter.
  163.95 + *
  163.96 + * @see     BigDecimal
  163.97 + * @author  Josh Bloch
  163.98 + * @author  Michael McCloskey
  163.99 + * @since JDK1.1
 163.100 + */
 163.101 +
 163.102 +public class BigInteger extends Number implements Comparable<BigInteger> {
 163.103 +    /**
 163.104 +     * The signum of this BigInteger: -1 for negative, 0 for zero, or
 163.105 +     * 1 for positive.  Note that the BigInteger zero <i>must</i> have
 163.106 +     * a signum of 0.  This is necessary to ensures that there is exactly one
 163.107 +     * representation for each BigInteger value.
 163.108 +     *
 163.109 +     * @serial
 163.110 +     */
 163.111 +    final int signum;
 163.112 +
 163.113 +    /**
 163.114 +     * The magnitude of this BigInteger, in <i>big-endian</i> order: the
 163.115 +     * zeroth element of this array is the most-significant int of the
 163.116 +     * magnitude.  The magnitude must be "minimal" in that the most-significant
 163.117 +     * int ({@code mag[0]}) must be non-zero.  This is necessary to
 163.118 +     * ensure that there is exactly one representation for each BigInteger
 163.119 +     * value.  Note that this implies that the BigInteger zero has a
 163.120 +     * zero-length mag array.
 163.121 +     */
 163.122 +    final int[] mag;
 163.123 +
 163.124 +    // These "redundant fields" are initialized with recognizable nonsense
 163.125 +    // values, and cached the first time they are needed (or never, if they
 163.126 +    // aren't needed).
 163.127 +
 163.128 +     /**
 163.129 +     * One plus the bitCount of this BigInteger. Zeros means unitialized.
 163.130 +     *
 163.131 +     * @serial
 163.132 +     * @see #bitCount
 163.133 +     * @deprecated Deprecated since logical value is offset from stored
 163.134 +     * value and correction factor is applied in accessor method.
 163.135 +     */
 163.136 +    @Deprecated
 163.137 +    private int bitCount;
 163.138 +
 163.139 +    /**
 163.140 +     * One plus the bitLength of this BigInteger. Zeros means unitialized.
 163.141 +     * (either value is acceptable).
 163.142 +     *
 163.143 +     * @serial
 163.144 +     * @see #bitLength()
 163.145 +     * @deprecated Deprecated since logical value is offset from stored
 163.146 +     * value and correction factor is applied in accessor method.
 163.147 +     */
 163.148 +    @Deprecated
 163.149 +    private int bitLength;
 163.150 +
 163.151 +    /**
 163.152 +     * Two plus the lowest set bit of this BigInteger, as returned by
 163.153 +     * getLowestSetBit().
 163.154 +     *
 163.155 +     * @serial
 163.156 +     * @see #getLowestSetBit
 163.157 +     * @deprecated Deprecated since logical value is offset from stored
 163.158 +     * value and correction factor is applied in accessor method.
 163.159 +     */
 163.160 +    @Deprecated
 163.161 +    private int lowestSetBit;
 163.162 +
 163.163 +    /**
 163.164 +     * Two plus the index of the lowest-order int in the magnitude of this
 163.165 +     * BigInteger that contains a nonzero int, or -2 (either value is acceptable).
 163.166 +     * The least significant int has int-number 0, the next int in order of
 163.167 +     * increasing significance has int-number 1, and so forth.
 163.168 +     * @deprecated Deprecated since logical value is offset from stored
 163.169 +     * value and correction factor is applied in accessor method.
 163.170 +     */
 163.171 +    @Deprecated
 163.172 +    private int firstNonzeroIntNum;
 163.173 +
 163.174 +    /**
 163.175 +     * This mask is used to obtain the value of an int as if it were unsigned.
 163.176 +     */
 163.177 +    final static long LONG_MASK = 0xffffffffL;
 163.178 +
 163.179 +    //Constructors
 163.180 +
 163.181 +    /**
 163.182 +     * Translates a byte array containing the two's-complement binary
 163.183 +     * representation of a BigInteger into a BigInteger.  The input array is
 163.184 +     * assumed to be in <i>big-endian</i> byte-order: the most significant
 163.185 +     * byte is in the zeroth element.
 163.186 +     *
 163.187 +     * @param  val big-endian two's-complement binary representation of
 163.188 +     *         BigInteger.
 163.189 +     * @throws NumberFormatException {@code val} is zero bytes long.
 163.190 +     */
 163.191 +    public BigInteger(byte[] val) {
 163.192 +        if (val.length == 0)
 163.193 +            throw new NumberFormatException("Zero length BigInteger");
 163.194 +
 163.195 +        if (val[0] < 0) {
 163.196 +            mag = makePositive(val);
 163.197 +            signum = -1;
 163.198 +        } else {
 163.199 +            mag = stripLeadingZeroBytes(val);
 163.200 +            signum = (mag.length == 0 ? 0 : 1);
 163.201 +        }
 163.202 +    }
 163.203 +
 163.204 +    /**
 163.205 +     * This private constructor translates an int array containing the
 163.206 +     * two's-complement binary representation of a BigInteger into a
 163.207 +     * BigInteger. The input array is assumed to be in <i>big-endian</i>
 163.208 +     * int-order: the most significant int is in the zeroth element.
 163.209 +     */
 163.210 +    private BigInteger(int[] val) {
 163.211 +        if (val.length == 0)
 163.212 +            throw new NumberFormatException("Zero length BigInteger");
 163.213 +
 163.214 +        if (val[0] < 0) {
 163.215 +            mag = makePositive(val);
 163.216 +            signum = -1;
 163.217 +        } else {
 163.218 +            mag = trustedStripLeadingZeroInts(val);
 163.219 +            signum = (mag.length == 0 ? 0 : 1);
 163.220 +        }
 163.221 +    }
 163.222 +
 163.223 +    /**
 163.224 +     * Translates the sign-magnitude representation of a BigInteger into a
 163.225 +     * BigInteger.  The sign is represented as an integer signum value: -1 for
 163.226 +     * negative, 0 for zero, or 1 for positive.  The magnitude is a byte array
 163.227 +     * in <i>big-endian</i> byte-order: the most significant byte is in the
 163.228 +     * zeroth element.  A zero-length magnitude array is permissible, and will
 163.229 +     * result in a BigInteger value of 0, whether signum is -1, 0 or 1.
 163.230 +     *
 163.231 +     * @param  signum signum of the number (-1 for negative, 0 for zero, 1
 163.232 +     *         for positive).
 163.233 +     * @param  magnitude big-endian binary representation of the magnitude of
 163.234 +     *         the number.
 163.235 +     * @throws NumberFormatException {@code signum} is not one of the three
 163.236 +     *         legal values (-1, 0, and 1), or {@code signum} is 0 and
 163.237 +     *         {@code magnitude} contains one or more non-zero bytes.
 163.238 +     */
 163.239 +    public BigInteger(int signum, byte[] magnitude) {
 163.240 +        this.mag = stripLeadingZeroBytes(magnitude);
 163.241 +
 163.242 +        if (signum < -1 || signum > 1)
 163.243 +            throw(new NumberFormatException("Invalid signum value"));
 163.244 +
 163.245 +        if (this.mag.length==0) {
 163.246 +            this.signum = 0;
 163.247 +        } else {
 163.248 +            if (signum == 0)
 163.249 +                throw(new NumberFormatException("signum-magnitude mismatch"));
 163.250 +            this.signum = signum;
 163.251 +        }
 163.252 +    }
 163.253 +
 163.254 +    /**
 163.255 +     * A constructor for internal use that translates the sign-magnitude
 163.256 +     * representation of a BigInteger into a BigInteger. It checks the
 163.257 +     * arguments and copies the magnitude so this constructor would be
 163.258 +     * safe for external use.
 163.259 +     */
 163.260 +    private BigInteger(int signum, int[] magnitude) {
 163.261 +        this.mag = stripLeadingZeroInts(magnitude);
 163.262 +
 163.263 +        if (signum < -1 || signum > 1)
 163.264 +            throw(new NumberFormatException("Invalid signum value"));
 163.265 +
 163.266 +        if (this.mag.length==0) {
 163.267 +            this.signum = 0;
 163.268 +        } else {
 163.269 +            if (signum == 0)
 163.270 +                throw(new NumberFormatException("signum-magnitude mismatch"));
 163.271 +            this.signum = signum;
 163.272 +        }
 163.273 +    }
 163.274 +
 163.275 +    /**
 163.276 +     * Translates the String representation of a BigInteger in the
 163.277 +     * specified radix into a BigInteger.  The String representation
 163.278 +     * consists of an optional minus or plus sign followed by a
 163.279 +     * sequence of one or more digits in the specified radix.  The
 163.280 +     * character-to-digit mapping is provided by {@code
 163.281 +     * Character.digit}.  The String may not contain any extraneous
 163.282 +     * characters (whitespace, for example).
 163.283 +     *
 163.284 +     * @param val String representation of BigInteger.
 163.285 +     * @param radix radix to be used in interpreting {@code val}.
 163.286 +     * @throws NumberFormatException {@code val} is not a valid representation
 163.287 +     *         of a BigInteger in the specified radix, or {@code radix} is
 163.288 +     *         outside the range from {@link Character#MIN_RADIX} to
 163.289 +     *         {@link Character#MAX_RADIX}, inclusive.
 163.290 +     * @see    Character#digit
 163.291 +     */
 163.292 +    public BigInteger(String val, int radix) {
 163.293 +        int cursor = 0, numDigits;
 163.294 +        final int len = val.length();
 163.295 +
 163.296 +        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
 163.297 +            throw new NumberFormatException("Radix out of range");
 163.298 +        if (len == 0)
 163.299 +            throw new NumberFormatException("Zero length BigInteger");
 163.300 +
 163.301 +        // Check for at most one leading sign
 163.302 +        int sign = 1;
 163.303 +        int index1 = val.lastIndexOf('-');
 163.304 +        int index2 = val.lastIndexOf('+');
 163.305 +        if ((index1 + index2) <= -1) {
 163.306 +            // No leading sign character or at most one leading sign character
 163.307 +            if (index1 == 0 || index2 == 0) {
 163.308 +                cursor = 1;
 163.309 +                if (len == 1)
 163.310 +                    throw new NumberFormatException("Zero length BigInteger");
 163.311 +            }
 163.312 +            if (index1 == 0)
 163.313 +                sign = -1;
 163.314 +        } else
 163.315 +            throw new NumberFormatException("Illegal embedded sign character");
 163.316 +
 163.317 +        // Skip leading zeros and compute number of digits in magnitude
 163.318 +        while (cursor < len &&
 163.319 +               Character.digit(val.charAt(cursor), radix) == 0)
 163.320 +            cursor++;
 163.321 +        if (cursor == len) {
 163.322 +            signum = 0;
 163.323 +            mag = ZERO.mag;
 163.324 +            return;
 163.325 +        }
 163.326 +
 163.327 +        numDigits = len - cursor;
 163.328 +        signum = sign;
 163.329 +
 163.330 +        // Pre-allocate array of expected size. May be too large but can
 163.331 +        // never be too small. Typically exact.
 163.332 +        int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
 163.333 +        int numWords = (numBits + 31) >>> 5;
 163.334 +        int[] magnitude = new int[numWords];
 163.335 +
 163.336 +        // Process first (potentially short) digit group
 163.337 +        int firstGroupLen = numDigits % digitsPerInt[radix];
 163.338 +        if (firstGroupLen == 0)
 163.339 +            firstGroupLen = digitsPerInt[radix];
 163.340 +        String group = val.substring(cursor, cursor += firstGroupLen);
 163.341 +        magnitude[numWords - 1] = Integer.parseInt(group, radix);
 163.342 +        if (magnitude[numWords - 1] < 0)
 163.343 +            throw new NumberFormatException("Illegal digit");
 163.344 +
 163.345 +        // Process remaining digit groups
 163.346 +        int superRadix = intRadix[radix];
 163.347 +        int groupVal = 0;
 163.348 +        while (cursor < len) {
 163.349 +            group = val.substring(cursor, cursor += digitsPerInt[radix]);
 163.350 +            groupVal = Integer.parseInt(group, radix);
 163.351 +            if (groupVal < 0)
 163.352 +                throw new NumberFormatException("Illegal digit");
 163.353 +            destructiveMulAdd(magnitude, superRadix, groupVal);
 163.354 +        }
 163.355 +        // Required for cases where the array was overallocated.
 163.356 +        mag = trustedStripLeadingZeroInts(magnitude);
 163.357 +    }
 163.358 +
 163.359 +    // Constructs a new BigInteger using a char array with radix=10
 163.360 +    BigInteger(char[] val) {
 163.361 +        int cursor = 0, numDigits;
 163.362 +        int len = val.length;
 163.363 +
 163.364 +        // Check for leading minus sign
 163.365 +        int sign = 1;
 163.366 +        if (val[0] == '-') {
 163.367 +            if (len == 1)
 163.368 +                throw new NumberFormatException("Zero length BigInteger");
 163.369 +            sign = -1;
 163.370 +            cursor = 1;
 163.371 +        } else if (val[0] == '+') {
 163.372 +            if (len == 1)
 163.373 +                throw new NumberFormatException("Zero length BigInteger");
 163.374 +            cursor = 1;
 163.375 +        }
 163.376 +
 163.377 +        // Skip leading zeros and compute number of digits in magnitude
 163.378 +        while (cursor < len && Character.digit(val[cursor], 10) == 0)
 163.379 +            cursor++;
 163.380 +        if (cursor == len) {
 163.381 +            signum = 0;
 163.382 +            mag = ZERO.mag;
 163.383 +            return;
 163.384 +        }
 163.385 +
 163.386 +        numDigits = len - cursor;
 163.387 +        signum = sign;
 163.388 +
 163.389 +        // Pre-allocate array of expected size
 163.390 +        int numWords;
 163.391 +        if (len < 10) {
 163.392 +            numWords = 1;
 163.393 +        } else {
 163.394 +            int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1);
 163.395 +            numWords = (numBits + 31) >>> 5;
 163.396 +        }
 163.397 +        int[] magnitude = new int[numWords];
 163.398 +
 163.399 +        // Process first (potentially short) digit group
 163.400 +        int firstGroupLen = numDigits % digitsPerInt[10];
 163.401 +        if (firstGroupLen == 0)
 163.402 +            firstGroupLen = digitsPerInt[10];
 163.403 +        magnitude[numWords - 1] = parseInt(val, cursor,  cursor += firstGroupLen);
 163.404 +
 163.405 +        // Process remaining digit groups
 163.406 +        while (cursor < len) {
 163.407 +            int groupVal = parseInt(val, cursor, cursor += digitsPerInt[10]);
 163.408 +            destructiveMulAdd(magnitude, intRadix[10], groupVal);
 163.409 +        }
 163.410 +        mag = trustedStripLeadingZeroInts(magnitude);
 163.411 +    }
 163.412 +
 163.413 +    // Create an integer with the digits between the two indexes
 163.414 +    // Assumes start < end. The result may be negative, but it
 163.415 +    // is to be treated as an unsigned value.
 163.416 +    private int parseInt(char[] source, int start, int end) {
 163.417 +        int result = Character.digit(source[start++], 10);
 163.418 +        if (result == -1)
 163.419 +            throw new NumberFormatException(new String(source));
 163.420 +
 163.421 +        for (int index = start; index<end; index++) {
 163.422 +            int nextVal = Character.digit(source[index], 10);
 163.423 +            if (nextVal == -1)
 163.424 +                throw new NumberFormatException(new String(source));
 163.425 +            result = 10*result + nextVal;
 163.426 +        }
 163.427 +
 163.428 +        return result;
 163.429 +    }
 163.430 +
 163.431 +    // bitsPerDigit in the given radix times 1024
 163.432 +    // Rounded up to avoid underallocation.
 163.433 +    private static long bitsPerDigit[] = { 0, 0,
 163.434 +        1024, 1624, 2048, 2378, 2648, 2875, 3072, 3247, 3402, 3543, 3672,
 163.435 +        3790, 3899, 4001, 4096, 4186, 4271, 4350, 4426, 4498, 4567, 4633,
 163.436 +        4696, 4756, 4814, 4870, 4923, 4975, 5025, 5074, 5120, 5166, 5210,
 163.437 +                                           5253, 5295};
 163.438 +
 163.439 +    // Multiply x array times word y in place, and add word z
 163.440 +    private static void destructiveMulAdd(int[] x, int y, int z) {
 163.441 +        // Perform the multiplication word by word
 163.442 +        long ylong = y & LONG_MASK;
 163.443 +        long zlong = z & LONG_MASK;
 163.444 +        int len = x.length;
 163.445 +
 163.446 +        long product = 0;
 163.447 +        long carry = 0;
 163.448 +        for (int i = len-1; i >= 0; i--) {
 163.449 +            product = ylong * (x[i] & LONG_MASK) + carry;
 163.450 +            x[i] = (int)product;
 163.451 +            carry = product >>> 32;
 163.452 +        }
 163.453 +
 163.454 +        // Perform the addition
 163.455 +        long sum = (x[len-1] & LONG_MASK) + zlong;
 163.456 +        x[len-1] = (int)sum;
 163.457 +        carry = sum >>> 32;
 163.458 +        for (int i = len-2; i >= 0; i--) {
 163.459 +            sum = (x[i] & LONG_MASK) + carry;
 163.460 +            x[i] = (int)sum;
 163.461 +            carry = sum >>> 32;
 163.462 +        }
 163.463 +    }
 163.464 +
 163.465 +    /**
 163.466 +     * Translates the decimal String representation of a BigInteger into a
 163.467 +     * BigInteger.  The String representation consists of an optional minus
 163.468 +     * sign followed by a sequence of one or more decimal digits.  The
 163.469 +     * character-to-digit mapping is provided by {@code Character.digit}.
 163.470 +     * The String may not contain any extraneous characters (whitespace, for
 163.471 +     * example).
 163.472 +     *
 163.473 +     * @param val decimal String representation of BigInteger.
 163.474 +     * @throws NumberFormatException {@code val} is not a valid representation
 163.475 +     *         of a BigInteger.
 163.476 +     * @see    Character#digit
 163.477 +     */
 163.478 +    public BigInteger(String val) {
 163.479 +        this(val, 10);
 163.480 +    }
 163.481 +
 163.482 +    /**
 163.483 +     * Constructs a randomly generated BigInteger, uniformly distributed over
 163.484 +     * the range 0 to (2<sup>{@code numBits}</sup> - 1), inclusive.
 163.485 +     * The uniformity of the distribution assumes that a fair source of random
 163.486 +     * bits is provided in {@code rnd}.  Note that this constructor always
 163.487 +     * constructs a non-negative BigInteger.
 163.488 +     *
 163.489 +     * @param  numBits maximum bitLength of the new BigInteger.
 163.490 +     * @param  rnd source of randomness to be used in computing the new
 163.491 +     *         BigInteger.
 163.492 +     * @throws IllegalArgumentException {@code numBits} is negative.
 163.493 +     * @see #bitLength()
 163.494 +     */
 163.495 +    public BigInteger(int numBits, Random rnd) {
 163.496 +        this(1, randomBits(numBits, rnd));
 163.497 +    }
 163.498 +
 163.499 +    private static byte[] randomBits(int numBits, Random rnd) {
 163.500 +        if (numBits < 0)
 163.501 +            throw new IllegalArgumentException("numBits must be non-negative");
 163.502 +        int numBytes = (int)(((long)numBits+7)/8); // avoid overflow
 163.503 +        byte[] randomBits = new byte[numBytes];
 163.504 +
 163.505 +        // Generate random bytes and mask out any excess bits
 163.506 +        if (numBytes > 0) {
 163.507 +            rnd.nextBytes(randomBits);
 163.508 +            int excessBits = 8*numBytes - numBits;
 163.509 +            randomBits[0] &= (1 << (8-excessBits)) - 1;
 163.510 +        }
 163.511 +        return randomBits;
 163.512 +    }
 163.513 +
 163.514 +    /**
 163.515 +     * Constructs a randomly generated positive BigInteger that is probably
 163.516 +     * prime, with the specified bitLength.
 163.517 +     *
 163.518 +     * <p>It is recommended that the {@link #probablePrime probablePrime}
 163.519 +     * method be used in preference to this constructor unless there
 163.520 +     * is a compelling need to specify a certainty.
 163.521 +     *
 163.522 +     * @param  bitLength bitLength of the returned BigInteger.
 163.523 +     * @param  certainty a measure of the uncertainty that the caller is
 163.524 +     *         willing to tolerate.  The probability that the new BigInteger
 163.525 +     *         represents a prime number will exceed
 163.526 +     *         (1 - 1/2<sup>{@code certainty}</sup>).  The execution time of
 163.527 +     *         this constructor is proportional to the value of this parameter.
 163.528 +     * @param  rnd source of random bits used to select candidates to be
 163.529 +     *         tested for primality.
 163.530 +     * @throws ArithmeticException {@code bitLength < 2}.
 163.531 +     * @see    #bitLength()
 163.532 +     */
 163.533 +    public BigInteger(int bitLength, int certainty, Random rnd) {
 163.534 +        BigInteger prime;
 163.535 +
 163.536 +        if (bitLength < 2)
 163.537 +            throw new ArithmeticException("bitLength < 2");
 163.538 +        // The cutoff of 95 was chosen empirically for best performance
 163.539 +        prime = (bitLength < 95 ? smallPrime(bitLength, certainty, rnd)
 163.540 +                                : largePrime(bitLength, certainty, rnd));
 163.541 +        signum = 1;
 163.542 +        mag = prime.mag;
 163.543 +    }
 163.544 +
 163.545 +    // Minimum size in bits that the requested prime number has
 163.546 +    // before we use the large prime number generating algorithms
 163.547 +    private static final int SMALL_PRIME_THRESHOLD = 95;
 163.548 +
 163.549 +    // Certainty required to meet the spec of probablePrime
 163.550 +    private static final int DEFAULT_PRIME_CERTAINTY = 100;
 163.551 +
 163.552 +    /**
 163.553 +     * Returns a positive BigInteger that is probably prime, with the
 163.554 +     * specified bitLength. The probability that a BigInteger returned
 163.555 +     * by this method is composite does not exceed 2<sup>-100</sup>.
 163.556 +     *
 163.557 +     * @param  bitLength bitLength of the returned BigInteger.
 163.558 +     * @param  rnd source of random bits used to select candidates to be
 163.559 +     *         tested for primality.
 163.560 +     * @return a BigInteger of {@code bitLength} bits that is probably prime
 163.561 +     * @throws ArithmeticException {@code bitLength < 2}.
 163.562 +     * @see    #bitLength()
 163.563 +     * @since 1.4
 163.564 +     */
 163.565 +    public static BigInteger probablePrime(int bitLength, Random rnd) {
 163.566 +        if (bitLength < 2)
 163.567 +            throw new ArithmeticException("bitLength < 2");
 163.568 +
 163.569 +        // The cutoff of 95 was chosen empirically for best performance
 163.570 +        return (bitLength < SMALL_PRIME_THRESHOLD ?
 163.571 +                smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
 163.572 +                largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
 163.573 +    }
 163.574 +
 163.575 +    /**
 163.576 +     * Find a random number of the specified bitLength that is probably prime.
 163.577 +     * This method is used for smaller primes, its performance degrades on
 163.578 +     * larger bitlengths.
 163.579 +     *
 163.580 +     * This method assumes bitLength > 1.
 163.581 +     */
 163.582 +    private static BigInteger smallPrime(int bitLength, int certainty, Random rnd) {
 163.583 +        int magLen = (bitLength + 31) >>> 5;
 163.584 +        int temp[] = new int[magLen];
 163.585 +        int highBit = 1 << ((bitLength+31) & 0x1f);  // High bit of high int
 163.586 +        int highMask = (highBit << 1) - 1;  // Bits to keep in high int
 163.587 +
 163.588 +        while(true) {
 163.589 +            // Construct a candidate
 163.590 +            for (int i=0; i<magLen; i++)
 163.591 +                temp[i] = rnd.nextInt();
 163.592 +            temp[0] = (temp[0] & highMask) | highBit;  // Ensure exact length
 163.593 +            if (bitLength > 2)
 163.594 +                temp[magLen-1] |= 1;  // Make odd if bitlen > 2
 163.595 +
 163.596 +            BigInteger p = new BigInteger(temp, 1);
 163.597 +
 163.598 +            // Do cheap "pre-test" if applicable
 163.599 +            if (bitLength > 6) {
 163.600 +                long r = p.remainder(SMALL_PRIME_PRODUCT).longValue();
 163.601 +                if ((r%3==0)  || (r%5==0)  || (r%7==0)  || (r%11==0) ||
 163.602 +                    (r%13==0) || (r%17==0) || (r%19==0) || (r%23==0) ||
 163.603 +                    (r%29==0) || (r%31==0) || (r%37==0) || (r%41==0))
 163.604 +                    continue; // Candidate is composite; try another
 163.605 +            }
 163.606 +
 163.607 +            // All candidates of bitLength 2 and 3 are prime by this point
 163.608 +            if (bitLength < 4)
 163.609 +                return p;
 163.610 +
 163.611 +            // Do expensive test if we survive pre-test (or it's inapplicable)
 163.612 +            if (p.primeToCertainty(certainty, rnd))
 163.613 +                return p;
 163.614 +        }
 163.615 +    }
 163.616 +
 163.617 +    private static final BigInteger SMALL_PRIME_PRODUCT
 163.618 +                       = valueOf(3L*5*7*11*13*17*19*23*29*31*37*41);
 163.619 +
 163.620 +    /**
 163.621 +     * Find a random number of the specified bitLength that is probably prime.
 163.622 +     * This method is more appropriate for larger bitlengths since it uses
 163.623 +     * a sieve to eliminate most composites before using a more expensive
 163.624 +     * test.
 163.625 +     */
 163.626 +    private static BigInteger largePrime(int bitLength, int certainty, Random rnd) {
 163.627 +        BigInteger p;
 163.628 +        p = new BigInteger(bitLength, rnd).setBit(bitLength-1);
 163.629 +        p.mag[p.mag.length-1] &= 0xfffffffe;
 163.630 +
 163.631 +        // Use a sieve length likely to contain the next prime number
 163.632 +        int searchLen = (bitLength / 20) * 64;
 163.633 +        BitSieve searchSieve = new BitSieve(p, searchLen);
 163.634 +        BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
 163.635 +
 163.636 +        while ((candidate == null) || (candidate.bitLength() != bitLength)) {
 163.637 +            p = p.add(BigInteger.valueOf(2*searchLen));
 163.638 +            if (p.bitLength() != bitLength)
 163.639 +                p = new BigInteger(bitLength, rnd).setBit(bitLength-1);
 163.640 +            p.mag[p.mag.length-1] &= 0xfffffffe;
 163.641 +            searchSieve = new BitSieve(p, searchLen);
 163.642 +            candidate = searchSieve.retrieve(p, certainty, rnd);
 163.643 +        }
 163.644 +        return candidate;
 163.645 +    }
 163.646 +
 163.647 +   /**
 163.648 +    * Returns the first integer greater than this {@code BigInteger} that
 163.649 +    * is probably prime.  The probability that the number returned by this
 163.650 +    * method is composite does not exceed 2<sup>-100</sup>. This method will
 163.651 +    * never skip over a prime when searching: if it returns {@code p}, there
 163.652 +    * is no prime {@code q} such that {@code this < q < p}.
 163.653 +    *
 163.654 +    * @return the first integer greater than this {@code BigInteger} that
 163.655 +    *         is probably prime.
 163.656 +    * @throws ArithmeticException {@code this < 0}.
 163.657 +    * @since 1.5
 163.658 +    */
 163.659 +    public BigInteger nextProbablePrime() {
 163.660 +        if (this.signum < 0)
 163.661 +            throw new ArithmeticException("start < 0: " + this);
 163.662 +
 163.663 +        // Handle trivial cases
 163.664 +        if ((this.signum == 0) || this.equals(ONE))
 163.665 +            return TWO;
 163.666 +
 163.667 +        BigInteger result = this.add(ONE);
 163.668 +
 163.669 +        // Fastpath for small numbers
 163.670 +        if (result.bitLength() < SMALL_PRIME_THRESHOLD) {
 163.671 +
 163.672 +            // Ensure an odd number
 163.673 +            if (!result.testBit(0))
 163.674 +                result = result.add(ONE);
 163.675 +
 163.676 +            while(true) {
 163.677 +                // Do cheap "pre-test" if applicable
 163.678 +                if (result.bitLength() > 6) {
 163.679 +                    long r = result.remainder(SMALL_PRIME_PRODUCT).longValue();
 163.680 +                    if ((r%3==0)  || (r%5==0)  || (r%7==0)  || (r%11==0) ||
 163.681 +                        (r%13==0) || (r%17==0) || (r%19==0) || (r%23==0) ||
 163.682 +                        (r%29==0) || (r%31==0) || (r%37==0) || (r%41==0)) {
 163.683 +                        result = result.add(TWO);
 163.684 +                        continue; // Candidate is composite; try another
 163.685 +                    }
 163.686 +                }
 163.687 +
 163.688 +                // All candidates of bitLength 2 and 3 are prime by this point
 163.689 +                if (result.bitLength() < 4)
 163.690 +                    return result;
 163.691 +
 163.692 +                // The expensive test
 163.693 +                if (result.primeToCertainty(DEFAULT_PRIME_CERTAINTY, null))
 163.694 +                    return result;
 163.695 +
 163.696 +                result = result.add(TWO);
 163.697 +            }
 163.698 +        }
 163.699 +
 163.700 +        // Start at previous even number
 163.701 +        if (result.testBit(0))
 163.702 +            result = result.subtract(ONE);
 163.703 +
 163.704 +        // Looking for the next large prime
 163.705 +        int searchLen = (result.bitLength() / 20) * 64;
 163.706 +
 163.707 +        while(true) {
 163.708 +           BitSieve searchSieve = new BitSieve(result, searchLen);
 163.709 +           BigInteger candidate = searchSieve.retrieve(result,
 163.710 +                                                 DEFAULT_PRIME_CERTAINTY, null);
 163.711 +           if (candidate != null)
 163.712 +               return candidate;
 163.713 +           result = result.add(BigInteger.valueOf(2 * searchLen));
 163.714 +        }
 163.715 +    }
 163.716 +
 163.717 +    /**
 163.718 +     * Returns {@code true} if this BigInteger is probably prime,
 163.719 +     * {@code false} if it's definitely composite.
 163.720 +     *
 163.721 +     * This method assumes bitLength > 2.
 163.722 +     *
 163.723 +     * @param  certainty a measure of the uncertainty that the caller is
 163.724 +     *         willing to tolerate: if the call returns {@code true}
 163.725 +     *         the probability that this BigInteger is prime exceeds
 163.726 +     *         {@code (1 - 1/2<sup>certainty</sup>)}.  The execution time of
 163.727 +     *         this method is proportional to the value of this parameter.
 163.728 +     * @return {@code true} if this BigInteger is probably prime,
 163.729 +     *         {@code false} if it's definitely composite.
 163.730 +     */
 163.731 +    boolean primeToCertainty(int certainty, Random random) {
 163.732 +        int rounds = 0;
 163.733 +        int n = (Math.min(certainty, Integer.MAX_VALUE-1)+1)/2;
 163.734 +
 163.735 +        // The relationship between the certainty and the number of rounds
 163.736 +        // we perform is given in the draft standard ANSI X9.80, "PRIME
 163.737 +        // NUMBER GENERATION, PRIMALITY TESTING, AND PRIMALITY CERTIFICATES".
 163.738 +        int sizeInBits = this.bitLength();
 163.739 +        if (sizeInBits < 100) {
 163.740 +            rounds = 50;
 163.741 +            rounds = n < rounds ? n : rounds;
 163.742 +            return passesMillerRabin(rounds, random);
 163.743 +        }
 163.744 +
 163.745 +        if (sizeInBits < 256) {
 163.746 +            rounds = 27;
 163.747 +        } else if (sizeInBits < 512) {
 163.748 +            rounds = 15;
 163.749 +        } else if (sizeInBits < 768) {
 163.750 +            rounds = 8;
 163.751 +        } else if (sizeInBits < 1024) {
 163.752 +            rounds = 4;
 163.753 +        } else {
 163.754 +            rounds = 2;
 163.755 +        }
 163.756 +        rounds = n < rounds ? n : rounds;
 163.757 +
 163.758 +        return passesMillerRabin(rounds, random) && passesLucasLehmer();
 163.759 +    }
 163.760 +
 163.761 +    /**
 163.762 +     * Returns true iff this BigInteger is a Lucas-Lehmer probable prime.
 163.763 +     *
 163.764 +     * The following assumptions are made:
 163.765 +     * This BigInteger is a positive, odd number.
 163.766 +     */
 163.767 +    private boolean passesLucasLehmer() {
 163.768 +        BigInteger thisPlusOne = this.add(ONE);
 163.769 +
 163.770 +        // Step 1
 163.771 +        int d = 5;
 163.772 +        while (jacobiSymbol(d, this) != -1) {
 163.773 +            // 5, -7, 9, -11, ...
 163.774 +            d = (d<0) ? Math.abs(d)+2 : -(d+2);
 163.775 +        }
 163.776 +
 163.777 +        // Step 2
 163.778 +        BigInteger u = lucasLehmerSequence(d, thisPlusOne, this);
 163.779 +
 163.780 +        // Step 3
 163.781 +        return u.mod(this).equals(ZERO);
 163.782 +    }
 163.783 +
 163.784 +    /**
 163.785 +     * Computes Jacobi(p,n).
 163.786 +     * Assumes n positive, odd, n>=3.
 163.787 +     */
 163.788 +    private static int jacobiSymbol(int p, BigInteger n) {
 163.789 +        if (p == 0)
 163.790 +            return 0;
 163.791 +
 163.792 +        // Algorithm and comments adapted from Colin Plumb's C library.
 163.793 +        int j = 1;
 163.794 +        int u = n.mag[n.mag.length-1];
 163.795 +
 163.796 +        // Make p positive
 163.797 +        if (p < 0) {
 163.798 +            p = -p;
 163.799 +            int n8 = u & 7;
 163.800 +            if ((n8 == 3) || (n8 == 7))
 163.801 +                j = -j; // 3 (011) or 7 (111) mod 8
 163.802 +        }
 163.803 +
 163.804 +        // Get rid of factors of 2 in p
 163.805 +        while ((p & 3) == 0)
 163.806 +            p >>= 2;
 163.807 +        if ((p & 1) == 0) {
 163.808 +            p >>= 1;
 163.809 +            if (((u ^ (u>>1)) & 2) != 0)
 163.810 +                j = -j; // 3 (011) or 5 (101) mod 8
 163.811 +        }
 163.812 +        if (p == 1)
 163.813 +            return j;
 163.814 +        // Then, apply quadratic reciprocity
 163.815 +        if ((p & u & 2) != 0)   // p = u = 3 (mod 4)?
 163.816 +            j = -j;
 163.817 +        // And reduce u mod p
 163.818 +        u = n.mod(BigInteger.valueOf(p)).intValue();
 163.819 +
 163.820 +        // Now compute Jacobi(u,p), u < p
 163.821 +        while (u != 0) {
 163.822 +            while ((u & 3) == 0)
 163.823 +                u >>= 2;
 163.824 +            if ((u & 1) == 0) {
 163.825 +                u >>= 1;
 163.826 +                if (((p ^ (p>>1)) & 2) != 0)
 163.827 +                    j = -j;     // 3 (011) or 5 (101) mod 8
 163.828 +            }
 163.829 +            if (u == 1)
 163.830 +                return j;
 163.831 +            // Now both u and p are odd, so use quadratic reciprocity
 163.832 +            assert (u < p);
 163.833 +            int t = u; u = p; p = t;
 163.834 +            if ((u & p & 2) != 0) // u = p = 3 (mod 4)?
 163.835 +                j = -j;
 163.836 +            // Now u >= p, so it can be reduced
 163.837 +            u %= p;
 163.838 +        }
 163.839 +        return 0;
 163.840 +    }
 163.841 +
 163.842 +    private static BigInteger lucasLehmerSequence(int z, BigInteger k, BigInteger n) {
 163.843 +        BigInteger d = BigInteger.valueOf(z);
 163.844 +        BigInteger u = ONE; BigInteger u2;
 163.845 +        BigInteger v = ONE; BigInteger v2;
 163.846 +
 163.847 +        for (int i=k.bitLength()-2; i>=0; i--) {
 163.848 +            u2 = u.multiply(v).mod(n);
 163.849 +
 163.850 +            v2 = v.square().add(d.multiply(u.square())).mod(n);
 163.851 +            if (v2.testBit(0))
 163.852 +                v2 = v2.subtract(n);
 163.853 +
 163.854 +            v2 = v2.shiftRight(1);
 163.855 +
 163.856 +            u = u2; v = v2;
 163.857 +            if (k.testBit(i)) {
 163.858 +                u2 = u.add(v).mod(n);
 163.859 +                if (u2.testBit(0))
 163.860 +                    u2 = u2.subtract(n);
 163.861 +
 163.862 +                u2 = u2.shiftRight(1);
 163.863 +                v2 = v.add(d.multiply(u)).mod(n);
 163.864 +                if (v2.testBit(0))
 163.865 +                    v2 = v2.subtract(n);
 163.866 +                v2 = v2.shiftRight(1);
 163.867 +
 163.868 +                u = u2; v = v2;
 163.869 +            }
 163.870 +        }
 163.871 +        return u;
 163.872 +    }
 163.873 +
 163.874 +    private static volatile Random staticRandom;
 163.875 +
 163.876 +    private static Random getSecureRandom() {
 163.877 +        if (staticRandom == null) {
 163.878 +            staticRandom = new Random();
 163.879 +        }
 163.880 +        return staticRandom;
 163.881 +    }
 163.882 +
 163.883 +    /**
 163.884 +     * Returns true iff this BigInteger passes the specified number of
 163.885 +     * Miller-Rabin tests. This test is taken from the DSA spec (NIST FIPS
 163.886 +     * 186-2).
 163.887 +     *
 163.888 +     * The following assumptions are made:
 163.889 +     * This BigInteger is a positive, odd number greater than 2.
 163.890 +     * iterations<=50.
 163.891 +     */
 163.892 +    private boolean passesMillerRabin(int iterations, Random rnd) {
 163.893 +        // Find a and m such that m is odd and this == 1 + 2**a * m
 163.894 +        BigInteger thisMinusOne = this.subtract(ONE);
 163.895 +        BigInteger m = thisMinusOne;
 163.896 +        int a = m.getLowestSetBit();
 163.897 +        m = m.shiftRight(a);
 163.898 +
 163.899 +        // Do the tests
 163.900 +        if (rnd == null) {
 163.901 +            rnd = getSecureRandom();
 163.902 +        }
 163.903 +        for (int i=0; i<iterations; i++) {
 163.904 +            // Generate a uniform random on (1, this)
 163.905 +            BigInteger b;
 163.906 +            do {
 163.907 +                b = new BigInteger(this.bitLength(), rnd);
 163.908 +            } while (b.compareTo(ONE) <= 0 || b.compareTo(this) >= 0);
 163.909 +
 163.910 +            int j = 0;
 163.911 +            BigInteger z = b.modPow(m, this);
 163.912 +            while(!((j==0 && z.equals(ONE)) || z.equals(thisMinusOne))) {
 163.913 +                if (j>0 && z.equals(ONE) || ++j==a)
 163.914 +                    return false;
 163.915 +                z = z.modPow(TWO, this);
 163.916 +            }
 163.917 +        }
 163.918 +        return true;
 163.919 +    }
 163.920 +
 163.921 +    /**
 163.922 +     * This internal constructor differs from its public cousin
 163.923 +     * with the arguments reversed in two ways: it assumes that its
 163.924 +     * arguments are correct, and it doesn't copy the magnitude array.
 163.925 +     */
 163.926 +    BigInteger(int[] magnitude, int signum) {
 163.927 +        this.signum = (magnitude.length==0 ? 0 : signum);
 163.928 +        this.mag = magnitude;
 163.929 +    }
 163.930 +
 163.931 +    /**
 163.932 +     * This private constructor is for internal use and assumes that its
 163.933 +     * arguments are correct.
 163.934 +     */
 163.935 +    private BigInteger(byte[] magnitude, int signum) {
 163.936 +        this.signum = (magnitude.length==0 ? 0 : signum);
 163.937 +        this.mag = stripLeadingZeroBytes(magnitude);
 163.938 +    }
 163.939 +
 163.940 +    //Static Factory Methods
 163.941 +
 163.942 +    /**
 163.943 +     * Returns a BigInteger whose value is equal to that of the
 163.944 +     * specified {@code long}.  This "static factory method" is
 163.945 +     * provided in preference to a ({@code long}) constructor
 163.946 +     * because it allows for reuse of frequently used BigIntegers.
 163.947 +     *
 163.948 +     * @param  val value of the BigInteger to return.
 163.949 +     * @return a BigInteger with the specified value.
 163.950 +     */
 163.951 +    public static BigInteger valueOf(long val) {
 163.952 +        // If -MAX_CONSTANT < val < MAX_CONSTANT, return stashed constant
 163.953 +        if (val == 0)
 163.954 +            return ZERO;
 163.955 +        if (val > 0 && val <= MAX_CONSTANT)
 163.956 +            return posConst[(int) val];
 163.957 +        else if (val < 0 && val >= -MAX_CONSTANT)
 163.958 +            return negConst[(int) -val];
 163.959 +
 163.960 +        return new BigInteger(val);
 163.961 +    }
 163.962 +
 163.963 +    /**
 163.964 +     * Constructs a BigInteger with the specified value, which may not be zero.
 163.965 +     */
 163.966 +    private BigInteger(long val) {
 163.967 +        if (val < 0) {
 163.968 +            val = -val;
 163.969 +            signum = -1;
 163.970 +        } else {
 163.971 +            signum = 1;
 163.972 +        }
 163.973 +
 163.974 +        int highWord = (int)(val >>> 32);
 163.975 +        if (highWord==0) {
 163.976 +            mag = new int[1];
 163.977 +            mag[0] = (int)val;
 163.978 +        } else {
 163.979 +            mag = new int[2];
 163.980 +            mag[0] = highWord;
 163.981 +            mag[1] = (int)val;
 163.982 +        }
 163.983 +    }
 163.984 +
 163.985 +    /**
 163.986 +     * Returns a BigInteger with the given two's complement representation.
 163.987 +     * Assumes that the input array will not be modified (the returned
 163.988 +     * BigInteger will reference the input array if feasible).
 163.989 +     */
 163.990 +    private static BigInteger valueOf(int val[]) {
 163.991 +        return (val[0]>0 ? new BigInteger(val, 1) : new BigInteger(val));
 163.992 +    }
 163.993 +
 163.994 +    // Constants
 163.995 +
 163.996 +    /**
 163.997 +     * Initialize static constant array when class is loaded.
 163.998 +     */
 163.999 +    private final static int MAX_CONSTANT = 16;
163.1000 +    private static BigInteger posConst[] = new BigInteger[MAX_CONSTANT+1];
163.1001 +    private static BigInteger negConst[] = new BigInteger[MAX_CONSTANT+1];
163.1002 +    static {
163.1003 +        for (int i = 1; i <= MAX_CONSTANT; i++) {
163.1004 +            int[] magnitude = new int[1];
163.1005 +            magnitude[0] = i;
163.1006 +            posConst[i] = new BigInteger(magnitude,  1);
163.1007 +            negConst[i] = new BigInteger(magnitude, -1);
163.1008 +        }
163.1009 +    }
163.1010 +
163.1011 +    /**
163.1012 +     * The BigInteger constant zero.
163.1013 +     *
163.1014 +     * @since   1.2
163.1015 +     */
163.1016 +    public static final BigInteger ZERO = new BigInteger(new int[0], 0);
163.1017 +
163.1018 +    /**
163.1019 +     * The BigInteger constant one.
163.1020 +     *
163.1021 +     * @since   1.2
163.1022 +     */
163.1023 +    public static final BigInteger ONE = valueOf(1);
163.1024 +
163.1025 +    /**
163.1026 +     * The BigInteger constant two.  (Not exported.)
163.1027 +     */
163.1028 +    private static final BigInteger TWO = valueOf(2);
163.1029 +
163.1030 +    /**
163.1031 +     * The BigInteger constant ten.
163.1032 +     *
163.1033 +     * @since   1.5
163.1034 +     */
163.1035 +    public static final BigInteger TEN = valueOf(10);
163.1036 +
163.1037 +    // Arithmetic Operations
163.1038 +
163.1039 +    /**
163.1040 +     * Returns a BigInteger whose value is {@code (this + val)}.
163.1041 +     *
163.1042 +     * @param  val value to be added to this BigInteger.
163.1043 +     * @return {@code this + val}
163.1044 +     */
163.1045 +    public BigInteger add(BigInteger val) {
163.1046 +        if (val.signum == 0)
163.1047 +            return this;
163.1048 +        if (signum == 0)
163.1049 +            return val;
163.1050 +        if (val.signum == signum)
163.1051 +            return new BigInteger(add(mag, val.mag), signum);
163.1052 +
163.1053 +        int cmp = compareMagnitude(val);
163.1054 +        if (cmp == 0)
163.1055 +            return ZERO;
163.1056 +        int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
163.1057 +                           : subtract(val.mag, mag));
163.1058 +        resultMag = trustedStripLeadingZeroInts(resultMag);
163.1059 +
163.1060 +        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
163.1061 +    }
163.1062 +
163.1063 +    /**
163.1064 +     * Adds the contents of the int arrays x and y. This method allocates
163.1065 +     * a new int array to hold the answer and returns a reference to that
163.1066 +     * array.
163.1067 +     */
163.1068 +    private static int[] add(int[] x, int[] y) {
163.1069 +        // If x is shorter, swap the two arrays
163.1070 +        if (x.length < y.length) {
163.1071 +            int[] tmp = x;
163.1072 +            x = y;
163.1073 +            y = tmp;
163.1074 +        }
163.1075 +
163.1076 +        int xIndex = x.length;
163.1077 +        int yIndex = y.length;
163.1078 +        int result[] = new int[xIndex];
163.1079 +        long sum = 0;
163.1080 +
163.1081 +        // Add common parts of both numbers
163.1082 +        while(yIndex > 0) {
163.1083 +            sum = (x[--xIndex] & LONG_MASK) +
163.1084 +                  (y[--yIndex] & LONG_MASK) + (sum >>> 32);
163.1085 +            result[xIndex] = (int)sum;
163.1086 +        }
163.1087 +
163.1088 +        // Copy remainder of longer number while carry propagation is required
163.1089 +        boolean carry = (sum >>> 32 != 0);
163.1090 +        while (xIndex > 0 && carry)
163.1091 +            carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
163.1092 +
163.1093 +        // Copy remainder of longer number
163.1094 +        while (xIndex > 0)
163.1095 +            result[--xIndex] = x[xIndex];
163.1096 +
163.1097 +        // Grow result if necessary
163.1098 +        if (carry) {
163.1099 +            int bigger[] = new int[result.length + 1];
163.1100 +            System.arraycopy(result, 0, bigger, 1, result.length);
163.1101 +            bigger[0] = 0x01;
163.1102 +            return bigger;
163.1103 +        }
163.1104 +        return result;
163.1105 +    }
163.1106 +
163.1107 +    /**
163.1108 +     * Returns a BigInteger whose value is {@code (this - val)}.
163.1109 +     *
163.1110 +     * @param  val value to be subtracted from this BigInteger.
163.1111 +     * @return {@code this - val}
163.1112 +     */
163.1113 +    public BigInteger subtract(BigInteger val) {
163.1114 +        if (val.signum == 0)
163.1115 +            return this;
163.1116 +        if (signum == 0)
163.1117 +            return val.negate();
163.1118 +        if (val.signum != signum)
163.1119 +            return new BigInteger(add(mag, val.mag), signum);
163.1120 +
163.1121 +        int cmp = compareMagnitude(val);
163.1122 +        if (cmp == 0)
163.1123 +            return ZERO;
163.1124 +        int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
163.1125 +                           : subtract(val.mag, mag));
163.1126 +        resultMag = trustedStripLeadingZeroInts(resultMag);
163.1127 +        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
163.1128 +    }
163.1129 +
163.1130 +    /**
163.1131 +     * Subtracts the contents of the second int arrays (little) from the
163.1132 +     * first (big).  The first int array (big) must represent a larger number
163.1133 +     * than the second.  This method allocates the space necessary to hold the
163.1134 +     * answer.
163.1135 +     */
163.1136 +    private static int[] subtract(int[] big, int[] little) {
163.1137 +        int bigIndex = big.length;
163.1138 +        int result[] = new int[bigIndex];
163.1139 +        int littleIndex = little.length;
163.1140 +        long difference = 0;
163.1141 +
163.1142 +        // Subtract common parts of both numbers
163.1143 +        while(littleIndex > 0) {
163.1144 +            difference = (big[--bigIndex] & LONG_MASK) -
163.1145 +                         (little[--littleIndex] & LONG_MASK) +
163.1146 +                         (difference >> 32);
163.1147 +            result[bigIndex] = (int)difference;
163.1148 +        }
163.1149 +
163.1150 +        // Subtract remainder of longer number while borrow propagates
163.1151 +        boolean borrow = (difference >> 32 != 0);
163.1152 +        while (bigIndex > 0 && borrow)
163.1153 +            borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1);
163.1154 +
163.1155 +        // Copy remainder of longer number
163.1156 +        while (bigIndex > 0)
163.1157 +            result[--bigIndex] = big[bigIndex];
163.1158 +
163.1159 +        return result;
163.1160 +    }
163.1161 +
163.1162 +    /**
163.1163 +     * Returns a BigInteger whose value is {@code (this * val)}.
163.1164 +     *
163.1165 +     * @param  val value to be multiplied by this BigInteger.
163.1166 +     * @return {@code this * val}
163.1167 +     */
163.1168 +    public BigInteger multiply(BigInteger val) {
163.1169 +        if (val.signum == 0 || signum == 0)
163.1170 +            return ZERO;
163.1171 +
163.1172 +        int[] result = multiplyToLen(mag, mag.length,
163.1173 +                                     val.mag, val.mag.length, null);
163.1174 +        result = trustedStripLeadingZeroInts(result);
163.1175 +        return new BigInteger(result, signum == val.signum ? 1 : -1);
163.1176 +    }
163.1177 +
163.1178 +    /**
163.1179 +     * Package private methods used by BigDecimal code to multiply a BigInteger
163.1180 +     * with a long. Assumes v is not equal to INFLATED.
163.1181 +     */
163.1182 +    BigInteger multiply(long v) {
163.1183 +        if (v == 0 || signum == 0)
163.1184 +          return ZERO;
163.1185 +        if (v == BigDecimal.INFLATED)
163.1186 +            return multiply(BigInteger.valueOf(v));
163.1187 +        int rsign = (v > 0 ? signum : -signum);
163.1188 +        if (v < 0)
163.1189 +            v = -v;
163.1190 +        long dh = v >>> 32;      // higher order bits
163.1191 +        long dl = v & LONG_MASK; // lower order bits
163.1192 +
163.1193 +        int xlen = mag.length;
163.1194 +        int[] value = mag;
163.1195 +        int[] rmag = (dh == 0L) ? (new int[xlen + 1]) : (new int[xlen + 2]);
163.1196 +        long carry = 0;
163.1197 +        int rstart = rmag.length - 1;
163.1198 +        for (int i = xlen - 1; i >= 0; i--) {
163.1199 +            long product = (value[i] & LONG_MASK) * dl + carry;
163.1200 +            rmag[rstart--] = (int)product;
163.1201 +            carry = product >>> 32;
163.1202 +        }
163.1203 +        rmag[rstart] = (int)carry;
163.1204 +        if (dh != 0L) {
163.1205 +            carry = 0;
163.1206 +            rstart = rmag.length - 2;
163.1207 +            for (int i = xlen - 1; i >= 0; i--) {
163.1208 +                long product = (value[i] & LONG_MASK) * dh +
163.1209 +                    (rmag[rstart] & LONG_MASK) + carry;
163.1210 +                rmag[rstart--] = (int)product;
163.1211 +                carry = product >>> 32;
163.1212 +            }
163.1213 +            rmag[0] = (int)carry;
163.1214 +        }
163.1215 +        if (carry == 0L)
163.1216 +            rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length);
163.1217 +        return new BigInteger(rmag, rsign);
163.1218 +    }
163.1219 +
163.1220 +    /**
163.1221 +     * Multiplies int arrays x and y to the specified lengths and places
163.1222 +     * the result into z. There will be no leading zeros in the resultant array.
163.1223 +     */
163.1224 +    private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
163.1225 +        int xstart = xlen - 1;
163.1226 +        int ystart = ylen - 1;
163.1227 +
163.1228 +        if (z == null || z.length < (xlen+ ylen))
163.1229 +            z = new int[xlen+ylen];
163.1230 +
163.1231 +        long carry = 0;
163.1232 +        for (int j=ystart, k=ystart+1+xstart; j>=0; j--, k--) {
163.1233 +            long product = (y[j] & LONG_MASK) *
163.1234 +                           (x[xstart] & LONG_MASK) + carry;
163.1235 +            z[k] = (int)product;
163.1236 +            carry = product >>> 32;
163.1237 +        }
163.1238 +        z[xstart] = (int)carry;
163.1239 +
163.1240 +        for (int i = xstart-1; i >= 0; i--) {
163.1241 +            carry = 0;
163.1242 +            for (int j=ystart, k=ystart+1+i; j>=0; j--, k--) {
163.1243 +                long product = (y[j] & LONG_MASK) *
163.1244 +                               (x[i] & LONG_MASK) +
163.1245 +                               (z[k] & LONG_MASK) + carry;
163.1246 +                z[k] = (int)product;
163.1247 +                carry = product >>> 32;
163.1248 +            }
163.1249 +            z[i] = (int)carry;
163.1250 +        }
163.1251 +        return z;
163.1252 +    }
163.1253 +
163.1254 +    /**
163.1255 +     * Returns a BigInteger whose value is {@code (this<sup>2</sup>)}.
163.1256 +     *
163.1257 +     * @return {@code this<sup>2</sup>}
163.1258 +     */
163.1259 +    private BigInteger square() {
163.1260 +        if (signum == 0)
163.1261 +            return ZERO;
163.1262 +        int[] z = squareToLen(mag, mag.length, null);
163.1263 +        return new BigInteger(trustedStripLeadingZeroInts(z), 1);
163.1264 +    }
163.1265 +
163.1266 +    /**
163.1267 +     * Squares the contents of the int array x. The result is placed into the
163.1268 +     * int array z.  The contents of x are not changed.
163.1269 +     */
163.1270 +    private static final int[] squareToLen(int[] x, int len, int[] z) {
163.1271 +        /*
163.1272 +         * The algorithm used here is adapted from Colin Plumb's C library.
163.1273 +         * Technique: Consider the partial products in the multiplication
163.1274 +         * of "abcde" by itself:
163.1275 +         *
163.1276 +         *               a  b  c  d  e
163.1277 +         *            *  a  b  c  d  e
163.1278 +         *          ==================
163.1279 +         *              ae be ce de ee
163.1280 +         *           ad bd cd dd de
163.1281 +         *        ac bc cc cd ce
163.1282 +         *     ab bb bc bd be
163.1283 +         *  aa ab ac ad ae
163.1284 +         *
163.1285 +         * Note that everything above the main diagonal:
163.1286 +         *              ae be ce de = (abcd) * e
163.1287 +         *           ad bd cd       = (abc) * d
163.1288 +         *        ac bc             = (ab) * c
163.1289 +         *     ab                   = (a) * b
163.1290 +         *
163.1291 +         * is a copy of everything below the main diagonal:
163.1292 +         *                       de
163.1293 +         *                 cd ce
163.1294 +         *           bc bd be
163.1295 +         *     ab ac ad ae
163.1296 +         *
163.1297 +         * Thus, the sum is 2 * (off the diagonal) + diagonal.
163.1298 +         *
163.1299 +         * This is accumulated beginning with the diagonal (which
163.1300 +         * consist of the squares of the digits of the input), which is then
163.1301 +         * divided by two, the off-diagonal added, and multiplied by two
163.1302 +         * again.  The low bit is simply a copy of the low bit of the
163.1303 +         * input, so it doesn't need special care.
163.1304 +         */
163.1305 +        int zlen = len << 1;
163.1306 +        if (z == null || z.length < zlen)
163.1307 +            z = new int[zlen];
163.1308 +
163.1309 +        // Store the squares, right shifted one bit (i.e., divided by 2)
163.1310 +        int lastProductLowWord = 0;
163.1311 +        for (int j=0, i=0; j<len; j++) {
163.1312 +            long piece = (x[j] & LONG_MASK);
163.1313 +            long product = piece * piece;
163.1314 +            z[i++] = (lastProductLowWord << 31) | (int)(product >>> 33);
163.1315 +            z[i++] = (int)(product >>> 1);
163.1316 +            lastProductLowWord = (int)product;
163.1317 +        }
163.1318 +
163.1319 +        // Add in off-diagonal sums
163.1320 +        for (int i=len, offset=1; i>0; i--, offset+=2) {
163.1321 +            int t = x[i-1];
163.1322 +            t = mulAdd(z, x, offset, i-1, t);
163.1323 +            addOne(z, offset-1, i, t);
163.1324 +        }
163.1325 +
163.1326 +        // Shift back up and set low bit
163.1327 +        primitiveLeftShift(z, zlen, 1);
163.1328 +        z[zlen-1] |= x[len-1] & 1;
163.1329 +
163.1330 +        return z;
163.1331 +    }
163.1332 +
163.1333 +    /**
163.1334 +     * Returns a BigInteger whose value is {@code (this / val)}.
163.1335 +     *
163.1336 +     * @param  val value by which this BigInteger is to be divided.
163.1337 +     * @return {@code this / val}
163.1338 +     * @throws ArithmeticException if {@code val} is zero.
163.1339 +     */
163.1340 +    public BigInteger divide(BigInteger val) {
163.1341 +        MutableBigInteger q = new MutableBigInteger(),
163.1342 +                          a = new MutableBigInteger(this.mag),
163.1343 +                          b = new MutableBigInteger(val.mag);
163.1344 +
163.1345 +        a.divide(b, q);
163.1346 +        return q.toBigInteger(this.signum == val.signum ? 1 : -1);
163.1347 +    }
163.1348 +
163.1349 +    /**
163.1350 +     * Returns an array of two BigIntegers containing {@code (this / val)}
163.1351 +     * followed by {@code (this % val)}.
163.1352 +     *
163.1353 +     * @param  val value by which this BigInteger is to be divided, and the
163.1354 +     *         remainder computed.
163.1355 +     * @return an array of two BigIntegers: the quotient {@code (this / val)}
163.1356 +     *         is the initial element, and the remainder {@code (this % val)}
163.1357 +     *         is the final element.
163.1358 +     * @throws ArithmeticException if {@code val} is zero.
163.1359 +     */
163.1360 +    public BigInteger[] divideAndRemainder(BigInteger val) {
163.1361 +        BigInteger[] result = new BigInteger[2];
163.1362 +        MutableBigInteger q = new MutableBigInteger(),
163.1363 +                          a = new MutableBigInteger(this.mag),
163.1364 +                          b = new MutableBigInteger(val.mag);
163.1365 +        MutableBigInteger r = a.divide(b, q);
163.1366 +        result[0] = q.toBigInteger(this.signum == val.signum ? 1 : -1);
163.1367 +        result[1] = r.toBigInteger(this.signum);
163.1368 +        return result;
163.1369 +    }
163.1370 +
163.1371 +    /**
163.1372 +     * Returns a BigInteger whose value is {@code (this % val)}.
163.1373 +     *
163.1374 +     * @param  val value by which this BigInteger is to be divided, and the
163.1375 +     *         remainder computed.
163.1376 +     * @return {@code this % val}
163.1377 +     * @throws ArithmeticException if {@code val} is zero.
163.1378 +     */
163.1379 +    public BigInteger remainder(BigInteger val) {
163.1380 +        MutableBigInteger q = new MutableBigInteger(),
163.1381 +                          a = new MutableBigInteger(this.mag),
163.1382 +                          b = new MutableBigInteger(val.mag);
163.1383 +
163.1384 +        return a.divide(b, q).toBigInteger(this.signum);
163.1385 +    }
163.1386 +
163.1387 +    /**
163.1388 +     * Returns a BigInteger whose value is <tt>(this<sup>exponent</sup>)</tt>.
163.1389 +     * Note that {@code exponent} is an integer rather than a BigInteger.
163.1390 +     *
163.1391 +     * @param  exponent exponent to which this BigInteger is to be raised.
163.1392 +     * @return <tt>this<sup>exponent</sup></tt>
163.1393 +     * @throws ArithmeticException {@code exponent} is negative.  (This would
163.1394 +     *         cause the operation to yield a non-integer value.)
163.1395 +     */
163.1396 +    public BigInteger pow(int exponent) {
163.1397 +        if (exponent < 0)
163.1398 +            throw new ArithmeticException("Negative exponent");
163.1399 +        if (signum==0)
163.1400 +            return (exponent==0 ? ONE : this);
163.1401 +
163.1402 +        // Perform exponentiation using repeated squaring trick
163.1403 +        int newSign = (signum<0 && (exponent&1)==1 ? -1 : 1);
163.1404 +        int[] baseToPow2 = this.mag;
163.1405 +        int[] result = {1};
163.1406 +
163.1407 +        while (exponent != 0) {
163.1408 +            if ((exponent & 1)==1) {
163.1409 +                result = multiplyToLen(result, result.length,
163.1410 +                                       baseToPow2, baseToPow2.length, null);
163.1411 +                result = trustedStripLeadingZeroInts(result);
163.1412 +            }
163.1413 +            if ((exponent >>>= 1) != 0) {
163.1414 +                baseToPow2 = squareToLen(baseToPow2, baseToPow2.length, null);
163.1415 +                baseToPow2 = trustedStripLeadingZeroInts(baseToPow2);
163.1416 +            }
163.1417 +        }
163.1418 +        return new BigInteger(result, newSign);
163.1419 +    }
163.1420 +
163.1421 +    /**
163.1422 +     * Returns a BigInteger whose value is the greatest common divisor of
163.1423 +     * {@code abs(this)} and {@code abs(val)}.  Returns 0 if
163.1424 +     * {@code this==0 && val==0}.
163.1425 +     *
163.1426 +     * @param  val value with which the GCD is to be computed.
163.1427 +     * @return {@code GCD(abs(this), abs(val))}
163.1428 +     */
163.1429 +    public BigInteger gcd(BigInteger val) {
163.1430 +        if (val.signum == 0)
163.1431 +            return this.abs();
163.1432 +        else if (this.signum == 0)
163.1433 +            return val.abs();
163.1434 +
163.1435 +        MutableBigInteger a = new MutableBigInteger(this);
163.1436 +        MutableBigInteger b = new MutableBigInteger(val);
163.1437 +
163.1438 +        MutableBigInteger result = a.hybridGCD(b);
163.1439 +
163.1440 +        return result.toBigInteger(1);
163.1441 +    }
163.1442 +
163.1443 +    /**
163.1444 +     * Package private method to return bit length for an integer.
163.1445 +     */
163.1446 +    static int bitLengthForInt(int n) {
163.1447 +        return 32 - Integer.numberOfLeadingZeros(n);
163.1448 +    }
163.1449 +
163.1450 +    /**
163.1451 +     * Left shift int array a up to len by n bits. Returns the array that
163.1452 +     * results from the shift since space may have to be reallocated.
163.1453 +     */
163.1454 +    private static int[] leftShift(int[] a, int len, int n) {
163.1455 +        int nInts = n >>> 5;
163.1456 +        int nBits = n&0x1F;
163.1457 +        int bitsInHighWord = bitLengthForInt(a[0]);
163.1458 +
163.1459 +        // If shift can be done without recopy, do so
163.1460 +        if (n <= (32-bitsInHighWord)) {
163.1461 +            primitiveLeftShift(a, len, nBits);
163.1462 +            return a;
163.1463 +        } else { // Array must be resized
163.1464 +            if (nBits <= (32-bitsInHighWord)) {
163.1465 +                int result[] = new int[nInts+len];
163.1466 +                for (int i=0; i<len; i++)
163.1467 +                    result[i] = a[i];
163.1468 +                primitiveLeftShift(result, result.length, nBits);
163.1469 +                return result;
163.1470 +            } else {
163.1471 +                int result[] = new int[nInts+len+1];
163.1472 +                for (int i=0; i<len; i++)
163.1473 +                    result[i] = a[i];
163.1474 +                primitiveRightShift(result, result.length, 32 - nBits);
163.1475 +                return result;
163.1476 +            }
163.1477 +        }
163.1478 +    }
163.1479 +
163.1480 +    // shifts a up to len right n bits assumes no leading zeros, 0<n<32
163.1481 +    static void primitiveRightShift(int[] a, int len, int n) {
163.1482 +        int n2 = 32 - n;
163.1483 +        for (int i=len-1, c=a[i]; i>0; i--) {
163.1484 +            int b = c;
163.1485 +            c = a[i-1];
163.1486 +            a[i] = (c << n2) | (b >>> n);
163.1487 +        }
163.1488 +        a[0] >>>= n;
163.1489 +    }
163.1490 +
163.1491 +    // shifts a up to len left n bits assumes no leading zeros, 0<=n<32
163.1492 +    static void primitiveLeftShift(int[] a, int len, int n) {
163.1493 +        if (len == 0 || n == 0)
163.1494 +            return;
163.1495 +
163.1496 +        int n2 = 32 - n;
163.1497 +        for (int i=0, c=a[i], m=i+len-1; i<m; i++) {
163.1498 +            int b = c;
163.1499 +            c = a[i+1];
163.1500 +            a[i] = (b << n) | (c >>> n2);
163.1501 +        }
163.1502 +        a[len-1] <<= n;
163.1503 +    }
163.1504 +
163.1505 +    /**
163.1506 +     * Calculate bitlength of contents of the first len elements an int array,
163.1507 +     * assuming there are no leading zero ints.
163.1508 +     */
163.1509 +    private static int bitLength(int[] val, int len) {
163.1510 +        if (len == 0)
163.1511 +            return 0;
163.1512 +        return ((len - 1) << 5) + bitLengthForInt(val[0]);
163.1513 +    }
163.1514 +
163.1515 +    /**
163.1516 +     * Returns a BigInteger whose value is the absolute value of this
163.1517 +     * BigInteger.
163.1518 +     *
163.1519 +     * @return {@code abs(this)}
163.1520 +     */
163.1521 +    public BigInteger abs() {
163.1522 +        return (signum >= 0 ? this : this.negate());
163.1523 +    }
163.1524 +
163.1525 +    /**
163.1526 +     * Returns a BigInteger whose value is {@code (-this)}.
163.1527 +     *
163.1528 +     * @return {@code -this}
163.1529 +     */
163.1530 +    public BigInteger negate() {
163.1531 +        return new BigInteger(this.mag, -this.signum);
163.1532 +    }
163.1533 +
163.1534 +    /**
163.1535 +     * Returns the signum function of this BigInteger.
163.1536 +     *
163.1537 +     * @return -1, 0 or 1 as the value of this BigInteger is negative, zero or
163.1538 +     *         positive.
163.1539 +     */
163.1540 +    public int signum() {
163.1541 +        return this.signum;
163.1542 +    }
163.1543 +
163.1544 +    // Modular Arithmetic Operations
163.1545 +
163.1546 +    /**
163.1547 +     * Returns a BigInteger whose value is {@code (this mod m}).  This method
163.1548 +     * differs from {@code remainder} in that it always returns a
163.1549 +     * <i>non-negative</i> BigInteger.
163.1550 +     *
163.1551 +     * @param  m the modulus.
163.1552 +     * @return {@code this mod m}
163.1553 +     * @throws ArithmeticException {@code m} &le; 0
163.1554 +     * @see    #remainder
163.1555 +     */
163.1556 +    public BigInteger mod(BigInteger m) {
163.1557 +        if (m.signum <= 0)
163.1558 +            throw new ArithmeticException("BigInteger: modulus not positive");
163.1559 +
163.1560 +        BigInteger result = this.remainder(m);
163.1561 +        return (result.signum >= 0 ? result : result.add(m));
163.1562 +    }
163.1563 +
163.1564 +    /**
163.1565 +     * Returns a BigInteger whose value is
163.1566 +     * <tt>(this<sup>exponent</sup> mod m)</tt>.  (Unlike {@code pow}, this
163.1567 +     * method permits negative exponents.)
163.1568 +     *
163.1569 +     * @param  exponent the exponent.
163.1570 +     * @param  m the modulus.
163.1571 +     * @return <tt>this<sup>exponent</sup> mod m</tt>
163.1572 +     * @throws ArithmeticException {@code m} &le; 0 or the exponent is
163.1573 +     *         negative and this BigInteger is not <i>relatively
163.1574 +     *         prime</i> to {@code m}.
163.1575 +     * @see    #modInverse
163.1576 +     */
163.1577 +    public BigInteger modPow(BigInteger exponent, BigInteger m) {
163.1578 +        if (m.signum <= 0)
163.1579 +            throw new ArithmeticException("BigInteger: modulus not positive");
163.1580 +
163.1581 +        // Trivial cases
163.1582 +        if (exponent.signum == 0)
163.1583 +            return (m.equals(ONE) ? ZERO : ONE);
163.1584 +
163.1585 +        if (this.equals(ONE))
163.1586 +            return (m.equals(ONE) ? ZERO : ONE);
163.1587 +
163.1588 +        if (this.equals(ZERO) && exponent.signum >= 0)
163.1589 +            return ZERO;
163.1590 +
163.1591 +        if (this.equals(negConst[1]) && (!exponent.testBit(0)))
163.1592 +            return (m.equals(ONE) ? ZERO : ONE);
163.1593 +
163.1594 +        boolean invertResult;
163.1595 +        if ((invertResult = (exponent.signum < 0)))
163.1596 +            exponent = exponent.negate();
163.1597 +
163.1598 +        BigInteger base = (this.signum < 0 || this.compareTo(m) >= 0
163.1599 +                           ? this.mod(m) : this);
163.1600 +        BigInteger result;
163.1601 +        if (m.testBit(0)) { // odd modulus
163.1602 +            result = base.oddModPow(exponent, m);
163.1603 +        } else {
163.1604 +            /*
163.1605 +             * Even modulus.  Tear it into an "odd part" (m1) and power of two
163.1606 +             * (m2), exponentiate mod m1, manually exponentiate mod m2, and
163.1607 +             * use Chinese Remainder Theorem to combine results.
163.1608 +             */
163.1609 +
163.1610 +            // Tear m apart into odd part (m1) and power of 2 (m2)
163.1611 +            int p = m.getLowestSetBit();   // Max pow of 2 that divides m
163.1612 +
163.1613 +            BigInteger m1 = m.shiftRight(p);  // m/2**p
163.1614 +            BigInteger m2 = ONE.shiftLeft(p); // 2**p
163.1615 +
163.1616 +            // Calculate new base from m1
163.1617 +            BigInteger base2 = (this.signum < 0 || this.compareTo(m1) >= 0
163.1618 +                                ? this.mod(m1) : this);
163.1619 +
163.1620 +            // Caculate (base ** exponent) mod m1.
163.1621 +            BigInteger a1 = (m1.equals(ONE) ? ZERO :
163.1622 +                             base2.oddModPow(exponent, m1));
163.1623 +
163.1624 +            // Calculate (this ** exponent) mod m2
163.1625 +            BigInteger a2 = base.modPow2(exponent, p);
163.1626 +
163.1627 +            // Combine results using Chinese Remainder Theorem
163.1628 +            BigInteger y1 = m2.modInverse(m1);
163.1629 +            BigInteger y2 = m1.modInverse(m2);
163.1630 +
163.1631 +            result = a1.multiply(m2).multiply(y1).add
163.1632 +                     (a2.multiply(m1).multiply(y2)).mod(m);
163.1633 +        }
163.1634 +
163.1635 +        return (invertResult ? result.modInverse(m) : result);
163.1636 +    }
163.1637 +
163.1638 +    static int[] bnExpModThreshTable = {7, 25, 81, 241, 673, 1793,
163.1639 +                                                Integer.MAX_VALUE}; // Sentinel
163.1640 +
163.1641 +    /**
163.1642 +     * Returns a BigInteger whose value is x to the power of y mod z.
163.1643 +     * Assumes: z is odd && x < z.
163.1644 +     */
163.1645 +    private BigInteger oddModPow(BigInteger y, BigInteger z) {
163.1646 +    /*
163.1647 +     * The algorithm is adapted from Colin Plumb's C library.
163.1648 +     *
163.1649 +     * The window algorithm:
163.1650 +     * The idea is to keep a running product of b1 = n^(high-order bits of exp)
163.1651 +     * and then keep appending exponent bits to it.  The following patterns
163.1652 +     * apply to a 3-bit window (k = 3):
163.1653 +     * To append   0: square
163.1654 +     * To append   1: square, multiply by n^1
163.1655 +     * To append  10: square, multiply by n^1, square
163.1656 +     * To append  11: square, square, multiply by n^3
163.1657 +     * To append 100: square, multiply by n^1, square, square
163.1658 +     * To append 101: square, square, square, multiply by n^5
163.1659 +     * To append 110: square, square, multiply by n^3, square
163.1660 +     * To append 111: square, square, square, multiply by n^7
163.1661 +     *
163.1662 +     * Since each pattern involves only one multiply, the longer the pattern
163.1663 +     * the better, except that a 0 (no multiplies) can be appended directly.
163.1664 +     * We precompute a table of odd powers of n, up to 2^k, and can then
163.1665 +     * multiply k bits of exponent at a time.  Actually, assuming random
163.1666 +     * exponents, there is on average one zero bit between needs to
163.1667 +     * multiply (1/2 of the time there's none, 1/4 of the time there's 1,
163.1668 +     * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so
163.1669 +     * you have to do one multiply per k+1 bits of exponent.
163.1670 +     *
163.1671 +     * The loop walks down the exponent, squaring the result buffer as
163.1672 +     * it goes.  There is a wbits+1 bit lookahead buffer, buf, that is
163.1673 +     * filled with the upcoming exponent bits.  (What is read after the
163.1674 +     * end of the exponent is unimportant, but it is filled with zero here.)
163.1675 +     * When the most-significant bit of this buffer becomes set, i.e.
163.1676 +     * (buf & tblmask) != 0, we have to decide what pattern to multiply
163.1677 +     * by, and when to do it.  We decide, remember to do it in future
163.1678 +     * after a suitable number of squarings have passed (e.g. a pattern
163.1679 +     * of "100" in the buffer requires that we multiply by n^1 immediately;
163.1680 +     * a pattern of "110" calls for multiplying by n^3 after one more
163.1681 +     * squaring), clear the buffer, and continue.
163.1682 +     *
163.1683 +     * When we start, there is one more optimization: the result buffer
163.1684 +     * is implcitly one, so squaring it or multiplying by it can be
163.1685 +     * optimized away.  Further, if we start with a pattern like "100"
163.1686 +     * in the lookahead window, rather than placing n into the buffer
163.1687 +     * and then starting to square it, we have already computed n^2
163.1688 +     * to compute the odd-powers table, so we can place that into
163.1689 +     * the buffer and save a squaring.
163.1690 +     *
163.1691 +     * This means that if you have a k-bit window, to compute n^z,
163.1692 +     * where z is the high k bits of the exponent, 1/2 of the time
163.1693 +     * it requires no squarings.  1/4 of the time, it requires 1
163.1694 +     * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
163.1695 +     * And the remaining 1/2^(k-1) of the time, the top k bits are a
163.1696 +     * 1 followed by k-1 0 bits, so it again only requires k-2
163.1697 +     * squarings, not k-1.  The average of these is 1.  Add that
163.1698 +     * to the one squaring we have to do to compute the table,
163.1699 +     * and you'll see that a k-bit window saves k-2 squarings
163.1700 +     * as well as reducing the multiplies.  (It actually doesn't
163.1701 +     * hurt in the case k = 1, either.)
163.1702 +     */
163.1703 +        // Special case for exponent of one
163.1704 +        if (y.equals(ONE))
163.1705 +            return this;
163.1706 +
163.1707 +        // Special case for base of zero
163.1708 +        if (signum==0)
163.1709 +            return ZERO;
163.1710 +
163.1711 +        int[] base = mag.clone();
163.1712 +        int[] exp = y.mag;
163.1713 +        int[] mod = z.mag;
163.1714 +        int modLen = mod.length;
163.1715 +
163.1716 +        // Select an appropriate window size
163.1717 +        int wbits = 0;
163.1718 +        int ebits = bitLength(exp, exp.length);
163.1719 +        // if exponent is 65537 (0x10001), use minimum window size
163.1720 +        if ((ebits != 17) || (exp[0] != 65537)) {
163.1721 +            while (ebits > bnExpModThreshTable[wbits]) {
163.1722 +                wbits++;
163.1723 +            }
163.1724 +        }
163.1725 +
163.1726 +        // Calculate appropriate table size
163.1727 +        int tblmask = 1 << wbits;
163.1728 +
163.1729 +        // Allocate table for precomputed odd powers of base in Montgomery form
163.1730 +        int[][] table = new int[tblmask][];
163.1731 +        for (int i=0; i<tblmask; i++)
163.1732 +            table[i] = new int[modLen];
163.1733 +
163.1734 +        // Compute the modular inverse
163.1735 +        int inv = -MutableBigInteger.inverseMod32(mod[modLen-1]);
163.1736 +
163.1737 +        // Convert base to Montgomery form
163.1738 +        int[] a = leftShift(base, base.length, modLen << 5);
163.1739 +
163.1740 +        MutableBigInteger q = new MutableBigInteger(),
163.1741 +                          a2 = new MutableBigInteger(a),
163.1742 +                          b2 = new MutableBigInteger(mod);
163.1743 +
163.1744 +        MutableBigInteger r= a2.divide(b2, q);
163.1745 +        table[0] = r.toIntArray();
163.1746 +
163.1747 +        // Pad table[0] with leading zeros so its length is at least modLen
163.1748 +        if (table[0].length < modLen) {
163.1749 +           int offset = modLen - table[0].length;
163.1750 +           int[] t2 = new int[modLen];
163.1751 +           for (int i=0; i<table[0].length; i++)
163.1752 +               t2[i+offset] = table[0][i];
163.1753 +           table[0] = t2;
163.1754 +        }
163.1755 +
163.1756 +        // Set b to the square of the base
163.1757 +        int[] b = squareToLen(table[0], modLen, null);
163.1758 +        b = montReduce(b, mod, modLen, inv);
163.1759 +
163.1760 +        // Set t to high half of b
163.1761 +        int[] t = new int[modLen];
163.1762 +        for(int i=0; i<modLen; i++)
163.1763 +            t[i] = b[i];
163.1764 +
163.1765 +        // Fill in the table with odd powers of the base
163.1766 +        for (int i=1; i<tblmask; i++) {
163.1767 +            int[] prod = multiplyToLen(t, modLen, table[i-1], modLen, null);
163.1768 +            table[i] = montReduce(prod, mod, modLen, inv);
163.1769 +        }
163.1770 +
163.1771 +        // Pre load the window that slides over the exponent
163.1772 +        int bitpos = 1 << ((ebits-1) & (32-1));
163.1773 +
163.1774 +        int buf = 0;
163.1775 +        int elen = exp.length;
163.1776 +        int eIndex = 0;
163.1777 +        for (int i = 0; i <= wbits; i++) {
163.1778 +            buf = (buf << 1) | (((exp[eIndex] & bitpos) != 0)?1:0);
163.1779 +            bitpos >>>= 1;
163.1780 +            if (bitpos == 0) {
163.1781 +                eIndex++;
163.1782 +                bitpos = 1 << (32-1);
163.1783 +                elen--;
163.1784 +            }
163.1785 +        }
163.1786 +
163.1787 +        int multpos = ebits;
163.1788 +
163.1789 +        // The first iteration, which is hoisted out of the main loop
163.1790 +        ebits--;
163.1791 +        boolean isone = true;
163.1792 +
163.1793 +        multpos = ebits - wbits;
163.1794 +        while ((buf & 1) == 0) {
163.1795 +            buf >>>= 1;
163.1796 +            multpos++;
163.1797 +        }
163.1798 +
163.1799 +        int[] mult = table[buf >>> 1];
163.1800 +
163.1801 +        buf = 0;
163.1802 +        if (multpos == ebits)
163.1803 +            isone = false;
163.1804 +
163.1805 +        // The main loop
163.1806 +        while(true) {
163.1807 +            ebits--;
163.1808 +            // Advance the window
163.1809 +            buf <<= 1;
163.1810 +
163.1811 +            if (elen != 0) {
163.1812 +                buf |= ((exp[eIndex] & bitpos) != 0) ? 1 : 0;
163.1813 +                bitpos >>>= 1;
163.1814 +                if (bitpos == 0) {
163.1815 +                    eIndex++;
163.1816 +                    bitpos = 1 << (32-1);
163.1817 +                    elen--;
163.1818 +                }
163.1819 +            }
163.1820 +
163.1821 +            // Examine the window for pending multiplies
163.1822 +            if ((buf & tblmask) != 0) {
163.1823 +                multpos = ebits - wbits;
163.1824 +                while ((buf & 1) == 0) {
163.1825 +                    buf >>>= 1;
163.1826 +                    multpos++;
163.1827 +                }
163.1828 +                mult = table[buf >>> 1];
163.1829 +                buf = 0;
163.1830 +            }
163.1831 +
163.1832 +            // Perform multiply
163.1833 +            if (ebits == multpos) {
163.1834 +                if (isone) {
163.1835 +                    b = mult.clone();
163.1836 +                    isone = false;
163.1837 +                } else {
163.1838 +                    t = b;
163.1839 +                    a = multiplyToLen(t, modLen, mult, modLen, a);
163.1840 +                    a = montReduce(a, mod, modLen, inv);
163.1841 +                    t = a; a = b; b = t;
163.1842 +                }
163.1843 +            }
163.1844 +
163.1845 +            // Check if done
163.1846 +            if (ebits == 0)
163.1847 +                break;
163.1848 +
163.1849 +            // Square the input
163.1850 +            if (!isone) {
163.1851 +                t = b;
163.1852 +                a = squareToLen(t, modLen, a);
163.1853 +                a = montReduce(a, mod, modLen, inv);
163.1854 +                t = a; a = b; b = t;
163.1855 +            }
163.1856 +        }
163.1857 +
163.1858 +        // Convert result out of Montgomery form and return
163.1859 +        int[] t2 = new int[2*modLen];
163.1860 +        for(int i=0; i<modLen; i++)
163.1861 +            t2[i+modLen] = b[i];
163.1862 +
163.1863 +        b = montReduce(t2, mod, modLen, inv);
163.1864 +
163.1865 +        t2 = new int[modLen];
163.1866 +        for(int i=0; i<modLen; i++)
163.1867 +            t2[i] = b[i];
163.1868 +
163.1869 +        return new BigInteger(1, t2);
163.1870 +    }
163.1871 +
163.1872 +    /**
163.1873 +     * Montgomery reduce n, modulo mod.  This reduces modulo mod and divides
163.1874 +     * by 2^(32*mlen). Adapted from Colin Plumb's C library.
163.1875 +     */
163.1876 +    private static int[] montReduce(int[] n, int[] mod, int mlen, int inv) {
163.1877 +        int c=0;
163.1878 +        int len = mlen;
163.1879 +        int offset=0;
163.1880 +
163.1881 +        do {
163.1882 +            int nEnd = n[n.length-1-offset];
163.1883 +            int carry = mulAdd(n, mod, offset, mlen, inv * nEnd);
163.1884 +            c += addOne(n, offset, mlen, carry);
163.1885 +            offset++;
163.1886 +        } while(--len > 0);
163.1887 +
163.1888 +        while(c>0)
163.1889 +            c += subN(n, mod, mlen);
163.1890 +
163.1891 +        while (intArrayCmpToLen(n, mod, mlen) >= 0)
163.1892 +            subN(n, mod, mlen);
163.1893 +
163.1894 +        return n;
163.1895 +    }
163.1896 +
163.1897 +
163.1898 +    /*
163.1899 +     * Returns -1, 0 or +1 as big-endian unsigned int array arg1 is less than,
163.1900 +     * equal to, or greater than arg2 up to length len.
163.1901 +     */
163.1902 +    private static int intArrayCmpToLen(int[] arg1, int[] arg2, int len) {
163.1903 +        for (int i=0; i<len; i++) {
163.1904 +            long b1 = arg1[i] & LONG_MASK;
163.1905 +            long b2 = arg2[i] & LONG_MASK;
163.1906 +            if (b1 < b2)
163.1907 +                return -1;
163.1908 +            if (b1 > b2)
163.1909 +                return 1;
163.1910 +        }
163.1911 +        return 0;
163.1912 +    }
163.1913 +
163.1914 +    /**
163.1915 +     * Subtracts two numbers of same length, returning borrow.
163.1916 +     */
163.1917 +    private static int subN(int[] a, int[] b, int len) {
163.1918 +        long sum = 0;
163.1919 +
163.1920 +        while(--len >= 0) {
163.1921 +            sum = (a[len] & LONG_MASK) -
163.1922 +                 (b[len] & LONG_MASK) + (sum >> 32);
163.1923 +            a[len] = (int)sum;
163.1924 +        }
163.1925 +
163.1926 +        return (int)(sum >> 32);
163.1927 +    }
163.1928 +
163.1929 +    /**
163.1930 +     * Multiply an array by one word k and add to result, return the carry
163.1931 +     */
163.1932 +    static int mulAdd(int[] out, int[] in, int offset, int len, int k) {
163.1933 +        long kLong = k & LONG_MASK;
163.1934 +        long carry = 0;
163.1935 +
163.1936 +        offset = out.length-offset - 1;
163.1937 +        for (int j=len-1; j >= 0; j--) {
163.1938 +            long product = (in[j] & LONG_MASK) * kLong +
163.1939 +                           (out[offset] & LONG_MASK) + carry;
163.1940 +            out[offset--] = (int)product;
163.1941 +            carry = product >>> 32;
163.1942 +        }
163.1943 +        return (int)carry;
163.1944 +    }
163.1945 +
163.1946 +    /**
163.1947 +     * Add one word to the number a mlen words into a. Return the resulting
163.1948 +     * carry.
163.1949 +     */
163.1950 +    static int addOne(int[] a, int offset, int mlen, int carry) {
163.1951 +        offset = a.length-1-mlen-offset;
163.1952 +        long t = (a[offset] & LONG_MASK) + (carry & LONG_MASK);
163.1953 +
163.1954 +        a[offset] = (int)t;
163.1955 +        if ((t >>> 32) == 0)
163.1956 +            return 0;
163.1957 +        while (--mlen >= 0) {
163.1958 +            if (--offset < 0) { // Carry out of number
163.1959 +                return 1;
163.1960 +            } else {
163.1961 +                a[offset]++;
163.1962 +                if (a[offset] != 0)
163.1963 +                    return 0;
163.1964 +            }
163.1965 +        }
163.1966 +        return 1;
163.1967 +    }
163.1968 +
163.1969 +    /**
163.1970 +     * Returns a BigInteger whose value is (this ** exponent) mod (2**p)
163.1971 +     */
163.1972 +    private BigInteger modPow2(BigInteger exponent, int p) {
163.1973 +        /*
163.1974 +         * Perform exponentiation using repeated squaring trick, chopping off
163.1975 +         * high order bits as indicated by modulus.
163.1976 +         */
163.1977 +        BigInteger result = valueOf(1);
163.1978 +        BigInteger baseToPow2 = this.mod2(p);
163.1979 +        int expOffset = 0;
163.1980 +
163.1981 +        int limit = exponent.bitLength();
163.1982 +
163.1983 +        if (this.testBit(0))
163.1984 +           limit = (p-1) < limit ? (p-1) : limit;
163.1985 +
163.1986 +        while (expOffset < limit) {
163.1987 +            if (exponent.testBit(expOffset))
163.1988 +                result = result.multiply(baseToPow2).mod2(p);
163.1989 +            expOffset++;
163.1990 +            if (expOffset < limit)
163.1991 +                baseToPow2 = baseToPow2.square().mod2(p);
163.1992 +        }
163.1993 +
163.1994 +        return result;
163.1995 +    }
163.1996 +
163.1997 +    /**
163.1998 +     * Returns a BigInteger whose value is this mod(2**p).
163.1999 +     * Assumes that this {@code BigInteger >= 0} and {@code p > 0}.
163.2000 +     */
163.2001 +    private BigInteger mod2(int p) {
163.2002 +        if (bitLength() <= p)
163.2003 +            return this;
163.2004 +
163.2005 +        // Copy remaining ints of mag
163.2006 +        int numInts = (p + 31) >>> 5;
163.2007 +        int[] mag = new int[numInts];
163.2008 +        for (int i=0; i<numInts; i++)
163.2009 +            mag[i] = this.mag[i + (this.mag.length - numInts)];
163.2010 +
163.2011 +        // Mask out any excess bits
163.2012 +        int excessBits = (numInts << 5) - p;
163.2013 +        mag[0] &= (1L << (32-excessBits)) - 1;
163.2014 +
163.2015 +        return (mag[0]==0 ? new BigInteger(1, mag) : new BigInteger(mag, 1));
163.2016 +    }
163.2017 +
163.2018 +    /**
163.2019 +     * Returns a BigInteger whose value is {@code (this}<sup>-1</sup> {@code mod m)}.
163.2020 +     *
163.2021 +     * @param  m the modulus.
163.2022 +     * @return {@code this}<sup>-1</sup> {@code mod m}.
163.2023 +     * @throws ArithmeticException {@code  m} &le; 0, or this BigInteger
163.2024 +     *         has no multiplicative inverse mod m (that is, this BigInteger
163.2025 +     *         is not <i>relatively prime</i> to m).
163.2026 +     */
163.2027 +    public BigInteger modInverse(BigInteger m) {
163.2028 +        if (m.signum != 1)
163.2029 +            throw new ArithmeticException("BigInteger: modulus not positive");
163.2030 +
163.2031 +        if (m.equals(ONE))
163.2032 +            return ZERO;
163.2033 +
163.2034 +        // Calculate (this mod m)
163.2035 +        BigInteger modVal = this;
163.2036 +        if (signum < 0 || (this.compareMagnitude(m) >= 0))
163.2037 +            modVal = this.mod(m);
163.2038 +
163.2039 +        if (modVal.equals(ONE))
163.2040 +            return ONE;
163.2041 +
163.2042 +        MutableBigInteger a = new MutableBigInteger(modVal);
163.2043 +        MutableBigInteger b = new MutableBigInteger(m);
163.2044 +
163.2045 +        MutableBigInteger result = a.mutableModInverse(b);
163.2046 +        return result.toBigInteger(1);
163.2047 +    }
163.2048 +
163.2049 +    // Shift Operations
163.2050 +
163.2051 +    /**
163.2052 +     * Returns a BigInteger whose value is {@code (this << n)}.
163.2053 +     * The shift distance, {@code n}, may be negative, in which case
163.2054 +     * this method performs a right shift.
163.2055 +     * (Computes <tt>floor(this * 2<sup>n</sup>)</tt>.)
163.2056 +     *
163.2057 +     * @param  n shift distance, in bits.
163.2058 +     * @return {@code this << n}
163.2059 +     * @throws ArithmeticException if the shift distance is {@code
163.2060 +     *         Integer.MIN_VALUE}.
163.2061 +     * @see #shiftRight
163.2062 +     */
163.2063 +    public BigInteger shiftLeft(int n) {
163.2064 +        if (signum == 0)
163.2065 +            return ZERO;
163.2066 +        if (n==0)
163.2067 +            return this;
163.2068 +        if (n<0) {
163.2069 +            if (n == Integer.MIN_VALUE) {
163.2070 +                throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
163.2071 +            } else {
163.2072 +                return shiftRight(-n);
163.2073 +            }
163.2074 +        }
163.2075 +
163.2076 +        int nInts = n >>> 5;
163.2077 +        int nBits = n & 0x1f;
163.2078 +        int magLen = mag.length;
163.2079 +        int newMag[] = null;
163.2080 +
163.2081 +        if (nBits == 0) {
163.2082 +            newMag = new int[magLen + nInts];
163.2083 +            for (int i=0; i<magLen; i++)
163.2084 +                newMag[i] = mag[i];
163.2085 +        } else {
163.2086 +            int i = 0;
163.2087 +            int nBits2 = 32 - nBits;
163.2088 +            int highBits = mag[0] >>> nBits2;
163.2089 +            if (highBits != 0) {
163.2090 +                newMag = new int[magLen + nInts + 1];
163.2091 +                newMag[i++] = highBits;
163.2092 +            } else {
163.2093 +                newMag = new int[magLen + nInts];
163.2094 +            }
163.2095 +            int j=0;
163.2096 +            while (j < magLen-1)
163.2097 +                newMag[i++] = mag[j++] << nBits | mag[j] >>> nBits2;
163.2098 +            newMag[i] = mag[j] << nBits;
163.2099 +        }
163.2100 +
163.2101 +        return new BigInteger(newMag, signum);
163.2102 +    }
163.2103 +
163.2104 +    /**
163.2105 +     * Returns a BigInteger whose value is {@code (this >> n)}.  Sign
163.2106 +     * extension is performed.  The shift distance, {@code n}, may be
163.2107 +     * negative, in which case this method performs a left shift.
163.2108 +     * (Computes <tt>floor(this / 2<sup>n</sup>)</tt>.)
163.2109 +     *
163.2110 +     * @param  n shift distance, in bits.
163.2111 +     * @return {@code this >> n}
163.2112 +     * @throws ArithmeticException if the shift distance is {@code
163.2113 +     *         Integer.MIN_VALUE}.
163.2114 +     * @see #shiftLeft
163.2115 +     */
163.2116 +    public BigInteger shiftRight(int n) {
163.2117 +        if (n==0)
163.2118 +            return this;
163.2119 +        if (n<0) {
163.2120 +            if (n == Integer.MIN_VALUE) {
163.2121 +                throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
163.2122 +            } else {
163.2123 +                return shiftLeft(-n);
163.2124 +            }
163.2125 +        }
163.2126 +
163.2127 +        int nInts = n >>> 5;
163.2128 +        int nBits = n & 0x1f;
163.2129 +        int magLen = mag.length;
163.2130 +        int newMag[] = null;
163.2131 +
163.2132 +        // Special case: entire contents shifted off the end
163.2133 +        if (nInts >= magLen)
163.2134 +            return (signum >= 0 ? ZERO : negConst[1]);
163.2135 +
163.2136 +        if (nBits == 0) {
163.2137 +            int newMagLen = magLen - nInts;
163.2138 +            newMag = new int[newMagLen];
163.2139 +            for (int i=0; i<newMagLen; i++)
163.2140 +                newMag[i] = mag[i];
163.2141 +        } else {
163.2142 +            int i = 0;
163.2143 +            int highBits = mag[0] >>> nBits;
163.2144 +            if (highBits != 0) {
163.2145 +                newMag = new int[magLen - nInts];
163.2146 +                newMag[i++] = highBits;
163.2147 +            } else {
163.2148 +                newMag = new int[magLen - nInts -1];
163.2149 +            }
163.2150 +
163.2151 +            int nBits2 = 32 - nBits;
163.2152 +            int j=0;
163.2153 +            while (j < magLen - nInts - 1)
163.2154 +                newMag[i++] = (mag[j++] << nBits2) | (mag[j] >>> nBits);
163.2155 +        }
163.2156 +
163.2157 +        if (signum < 0) {
163.2158 +            // Find out whether any one-bits were shifted off the end.
163.2159 +            boolean onesLost = false;
163.2160 +            for (int i=magLen-1, j=magLen-nInts; i>=j && !onesLost; i--)
163.2161 +                onesLost = (mag[i] != 0);
163.2162 +            if (!onesLost && nBits != 0)
163.2163 +                onesLost = (mag[magLen - nInts - 1] << (32 - nBits) != 0);
163.2164 +
163.2165 +            if (onesLost)
163.2166 +                newMag = javaIncrement(newMag);
163.2167 +        }
163.2168 +
163.2169 +        return new BigInteger(newMag, signum);
163.2170 +    }
163.2171 +
163.2172 +    int[] javaIncrement(int[] val) {
163.2173 +        int lastSum = 0;
163.2174 +        for (int i=val.length-1;  i >= 0 && lastSum == 0; i--)
163.2175 +            lastSum = (val[i] += 1);
163.2176 +        if (lastSum == 0) {
163.2177 +            val = new int[val.length+1];
163.2178 +            val[0] = 1;
163.2179 +        }
163.2180 +        return val;
163.2181 +    }
163.2182 +
163.2183 +    // Bitwise Operations
163.2184 +
163.2185 +    /**
163.2186 +     * Returns a BigInteger whose value is {@code (this & val)}.  (This
163.2187 +     * method returns a negative BigInteger if and only if this and val are
163.2188 +     * both negative.)
163.2189 +     *
163.2190 +     * @param val value to be AND'ed with this BigInteger.
163.2191 +     * @return {@code this & val}
163.2192 +     */
163.2193 +    public BigInteger and(BigInteger val) {
163.2194 +        int[] result = new int[Math.max(intLength(), val.intLength())];
163.2195 +        for (int i=0; i<result.length; i++)
163.2196 +            result[i] = (getInt(result.length-i-1)
163.2197 +                         & val.getInt(result.length-i-1));
163.2198 +
163.2199 +        return valueOf(result);
163.2200 +    }
163.2201 +
163.2202 +    /**
163.2203 +     * Returns a BigInteger whose value is {@code (this | val)}.  (This method
163.2204 +     * returns a negative BigInteger if and only if either this or val is
163.2205 +     * negative.)
163.2206 +     *
163.2207 +     * @param val value to be OR'ed with this BigInteger.
163.2208 +     * @return {@code this | val}
163.2209 +     */
163.2210 +    public BigInteger or(BigInteger val) {
163.2211 +        int[] result = new int[Math.max(intLength(), val.intLength())];
163.2212 +        for (int i=0; i<result.length; i++)
163.2213 +            result[i] = (getInt(result.length-i-1)
163.2214 +                         | val.getInt(result.length-i-1));
163.2215 +
163.2216 +        return valueOf(result);
163.2217 +    }
163.2218 +
163.2219 +    /**
163.2220 +     * Returns a BigInteger whose value is {@code (this ^ val)}.  (This method
163.2221 +     * returns a negative BigInteger if and only if exactly one of this and
163.2222 +     * val are negative.)
163.2223 +     *
163.2224 +     * @param val value to be XOR'ed with this BigInteger.
163.2225 +     * @return {@code this ^ val}
163.2226 +     */
163.2227 +    public BigInteger xor(BigInteger val) {
163.2228 +        int[] result = new int[Math.max(intLength(), val.intLength())];
163.2229 +        for (int i=0; i<result.length; i++)
163.2230 +            result[i] = (getInt(result.length-i-1)
163.2231 +                         ^ val.getInt(result.length-i-1));
163.2232 +
163.2233 +        return valueOf(result);
163.2234 +    }
163.2235 +
163.2236 +    /**
163.2237 +     * Returns a BigInteger whose value is {@code (~this)}.  (This method
163.2238 +     * returns a negative value if and only if this BigInteger is
163.2239 +     * non-negative.)
163.2240 +     *
163.2241 +     * @return {@code ~this}
163.2242 +     */
163.2243 +    public BigInteger not() {
163.2244 +        int[] result = new int[intLength()];
163.2245 +        for (int i=0; i<result.length; i++)
163.2246 +            result[i] = ~getInt(result.length-i-1);
163.2247 +
163.2248 +        return valueOf(result);
163.2249 +    }
163.2250 +
163.2251 +    /**
163.2252 +     * Returns a BigInteger whose value is {@code (this & ~val)}.  This
163.2253 +     * method, which is equivalent to {@code and(val.not())}, is provided as
163.2254 +     * a convenience for masking operations.  (This method returns a negative
163.2255 +     * BigInteger if and only if {@code this} is negative and {@code val} is
163.2256 +     * positive.)
163.2257 +     *
163.2258 +     * @param val value to be complemented and AND'ed with this BigInteger.
163.2259 +     * @return {@code this & ~val}
163.2260 +     */
163.2261 +    public BigInteger andNot(BigInteger val) {
163.2262 +        int[] result = new int[Math.max(intLength(), val.intLength())];
163.2263 +        for (int i=0; i<result.length; i++)
163.2264 +            result[i] = (getInt(result.length-i-1)
163.2265 +                         & ~val.getInt(result.length-i-1));
163.2266 +
163.2267 +        return valueOf(result);
163.2268 +    }
163.2269 +
163.2270 +
163.2271 +    // Single Bit Operations
163.2272 +
163.2273 +    /**
163.2274 +     * Returns {@code true} if and only if the designated bit is set.
163.2275 +     * (Computes {@code ((this & (1<<n)) != 0)}.)
163.2276 +     *
163.2277 +     * @param  n index of bit to test.
163.2278 +     * @return {@code true} if and only if the designated bit is set.
163.2279 +     * @throws ArithmeticException {@code n} is negative.
163.2280 +     */
163.2281 +    public boolean testBit(int n) {
163.2282 +        if (n<0)
163.2283 +            throw new ArithmeticException("Negative bit address");
163.2284 +
163.2285 +        return (getInt(n >>> 5) & (1 << (n & 31))) != 0;
163.2286 +    }
163.2287 +
163.2288 +    /**
163.2289 +     * Returns a BigInteger whose value is equivalent to this BigInteger
163.2290 +     * with the designated bit set.  (Computes {@code (this | (1<<n))}.)
163.2291 +     *
163.2292 +     * @param  n index of bit to set.
163.2293 +     * @return {@code this | (1<<n)}
163.2294 +     * @throws ArithmeticException {@code n} is negative.
163.2295 +     */
163.2296 +    public BigInteger setBit(int n) {
163.2297 +        if (n<0)
163.2298 +            throw new ArithmeticException("Negative bit address");
163.2299 +
163.2300 +        int intNum = n >>> 5;
163.2301 +        int[] result = new int[Math.max(intLength(), intNum+2)];
163.2302 +
163.2303 +        for (int i=0; i<result.length; i++)
163.2304 +            result[result.length-i-1] = getInt(i);
163.2305 +
163.2306 +        result[result.length-intNum-1] |= (1 << (n & 31));
163.2307 +
163.2308 +        return valueOf(result);
163.2309 +    }
163.2310 +
163.2311 +    /**
163.2312 +     * Returns a BigInteger whose value is equivalent to this BigInteger
163.2313 +     * with the designated bit cleared.
163.2314 +     * (Computes {@code (this & ~(1<<n))}.)
163.2315 +     *
163.2316 +     * @param  n index of bit to clear.
163.2317 +     * @return {@code this & ~(1<<n)}
163.2318 +     * @throws ArithmeticException {@code n} is negative.
163.2319 +     */
163.2320 +    public BigInteger clearBit(int n) {
163.2321 +        if (n<0)
163.2322 +            throw new ArithmeticException("Negative bit address");
163.2323 +
163.2324 +        int intNum = n >>> 5;
163.2325 +        int[] result = new int[Math.max(intLength(), ((n + 1) >>> 5) + 1)];
163.2326 +
163.2327 +        for (int i=0; i<result.length; i++)
163.2328 +            result[result.length-i-1] = getInt(i);
163.2329 +
163.2330 +        result[result.length-intNum-1] &= ~(1 << (n & 31));
163.2331 +
163.2332 +        return valueOf(result);
163.2333 +    }
163.2334 +
163.2335 +    /**
163.2336 +     * Returns a BigInteger whose value is equivalent to this BigInteger
163.2337 +     * with the designated bit flipped.
163.2338 +     * (Computes {@code (this ^ (1<<n))}.)
163.2339 +     *
163.2340 +     * @param  n index of bit to flip.
163.2341 +     * @return {@code this ^ (1<<n)}
163.2342 +     * @throws ArithmeticException {@code n} is negative.
163.2343 +     */
163.2344 +    public BigInteger flipBit(int n) {
163.2345 +        if (n<0)
163.2346 +            throw new ArithmeticException("Negative bit address");
163.2347 +
163.2348 +        int intNum = n >>> 5;
163.2349 +        int[] result = new int[Math.max(intLength(), intNum+2)];
163.2350 +
163.2351 +        for (int i=0; i<result.length; i++)
163.2352 +            result[result.length-i-1] = getInt(i);
163.2353 +
163.2354 +        result[result.length-intNum-1] ^= (1 << (n & 31));
163.2355 +
163.2356 +        return valueOf(result);
163.2357 +    }
163.2358 +
163.2359 +    /**
163.2360 +     * Returns the index of the rightmost (lowest-order) one bit in this
163.2361 +     * BigInteger (the number of zero bits to the right of the rightmost
163.2362 +     * one bit).  Returns -1 if this BigInteger contains no one bits.
163.2363 +     * (Computes {@code (this==0? -1 : log2(this & -this))}.)
163.2364 +     *
163.2365 +     * @return index of the rightmost one bit in this BigInteger.
163.2366 +     */
163.2367 +    public int getLowestSetBit() {
163.2368 +        @SuppressWarnings("deprecation") int lsb = lowestSetBit - 2;
163.2369 +        if (lsb == -2) {  // lowestSetBit not initialized yet
163.2370 +            lsb = 0;
163.2371 +            if (signum == 0) {
163.2372 +                lsb -= 1;
163.2373 +            } else {
163.2374 +                // Search for lowest order nonzero int
163.2375 +                int i,b;
163.2376 +                for (i=0; (b = getInt(i))==0; i++)
163.2377 +                    ;
163.2378 +                lsb += (i << 5) + Integer.numberOfTrailingZeros(b);
163.2379 +            }
163.2380 +            lowestSetBit = lsb + 2;
163.2381 +        }
163.2382 +        return lsb;
163.2383 +    }
163.2384 +
163.2385 +
163.2386 +    // Miscellaneous Bit Operations
163.2387 +
163.2388 +    /**
163.2389 +     * Returns the number of bits in the minimal two's-complement
163.2390 +     * representation of this BigInteger, <i>excluding</i> a sign bit.
163.2391 +     * For positive BigIntegers, this is equivalent to the number of bits in
163.2392 +     * the ordinary binary representation.  (Computes
163.2393 +     * {@code (ceil(log2(this < 0 ? -this : this+1)))}.)
163.2394 +     *
163.2395 +     * @return number of bits in the minimal two's-complement
163.2396 +     *         representation of this BigInteger, <i>excluding</i> a sign bit.
163.2397 +     */
163.2398 +    public int bitLength() {
163.2399 +        @SuppressWarnings("deprecation") int n = bitLength - 1;
163.2400 +        if (n == -1) { // bitLength not initialized yet
163.2401 +            int[] m = mag;
163.2402 +            int len = m.length;
163.2403 +            if (len == 0) {
163.2404 +                n = 0; // offset by one to initialize
163.2405 +            }  else {
163.2406 +                // Calculate the bit length of the magnitude
163.2407 +                int magBitLength = ((len - 1) << 5) + bitLengthForInt(mag[0]);
163.2408 +                 if (signum < 0) {
163.2409 +                     // Check if magnitude is a power of two
163.2410 +                     boolean pow2 = (Integer.bitCount(mag[0]) == 1);
163.2411 +                     for(int i=1; i< len && pow2; i++)
163.2412 +                         pow2 = (mag[i] == 0);
163.2413 +
163.2414 +                     n = (pow2 ? magBitLength -1 : magBitLength);
163.2415 +                 } else {
163.2416 +                     n = magBitLength;
163.2417 +                 }
163.2418 +            }
163.2419 +            bitLength = n + 1;
163.2420 +        }
163.2421 +        return n;
163.2422 +    }
163.2423 +
163.2424 +    /**
163.2425 +     * Returns the number of bits in the two's complement representation
163.2426 +     * of this BigInteger that differ from its sign bit.  This method is
163.2427 +     * useful when implementing bit-vector style sets atop BigIntegers.
163.2428 +     *
163.2429 +     * @return number of bits in the two's complement representation
163.2430 +     *         of this BigInteger that differ from its sign bit.
163.2431 +     */
163.2432 +    public int bitCount() {
163.2433 +        @SuppressWarnings("deprecation") int bc = bitCount - 1;
163.2434 +        if (bc == -1) {  // bitCount not initialized yet
163.2435 +            bc = 0;      // offset by one to initialize
163.2436 +            // Count the bits in the magnitude
163.2437 +            for (int i=0; i<mag.length; i++)
163.2438 +                bc += Integer.bitCount(mag[i]);
163.2439 +            if (signum < 0) {
163.2440 +                // Count the trailing zeros in the magnitude
163.2441 +                int magTrailingZeroCount = 0, j;
163.2442 +                for (j=mag.length-1; mag[j]==0; j--)
163.2443 +                    magTrailingZeroCount += 32;
163.2444 +                magTrailingZeroCount += Integer.numberOfTrailingZeros(mag[j]);
163.2445 +                bc += magTrailingZeroCount - 1;
163.2446 +            }
163.2447 +            bitCount = bc + 1;
163.2448 +        }
163.2449 +        return bc;
163.2450 +    }
163.2451 +
163.2452 +    // Primality Testing
163.2453 +
163.2454 +    /**
163.2455 +     * Returns {@code true} if this BigInteger is probably prime,
163.2456 +     * {@code false} if it's definitely composite.  If
163.2457 +     * {@code certainty} is &le; 0, {@code true} is
163.2458 +     * returned.
163.2459 +     *
163.2460 +     * @param  certainty a measure of the uncertainty that the caller is
163.2461 +     *         willing to tolerate: if the call returns {@code true}
163.2462 +     *         the probability that this BigInteger is prime exceeds
163.2463 +     *         (1 - 1/2<sup>{@code certainty}</sup>).  The execution time of
163.2464 +     *         this method is proportional to the value of this parameter.
163.2465 +     * @return {@code true} if this BigInteger is probably prime,
163.2466 +     *         {@code false} if it's definitely composite.
163.2467 +     */
163.2468 +    public boolean isProbablePrime(int certainty) {
163.2469 +        if (certainty <= 0)
163.2470 +            return true;
163.2471 +        BigInteger w = this.abs();
163.2472 +        if (w.equals(TWO))
163.2473 +            return true;
163.2474 +        if (!w.testBit(0) || w.equals(ONE))
163.2475 +            return false;
163.2476 +
163.2477 +        return w.primeToCertainty(certainty, null);
163.2478 +    }
163.2479 +
163.2480 +    // Comparison Operations
163.2481 +
163.2482 +    /**
163.2483 +     * Compares this BigInteger with the specified BigInteger.  This
163.2484 +     * method is provided in preference to individual methods for each
163.2485 +     * of the six boolean comparison operators ({@literal <}, ==,
163.2486 +     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The suggested
163.2487 +     * idiom for performing these comparisons is: {@code
163.2488 +     * (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
163.2489 +     * &lt;<i>op</i>&gt; is one of the six comparison operators.
163.2490 +     *
163.2491 +     * @param  val BigInteger to which this BigInteger is to be compared.
163.2492 +     * @return -1, 0 or 1 as this BigInteger is numerically less than, equal
163.2493 +     *         to, or greater than {@code val}.
163.2494 +     */
163.2495 +    public int compareTo(BigInteger val) {
163.2496 +        if (signum == val.signum) {
163.2497 +            switch (signum) {
163.2498 +            case 1:
163.2499 +                return compareMagnitude(val);
163.2500 +            case -1:
163.2501 +                return val.compareMagnitude(this);
163.2502 +            default:
163.2503 +                return 0;
163.2504 +            }
163.2505 +        }
163.2506 +        return signum > val.signum ? 1 : -1;
163.2507 +    }
163.2508 +
163.2509 +    /**
163.2510 +     * Compares the magnitude array of this BigInteger with the specified
163.2511 +     * BigInteger's. This is the version of compareTo ignoring sign.
163.2512 +     *
163.2513 +     * @param val BigInteger whose magnitude array to be compared.
163.2514 +     * @return -1, 0 or 1 as this magnitude array is less than, equal to or
163.2515 +     *         greater than the magnitude aray for the specified BigInteger's.
163.2516 +     */
163.2517 +    final int compareMagnitude(BigInteger val) {
163.2518 +        int[] m1 = mag;
163.2519 +        int len1 = m1.length;
163.2520 +        int[] m2 = val.mag;
163.2521 +        int len2 = m2.length;
163.2522 +        if (len1 < len2)
163.2523 +            return -1;
163.2524 +        if (len1 > len2)
163.2525 +            return 1;
163.2526 +        for (int i = 0; i < len1; i++) {
163.2527 +            int a = m1[i];
163.2528 +            int b = m2[i];
163.2529 +            if (a != b)
163.2530 +                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
163.2531 +        }
163.2532 +        return 0;
163.2533 +    }
163.2534 +
163.2535 +    /**
163.2536 +     * Compares this BigInteger with the specified Object for equality.
163.2537 +     *
163.2538 +     * @param  x Object to which this BigInteger is to be compared.
163.2539 +     * @return {@code true} if and only if the specified Object is a
163.2540 +     *         BigInteger whose value is numerically equal to this BigInteger.
163.2541 +     */
163.2542 +    public boolean equals(Object x) {
163.2543 +        // This test is just an optimization, which may or may not help
163.2544 +        if (x == this)
163.2545 +            return true;
163.2546 +
163.2547 +        if (!(x instanceof BigInteger))
163.2548 +            return false;
163.2549 +
163.2550 +        BigInteger xInt = (BigInteger) x;
163.2551 +        if (xInt.signum != signum)
163.2552 +            return false;
163.2553 +
163.2554 +        int[] m = mag;
163.2555 +        int len = m.length;
163.2556 +        int[] xm = xInt.mag;
163.2557 +        if (len != xm.length)
163.2558 +            return false;
163.2559 +
163.2560 +        for (int i = 0; i < len; i++)
163.2561 +            if (xm[i] != m[i])
163.2562 +                return false;
163.2563 +
163.2564 +        return true;
163.2565 +    }
163.2566 +
163.2567 +    /**
163.2568 +     * Returns the minimum of this BigInteger and {@code val}.
163.2569 +     *
163.2570 +     * @param  val value with which the minimum is to be computed.
163.2571 +     * @return the BigInteger whose value is the lesser of this BigInteger and
163.2572 +     *         {@code val}.  If they are equal, either may be returned.
163.2573 +     */
163.2574 +    public BigInteger min(BigInteger val) {
163.2575 +        return (compareTo(val)<0 ? this : val);
163.2576 +    }
163.2577 +
163.2578 +    /**
163.2579 +     * Returns the maximum of this BigInteger and {@code val}.
163.2580 +     *
163.2581 +     * @param  val value with which the maximum is to be computed.
163.2582 +     * @return the BigInteger whose value is the greater of this and
163.2583 +     *         {@code val}.  If they are equal, either may be returned.
163.2584 +     */
163.2585 +    public BigInteger max(BigInteger val) {
163.2586 +        return (compareTo(val)>0 ? this : val);
163.2587 +    }
163.2588 +
163.2589 +
163.2590 +    // Hash Function
163.2591 +
163.2592 +    /**
163.2593 +     * Returns the hash code for this BigInteger.
163.2594 +     *
163.2595 +     * @return hash code for this BigInteger.
163.2596 +     */
163.2597 +    public int hashCode() {
163.2598 +        int hashCode = 0;
163.2599 +
163.2600 +        for (int i=0; i<mag.length; i++)
163.2601 +            hashCode = (int)(31*hashCode + (mag[i] & LONG_MASK));
163.2602 +
163.2603 +        return hashCode * signum;
163.2604 +    }
163.2605 +
163.2606 +    /**
163.2607 +     * Returns the String representation of this BigInteger in the
163.2608 +     * given radix.  If the radix is outside the range from {@link
163.2609 +     * Character#MIN_RADIX} to {@link Character#MAX_RADIX} inclusive,
163.2610 +     * it will default to 10 (as is the case for
163.2611 +     * {@code Integer.toString}).  The digit-to-character mapping
163.2612 +     * provided by {@code Character.forDigit} is used, and a minus
163.2613 +     * sign is prepended if appropriate.  (This representation is
163.2614 +     * compatible with the {@link #BigInteger(String, int) (String,
163.2615 +     * int)} constructor.)
163.2616 +     *
163.2617 +     * @param  radix  radix of the String representation.
163.2618 +     * @return String representation of this BigInteger in the given radix.
163.2619 +     * @see    Integer#toString
163.2620 +     * @see    Character#forDigit
163.2621 +     * @see    #BigInteger(java.lang.String, int)
163.2622 +     */
163.2623 +    public String toString(int radix) {
163.2624 +        if (signum == 0)
163.2625 +            return "0";
163.2626 +        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
163.2627 +            radix = 10;
163.2628 +
163.2629 +        // Compute upper bound on number of digit groups and allocate space
163.2630 +        int maxNumDigitGroups = (4*mag.length + 6)/7;
163.2631 +        String digitGroup[] = new String[maxNumDigitGroups];
163.2632 +
163.2633 +        // Translate number to string, a digit group at a time
163.2634 +        BigInteger tmp = this.abs();
163.2635 +        int numGroups = 0;
163.2636 +        while (tmp.signum != 0) {
163.2637 +            BigInteger d = longRadix[radix];
163.2638 +
163.2639 +            MutableBigInteger q = new MutableBigInteger(),
163.2640 +                              a = new MutableBigInteger(tmp.mag),
163.2641 +                              b = new MutableBigInteger(d.mag);
163.2642 +            MutableBigInteger r = a.divide(b, q);
163.2643 +            BigInteger q2 = q.toBigInteger(tmp.signum * d.signum);
163.2644 +            BigInteger r2 = r.toBigInteger(tmp.signum * d.signum);
163.2645 +
163.2646 +            digitGroup[numGroups++] = Long.toString(r2.longValue(), radix);
163.2647 +            tmp = q2;
163.2648 +        }
163.2649 +
163.2650 +        // Put sign (if any) and first digit group into result buffer
163.2651 +        StringBuilder buf = new StringBuilder(numGroups*digitsPerLong[radix]+1);
163.2652 +        if (signum<0)
163.2653 +            buf.append('-');
163.2654 +        buf.append(digitGroup[numGroups-1]);
163.2655 +
163.2656 +        // Append remaining digit groups padded with leading zeros
163.2657 +        for (int i=numGroups-2; i>=0; i--) {
163.2658 +            // Prepend (any) leading zeros for this digit group
163.2659 +            int numLeadingZeros = digitsPerLong[radix]-digitGroup[i].length();
163.2660 +            if (numLeadingZeros != 0)
163.2661 +                buf.append(zeros[numLeadingZeros]);
163.2662 +            buf.append(digitGroup[i]);
163.2663 +        }
163.2664 +        return buf.toString();
163.2665 +    }
163.2666 +
163.2667 +    /* zero[i] is a string of i consecutive zeros. */
163.2668 +    private static String zeros[] = new String[64];
163.2669 +    static {
163.2670 +        zeros[63] =
163.2671 +            "000000000000000000000000000000000000000000000000000000000000000";
163.2672 +        for (int i=0; i<63; i++)
163.2673 +            zeros[i] = zeros[63].substring(0, i);
163.2674 +    }
163.2675 +
163.2676 +    /**
163.2677 +     * Returns the decimal String representation of this BigInteger.
163.2678 +     * The digit-to-character mapping provided by
163.2679 +     * {@code Character.forDigit} is used, and a minus sign is
163.2680 +     * prepended if appropriate.  (This representation is compatible
163.2681 +     * with the {@link #BigInteger(String) (String)} constructor, and
163.2682 +     * allows for String concatenation with Java's + operator.)
163.2683 +     *
163.2684 +     * @return decimal String representation of this BigInteger.
163.2685 +     * @see    Character#forDigit
163.2686 +     * @see    #BigInteger(java.lang.String)
163.2687 +     */
163.2688 +    public String toString() {
163.2689 +        return toString(10);
163.2690 +    }
163.2691 +
163.2692 +    /**
163.2693 +     * Returns a byte array containing the two's-complement
163.2694 +     * representation of this BigInteger.  The byte array will be in
163.2695 +     * <i>big-endian</i> byte-order: the most significant byte is in
163.2696 +     * the zeroth element.  The array will contain the minimum number
163.2697 +     * of bytes required to represent this BigInteger, including at
163.2698 +     * least one sign bit, which is {@code (ceil((this.bitLength() +
163.2699 +     * 1)/8))}.  (This representation is compatible with the
163.2700 +     * {@link #BigInteger(byte[]) (byte[])} constructor.)
163.2701 +     *
163.2702 +     * @return a byte array containing the two's-complement representation of
163.2703 +     *         this BigInteger.
163.2704 +     * @see    #BigInteger(byte[])
163.2705 +     */
163.2706 +    public byte[] toByteArray() {
163.2707 +        int byteLen = bitLength()/8 + 1;
163.2708 +        byte[] byteArray = new byte[byteLen];
163.2709 +
163.2710 +        for (int i=byteLen-1, bytesCopied=4, nextInt=0, intIndex=0; i>=0; i--) {
163.2711 +            if (bytesCopied == 4) {
163.2712 +                nextInt = getInt(intIndex++);
163.2713 +                bytesCopied = 1;
163.2714 +            } else {
163.2715 +                nextInt >>>= 8;
163.2716 +                bytesCopied++;
163.2717 +            }
163.2718 +            byteArray[i] = (byte)nextInt;
163.2719 +        }
163.2720 +        return byteArray;
163.2721 +    }
163.2722 +
163.2723 +    /**
163.2724 +     * Converts this BigInteger to an {@code int}.  This
163.2725 +     * conversion is analogous to a
163.2726 +     * <i>narrowing primitive conversion</i> from {@code long} to
163.2727 +     * {@code int} as defined in section 5.1.3 of
163.2728 +     * <cite>The Java&trade; Language Specification</cite>:
163.2729 +     * if this BigInteger is too big to fit in an
163.2730 +     * {@code int}, only the low-order 32 bits are returned.
163.2731 +     * Note that this conversion can lose information about the
163.2732 +     * overall magnitude of the BigInteger value as well as return a
163.2733 +     * result with the opposite sign.
163.2734 +     *
163.2735 +     * @return this BigInteger converted to an {@code int}.
163.2736 +     */
163.2737 +    public int intValue() {
163.2738 +        int result = 0;
163.2739 +        result = getInt(0);
163.2740 +        return result;
163.2741 +    }
163.2742 +
163.2743 +    /**
163.2744 +     * Converts this BigInteger to a {@code long}.  This
163.2745 +     * conversion is analogous to a
163.2746 +     * <i>narrowing primitive conversion</i> from {@code long} to
163.2747 +     * {@code int} as defined in section 5.1.3 of
163.2748 +     * <cite>The Java&trade; Language Specification</cite>:
163.2749 +     * if this BigInteger is too big to fit in a
163.2750 +     * {@code long}, only the low-order 64 bits are returned.
163.2751 +     * Note that this conversion can lose information about the
163.2752 +     * overall magnitude of the BigInteger value as well as return a
163.2753 +     * result with the opposite sign.
163.2754 +     *
163.2755 +     * @return this BigInteger converted to a {@code long}.
163.2756 +     */
163.2757 +    public long longValue() {
163.2758 +        long result = 0;
163.2759 +
163.2760 +        for (int i=1; i>=0; i--)
163.2761 +            result = (result << 32) + (getInt(i) & LONG_MASK);
163.2762 +        return result;
163.2763 +    }
163.2764 +
163.2765 +    /**
163.2766 +     * Converts this BigInteger to a {@code float}.  This
163.2767 +     * conversion is similar to the
163.2768 +     * <i>narrowing primitive conversion</i> from {@code double} to
163.2769 +     * {@code float} as defined in section 5.1.3 of
163.2770 +     * <cite>The Java&trade; Language Specification</cite>:
163.2771 +     * if this BigInteger has too great a magnitude
163.2772 +     * to represent as a {@code float}, it will be converted to
163.2773 +     * {@link Float#NEGATIVE_INFINITY} or {@link
163.2774 +     * Float#POSITIVE_INFINITY} as appropriate.  Note that even when
163.2775 +     * the return value is finite, this conversion can lose
163.2776 +     * information about the precision of the BigInteger value.
163.2777 +     *
163.2778 +     * @return this BigInteger converted to a {@code float}.
163.2779 +     */
163.2780 +    public float floatValue() {
163.2781 +        // Somewhat inefficient, but guaranteed to work.
163.2782 +        return Float.parseFloat(this.toString());
163.2783 +    }
163.2784 +
163.2785 +    /**
163.2786 +     * Converts this BigInteger to a {@code double}.  This
163.2787 +     * conversion is similar to the
163.2788 +     * <i>narrowing primitive conversion</i> from {@code double} to
163.2789 +     * {@code float} as defined in section 5.1.3 of
163.2790 +     * <cite>The Java&trade; Language Specification</cite>:
163.2791 +     * if this BigInteger has too great a magnitude
163.2792 +     * to represent as a {@code double}, it will be converted to
163.2793 +     * {@link Double#NEGATIVE_INFINITY} or {@link
163.2794 +     * Double#POSITIVE_INFINITY} as appropriate.  Note that even when
163.2795 +     * the return value is finite, this conversion can lose
163.2796 +     * information about the precision of the BigInteger value.
163.2797 +     *
163.2798 +     * @return this BigInteger converted to a {@code double}.
163.2799 +     */
163.2800 +    public double doubleValue() {
163.2801 +        // Somewhat inefficient, but guaranteed to work.
163.2802 +        return Double.parseDouble(this.toString());
163.2803 +    }
163.2804 +
163.2805 +    /**
163.2806 +     * Returns a copy of the input array stripped of any leading zero bytes.
163.2807 +     */
163.2808 +    private static int[] stripLeadingZeroInts(int val[]) {
163.2809 +        int vlen = val.length;
163.2810 +        int keep;
163.2811 +
163.2812 +        // Find first nonzero byte
163.2813 +        for (keep = 0; keep < vlen && val[keep] == 0; keep++)
163.2814 +            ;
163.2815 +        return java.util.Arrays.copyOfRange(val, keep, vlen);
163.2816 +    }
163.2817 +
163.2818 +    /**
163.2819 +     * Returns the input array stripped of any leading zero bytes.
163.2820 +     * Since the source is trusted the copying may be skipped.
163.2821 +     */
163.2822 +    private static int[] trustedStripLeadingZeroInts(int val[]) {
163.2823 +        int vlen = val.length;
163.2824 +        int keep;
163.2825 +
163.2826 +        // Find first nonzero byte
163.2827 +        for (keep = 0; keep < vlen && val[keep] == 0; keep++)
163.2828 +            ;
163.2829 +        return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen);
163.2830 +    }
163.2831 +
163.2832 +    /**
163.2833 +     * Returns a copy of the input array stripped of any leading zero bytes.
163.2834 +     */
163.2835 +    private static int[] stripLeadingZeroBytes(byte a[]) {
163.2836 +        int byteLength = a.length;
163.2837 +        int keep;
163.2838 +
163.2839 +        // Find first nonzero byte
163.2840 +        for (keep = 0; keep < byteLength && a[keep]==0; keep++)
163.2841 +            ;
163.2842 +
163.2843 +        // Allocate new array and copy relevant part of input array
163.2844 +        int intLength = ((byteLength - keep) + 3) >>> 2;
163.2845 +        int[] result = new int[intLength];
163.2846 +        int b = byteLength - 1;
163.2847 +        for (int i = intLength-1; i >= 0; i--) {
163.2848 +            result[i] = a[b--] & 0xff;
163.2849 +            int bytesRemaining = b - keep + 1;
163.2850 +            int bytesToTransfer = Math.min(3, bytesRemaining);
163.2851 +            for (int j=8; j <= (bytesToTransfer << 3); j += 8)
163.2852 +                result[i] |= ((a[b--] & 0xff) << j);
163.2853 +        }
163.2854 +        return result;
163.2855 +    }
163.2856 +
163.2857 +    /**
163.2858 +     * Takes an array a representing a negative 2's-complement number and
163.2859 +     * returns the minimal (no leading zero bytes) unsigned whose value is -a.
163.2860 +     */
163.2861 +    private static int[] makePositive(byte a[]) {
163.2862 +        int keep, k;
163.2863 +        int byteLength = a.length;
163.2864 +
163.2865 +        // Find first non-sign (0xff) byte of input
163.2866 +        for (keep=0; keep<byteLength && a[keep]==-1; keep++)
163.2867 +            ;
163.2868 +
163.2869 +
163.2870 +        /* Allocate output array.  If all non-sign bytes are 0x00, we must
163.2871 +         * allocate space for one extra output byte. */
163.2872 +        for (k=keep; k<byteLength && a[k]==0; k++)
163.2873 +            ;
163.2874 +
163.2875 +        int extraByte = (k==byteLength) ? 1 : 0;
163.2876 +        int intLength = ((byteLength - keep + extraByte) + 3)/4;
163.2877 +        int result[] = new int[intLength];
163.2878 +
163.2879 +        /* Copy one's complement of input into output, leaving extra
163.2880 +         * byte (if it exists) == 0x00 */
163.2881 +        int b = byteLength - 1;
163.2882 +        for (int i = intLength-1; i >= 0; i--) {
163.2883 +            result[i] = a[b--] & 0xff;
163.2884 +            int numBytesToTransfer = Math.min(3, b-keep+1);
163.2885 +            if (numBytesToTransfer < 0)
163.2886 +                numBytesToTransfer = 0;
163.2887 +            for (int j=8; j <= 8*numBytesToTransfer; j += 8)
163.2888 +                result[i] |= ((a[b--] & 0xff) << j);
163.2889 +
163.2890 +            // Mask indicates which bits must be complemented
163.2891 +            int mask = -1 >>> (8*(3-numBytesToTransfer));
163.2892 +            result[i] = ~result[i] & mask;
163.2893 +        }
163.2894 +
163.2895 +        // Add one to one's complement to generate two's complement
163.2896 +        for (int i=result.length-1; i>=0; i--) {
163.2897 +            result[i] = (int)((result[i] & LONG_MASK) + 1);
163.2898 +            if (result[i] != 0)
163.2899 +                break;
163.2900 +        }
163.2901 +
163.2902 +        return result;
163.2903 +    }
163.2904 +
163.2905 +    /**
163.2906 +     * Takes an array a representing a negative 2's-complement number and
163.2907 +     * returns the minimal (no leading zero ints) unsigned whose value is -a.
163.2908 +     */
163.2909 +    private static int[] makePositive(int a[]) {
163.2910 +        int keep, j;
163.2911 +
163.2912 +        // Find first non-sign (0xffffffff) int of input
163.2913 +        for (keep=0; keep<a.length && a[keep]==-1; keep++)
163.2914 +            ;
163.2915 +
163.2916 +        /* Allocate output array.  If all non-sign ints are 0x00, we must
163.2917 +         * allocate space for one extra output int. */
163.2918 +        for (j=keep; j<a.length && a[j]==0; j++)
163.2919 +            ;
163.2920 +        int extraInt = (j==a.length ? 1 : 0);
163.2921 +        int result[] = new int[a.length - keep + extraInt];
163.2922 +
163.2923 +        /* Copy one's complement of input into output, leaving extra
163.2924 +         * int (if it exists) == 0x00 */
163.2925 +        for (int i = keep; i<a.length; i++)
163.2926 +            result[i - keep + extraInt] = ~a[i];
163.2927 +
163.2928 +        // Add one to one's complement to generate two's complement
163.2929 +        for (int i=result.length-1; ++result[i]==0; i--)
163.2930 +            ;
163.2931 +
163.2932 +        return result;
163.2933 +    }
163.2934 +
163.2935 +    /*
163.2936 +     * The following two arrays are used for fast String conversions.  Both
163.2937 +     * are indexed by radix.  The first is the number of digits of the given
163.2938 +     * radix that can fit in a Java long without "going negative", i.e., the
163.2939 +     * highest integer n such that radix**n < 2**63.  The second is the
163.2940 +     * "long radix" that tears each number into "long digits", each of which
163.2941 +     * consists of the number of digits in the corresponding element in
163.2942 +     * digitsPerLong (longRadix[i] = i**digitPerLong[i]).  Both arrays have
163.2943 +     * nonsense values in their 0 and 1 elements, as radixes 0 and 1 are not
163.2944 +     * used.
163.2945 +     */
163.2946 +    private static int digitsPerLong[] = {0, 0,
163.2947 +        62, 39, 31, 27, 24, 22, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 15, 14,
163.2948 +        14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12};
163.2949 +
163.2950 +    private static BigInteger longRadix[] = {null, null,
163.2951 +        valueOf(0x4000000000000000L), valueOf(0x383d9170b85ff80bL),
163.2952 +        valueOf(0x4000000000000000L), valueOf(0x6765c793fa10079dL),
163.2953 +        valueOf(0x41c21cb8e1000000L), valueOf(0x3642798750226111L),
163.2954 +        valueOf(0x1000000000000000L), valueOf(0x12bf307ae81ffd59L),
163.2955 +        valueOf( 0xde0b6b3a7640000L), valueOf(0x4d28cb56c33fa539L),
163.2956 +        valueOf(0x1eca170c00000000L), valueOf(0x780c7372621bd74dL),
163.2957 +        valueOf(0x1e39a5057d810000L), valueOf(0x5b27ac993df97701L),
163.2958 +        valueOf(0x1000000000000000L), valueOf(0x27b95e997e21d9f1L),
163.2959 +        valueOf(0x5da0e1e53c5c8000L), valueOf( 0xb16a458ef403f19L),
163.2960 +        valueOf(0x16bcc41e90000000L), valueOf(0x2d04b7fdd9c0ef49L),
163.2961 +        valueOf(0x5658597bcaa24000L), valueOf( 0x6feb266931a75b7L),
163.2962 +        valueOf( 0xc29e98000000000L), valueOf(0x14adf4b7320334b9L),
163.2963 +        valueOf(0x226ed36478bfa000L), valueOf(0x383d9170b85ff80bL),
163.2964 +        valueOf(0x5a3c23e39c000000L), valueOf( 0x4e900abb53e6b71L),
163.2965 +        valueOf( 0x7600ec618141000L), valueOf( 0xaee5720ee830681L),
163.2966 +        valueOf(0x1000000000000000L), valueOf(0x172588ad4f5f0981L),
163.2967 +        valueOf(0x211e44f7d02c1000L), valueOf(0x2ee56725f06e5c71L),
163.2968 +        valueOf(0x41c21cb8e1000000L)};
163.2969 +
163.2970 +    /*
163.2971 +     * These two arrays are the integer analogue of above.
163.2972 +     */
163.2973 +    private static int digitsPerInt[] = {0, 0, 30, 19, 15, 13, 11,
163.2974 +        11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
163.2975 +        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5};
163.2976 +
163.2977 +    private static int intRadix[] = {0, 0,
163.2978 +        0x40000000, 0x4546b3db, 0x40000000, 0x48c27395, 0x159fd800,
163.2979 +        0x75db9c97, 0x40000000, 0x17179149, 0x3b9aca00, 0xcc6db61,
163.2980 +        0x19a10000, 0x309f1021, 0x57f6c100, 0xa2f1b6f,  0x10000000,
163.2981 +        0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d,
163.2982 +        0x6c20a40,  0x8d2d931,  0xb640000,  0xe8d4a51,  0x1269ae40,
163.2983 +        0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41,
163.2984 +        0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x39aa400
163.2985 +    };
163.2986 +
163.2987 +    /**
163.2988 +     * These routines provide access to the two's complement representation
163.2989 +     * of BigIntegers.
163.2990 +     */
163.2991 +
163.2992 +    /**
163.2993 +     * Returns the length of the two's complement representation in ints,
163.2994 +     * including space for at least one sign bit.
163.2995 +     */
163.2996 +    private int intLength() {
163.2997 +        return (bitLength() >>> 5) + 1;
163.2998 +    }
163.2999 +
163.3000 +    /* Returns sign bit */
163.3001 +    private int signBit() {
163.3002 +        return signum < 0 ? 1 : 0;
163.3003 +    }
163.3004 +
163.3005 +    /* Returns an int of sign bits */
163.3006 +    private int signInt() {
163.3007 +        return signum < 0 ? -1 : 0;
163.3008 +    }
163.3009 +
163.3010 +    /**
163.3011 +     * Returns the specified int of the little-endian two's complement
163.3012 +     * representation (int 0 is the least significant).  The int number can
163.3013 +     * be arbitrarily high (values are logically preceded by infinitely many
163.3014 +     * sign ints).
163.3015 +     */
163.3016 +    private int getInt(int n) {
163.3017 +        if (n < 0)
163.3018 +            return 0;
163.3019 +        if (n >= mag.length)
163.3020 +            return signInt();
163.3021 +
163.3022 +        int magInt = mag[mag.length-n-1];
163.3023 +
163.3024 +        return (signum >= 0 ? magInt :
163.3025 +                (n <= firstNonzeroIntNum() ? -magInt : ~magInt));
163.3026 +    }
163.3027 +
163.3028 +    /**
163.3029 +     * Returns the index of the int that contains the first nonzero int in the
163.3030 +     * little-endian binary representation of the magnitude (int 0 is the
163.3031 +     * least significant). If the magnitude is zero, return value is undefined.
163.3032 +     */
163.3033 +     private int firstNonzeroIntNum() {
163.3034 +         int fn = firstNonzeroIntNum - 2;
163.3035 +         if (fn == -2) { // firstNonzeroIntNum not initialized yet
163.3036 +             fn = 0;
163.3037 +
163.3038 +             // Search for the first nonzero int
163.3039 +             int i;
163.3040 +             int mlen = mag.length;
163.3041 +             for (i = mlen - 1; i >= 0 && mag[i] == 0; i--)
163.3042 +                 ;
163.3043 +             fn = mlen - i - 1;
163.3044 +             firstNonzeroIntNum = fn + 2; // offset by two to initialize
163.3045 +         }
163.3046 +         return fn;
163.3047 +     }
163.3048 +
163.3049 +    /** use serialVersionUID from JDK 1.1. for interoperability */
163.3050 +    private static final long serialVersionUID = -8287574255936472291L;
163.3051 +
163.3052 +    /**
163.3053 +     * Serializable fields for BigInteger.
163.3054 +     *
163.3055 +     * @serialField signum  int
163.3056 +     *              signum of this BigInteger.
163.3057 +     * @serialField magnitude int[]
163.3058 +     *              magnitude array of this BigInteger.
163.3059 +     * @serialField bitCount  int
163.3060 +     *              number of bits in this BigInteger
163.3061 +     * @serialField bitLength int
163.3062 +     *              the number of bits in the minimal two's-complement
163.3063 +     *              representation of this BigInteger
163.3064 +     * @serialField lowestSetBit int
163.3065 +     *              lowest set bit in the twos complement representation
163.3066 +     */
163.3067 +    private static final ObjectStreamField[] serialPersistentFields = {
163.3068 +        new ObjectStreamField("signum", Integer.TYPE),
163.3069 +        new ObjectStreamField("magnitude", byte[].class),
163.3070 +        new ObjectStreamField("bitCount", Integer.TYPE),
163.3071 +        new ObjectStreamField("bitLength", Integer.TYPE),
163.3072 +        new ObjectStreamField("firstNonzeroByteNum", Integer.TYPE),
163.3073 +        new ObjectStreamField("lowestSetBit", Integer.TYPE)
163.3074 +        };
163.3075 +
163.3076 +
163.3077 +
163.3078 +    /**
163.3079 +     * Save the {@code BigInteger} instance to a stream.
163.3080 +     * The magnitude of a BigInteger is serialized as a byte array for
163.3081 +     * historical reasons.
163.3082 +     *
163.3083 +     * @serialData two necessary fields are written as well as obsolete
163.3084 +     *             fields for compatibility with older versions.
163.3085 +     */
163.3086 +    private void writeObject(ObjectOutputStream s) throws IOException {
163.3087 +        // set the values of the Serializable fields
163.3088 +        ObjectOutputStream.PutField fields = s.putFields();
163.3089 +        fields.put("signum", signum);
163.3090 +        fields.put("magnitude", magSerializedForm());
163.3091 +        // The values written for cached fields are compatible with older
163.3092 +        // versions, but are ignored in readObject so don't otherwise matter.
163.3093 +        fields.put("bitCount", -1);
163.3094 +        fields.put("bitLength", -1);
163.3095 +        fields.put("lowestSetBit", -2);
163.3096 +        fields.put("firstNonzeroByteNum", -2);
163.3097 +
163.3098 +        // save them
163.3099 +        s.writeFields();
163.3100 +}
163.3101 +
163.3102 +    /**
163.3103 +     * Returns the mag array as an array of bytes.
163.3104 +     */
163.3105 +    private byte[] magSerializedForm() {
163.3106 +        int len = mag.length;
163.3107 +
163.3108 +        int bitLen = (len == 0 ? 0 : ((len - 1) << 5) + bitLengthForInt(mag[0]));
163.3109 +        int byteLen = (bitLen + 7) >>> 3;
163.3110 +        byte[] result = new byte[byteLen];
163.3111 +
163.3112 +        for (int i = byteLen - 1, bytesCopied = 4, intIndex = len - 1, nextInt = 0;
163.3113 +             i>=0; i--) {
163.3114 +            if (bytesCopied == 4) {
163.3115 +                nextInt = mag[intIndex--];
163.3116 +                bytesCopied = 1;
163.3117 +            } else {
163.3118 +                nextInt >>>= 8;
163.3119 +                bytesCopied++;
163.3120 +            }
163.3121 +            result[i] = (byte)nextInt;
163.3122 +        }
163.3123 +        return result;
163.3124 +    }
163.3125 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/rt/emul/compact/src/main/java/java/math/BitSieve.java	Wed Apr 30 15:04:10 2014 +0200
   164.3 @@ -0,0 +1,212 @@
   164.4 +/*
   164.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   164.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   164.7 + *
   164.8 + * This code is free software; you can redistribute it and/or modify it
   164.9 + * under the terms of the GNU General Public License version 2 only, as
  164.10 + * published by the Free Software Foundation.  Oracle designates this
  164.11 + * particular file as subject to the "Classpath" exception as provided
  164.12 + * by Oracle in the LICENSE file that accompanied this code.
  164.13 + *
  164.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  164.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  164.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  164.17 + * version 2 for more details (a copy is included in the LICENSE file that
  164.18 + * accompanied this code).
  164.19 + *
  164.20 + * You should have received a copy of the GNU General Public License version
  164.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  164.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  164.23 + *
  164.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  164.25 + * or visit www.oracle.com if you need additional information or have any
  164.26 + * questions.
  164.27 + */
  164.28 +
  164.29 +package java.math;
  164.30 +
  164.31 +/**
  164.32 + * A simple bit sieve used for finding prime number candidates. Allows setting
  164.33 + * and clearing of bits in a storage array. The size of the sieve is assumed to
  164.34 + * be constant to reduce overhead. All the bits of a new bitSieve are zero, and
  164.35 + * bits are removed from it by setting them.
  164.36 + *
  164.37 + * To reduce storage space and increase efficiency, no even numbers are
  164.38 + * represented in the sieve (each bit in the sieve represents an odd number).
  164.39 + * The relationship between the index of a bit and the number it represents is
  164.40 + * given by
  164.41 + * N = offset + (2*index + 1);
  164.42 + * Where N is the integer represented by a bit in the sieve, offset is some
  164.43 + * even integer offset indicating where the sieve begins, and index is the
  164.44 + * index of a bit in the sieve array.
  164.45 + *
  164.46 + * @see     BigInteger
  164.47 + * @author  Michael McCloskey
  164.48 + * @since   1.3
  164.49 + */
  164.50 +class BitSieve {
  164.51 +    /**
  164.52 +     * Stores the bits in this bitSieve.
  164.53 +     */
  164.54 +    private long bits[];
  164.55 +
  164.56 +    /**
  164.57 +     * Length is how many bits this sieve holds.
  164.58 +     */
  164.59 +    private int length;
  164.60 +
  164.61 +    /**
  164.62 +     * A small sieve used to filter out multiples of small primes in a search
  164.63 +     * sieve.
  164.64 +     */
  164.65 +    private static BitSieve smallSieve = new BitSieve();
  164.66 +
  164.67 +    /**
  164.68 +     * Construct a "small sieve" with a base of 0.  This constructor is
  164.69 +     * used internally to generate the set of "small primes" whose multiples
  164.70 +     * are excluded from sieves generated by the main (package private)
  164.71 +     * constructor, BitSieve(BigInteger base, int searchLen).  The length
  164.72 +     * of the sieve generated by this constructor was chosen for performance;
  164.73 +     * it controls a tradeoff between how much time is spent constructing
  164.74 +     * other sieves, and how much time is wasted testing composite candidates
  164.75 +     * for primality.  The length was chosen experimentally to yield good
  164.76 +     * performance.
  164.77 +     */
  164.78 +    private BitSieve() {
  164.79 +        length = 150 * 64;
  164.80 +        bits = new long[(unitIndex(length - 1) + 1)];
  164.81 +
  164.82 +        // Mark 1 as composite
  164.83 +        set(0);
  164.84 +        int nextIndex = 1;
  164.85 +        int nextPrime = 3;
  164.86 +
  164.87 +        // Find primes and remove their multiples from sieve
  164.88 +        do {
  164.89 +            sieveSingle(length, nextIndex + nextPrime, nextPrime);
  164.90 +            nextIndex = sieveSearch(length, nextIndex + 1);
  164.91 +            nextPrime = 2*nextIndex + 1;
  164.92 +        } while((nextIndex > 0) && (nextPrime < length));
  164.93 +    }
  164.94 +
  164.95 +    /**
  164.96 +     * Construct a bit sieve of searchLen bits used for finding prime number
  164.97 +     * candidates. The new sieve begins at the specified base, which must
  164.98 +     * be even.
  164.99 +     */
 164.100 +    BitSieve(BigInteger base, int searchLen) {
 164.101 +        /*
 164.102 +         * Candidates are indicated by clear bits in the sieve. As a candidates
 164.103 +         * nonprimality is calculated, a bit is set in the sieve to eliminate
 164.104 +         * it. To reduce storage space and increase efficiency, no even numbers
 164.105 +         * are represented in the sieve (each bit in the sieve represents an
 164.106 +         * odd number).
 164.107 +         */
 164.108 +        bits = new long[(unitIndex(searchLen-1) + 1)];
 164.109 +        length = searchLen;
 164.110 +        int start = 0;
 164.111 +
 164.112 +        int step = smallSieve.sieveSearch(smallSieve.length, start);
 164.113 +        int convertedStep = (step *2) + 1;
 164.114 +
 164.115 +        // Construct the large sieve at an even offset specified by base
 164.116 +        MutableBigInteger b = new MutableBigInteger(base);
 164.117 +        MutableBigInteger q = new MutableBigInteger();
 164.118 +        do {
 164.119 +            // Calculate base mod convertedStep
 164.120 +            start = b.divideOneWord(convertedStep, q);
 164.121 +
 164.122 +            // Take each multiple of step out of sieve
 164.123 +            start = convertedStep - start;
 164.124 +            if (start%2 == 0)
 164.125 +                start += convertedStep;
 164.126 +            sieveSingle(searchLen, (start-1)/2, convertedStep);
 164.127 +
 164.128 +            // Find next prime from small sieve
 164.129 +            step = smallSieve.sieveSearch(smallSieve.length, step+1);
 164.130 +            convertedStep = (step *2) + 1;
 164.131 +        } while (step > 0);
 164.132 +    }
 164.133 +
 164.134 +    /**
 164.135 +     * Given a bit index return unit index containing it.
 164.136 +     */
 164.137 +    private static int unitIndex(int bitIndex) {
 164.138 +        return bitIndex >>> 6;
 164.139 +    }
 164.140 +
 164.141 +    /**
 164.142 +     * Return a unit that masks the specified bit in its unit.
 164.143 +     */
 164.144 +    private static long bit(int bitIndex) {
 164.145 +        return 1L << (bitIndex & ((1<<6) - 1));
 164.146 +    }
 164.147 +
 164.148 +    /**
 164.149 +     * Get the value of the bit at the specified index.
 164.150 +     */
 164.151 +    private boolean get(int bitIndex) {
 164.152 +        int unitIndex = unitIndex(bitIndex);
 164.153 +        return ((bits[unitIndex] & bit(bitIndex)) != 0);
 164.154 +    }
 164.155 +
 164.156 +    /**
 164.157 +     * Set the bit at the specified index.
 164.158 +     */
 164.159 +    private void set(int bitIndex) {
 164.160 +        int unitIndex = unitIndex(bitIndex);
 164.161 +        bits[unitIndex] |= bit(bitIndex);
 164.162 +    }
 164.163 +
 164.164 +    /**
 164.165 +     * This method returns the index of the first clear bit in the search
 164.166 +     * array that occurs at or after start. It will not search past the
 164.167 +     * specified limit. It returns -1 if there is no such clear bit.
 164.168 +     */
 164.169 +    private int sieveSearch(int limit, int start) {
 164.170 +        if (start >= limit)
 164.171 +            return -1;
 164.172 +
 164.173 +        int index = start;
 164.174 +        do {
 164.175 +            if (!get(index))
 164.176 +                return index;
 164.177 +            index++;
 164.178 +        } while(index < limit-1);
 164.179 +        return -1;
 164.180 +    }
 164.181 +
 164.182 +    /**
 164.183 +     * Sieve a single set of multiples out of the sieve. Begin to remove
 164.184 +     * multiples of the specified step starting at the specified start index,
 164.185 +     * up to the specified limit.
 164.186 +     */
 164.187 +    private void sieveSingle(int limit, int start, int step) {
 164.188 +        while(start < limit) {
 164.189 +            set(start);
 164.190 +            start += step;
 164.191 +        }
 164.192 +    }
 164.193 +
 164.194 +    /**
 164.195 +     * Test probable primes in the sieve and return successful candidates.
 164.196 +     */
 164.197 +    BigInteger retrieve(BigInteger initValue, int certainty, java.util.Random random) {
 164.198 +        // Examine the sieve one long at a time to find possible primes
 164.199 +        int offset = 1;
 164.200 +        for (int i=0; i<bits.length; i++) {
 164.201 +            long nextLong = ~bits[i];
 164.202 +            for (int j=0; j<64; j++) {
 164.203 +                if ((nextLong & 1) == 1) {
 164.204 +                    BigInteger candidate = initValue.add(
 164.205 +                                           BigInteger.valueOf(offset));
 164.206 +                    if (candidate.primeToCertainty(certainty, random))
 164.207 +                        return candidate;
 164.208 +                }
 164.209 +                nextLong >>>= 1;
 164.210 +                offset+=2;
 164.211 +            }
 164.212 +        }
 164.213 +        return null;
 164.214 +    }
 164.215 +}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/rt/emul/compact/src/main/java/java/math/MathContext.java	Wed Apr 30 15:04:10 2014 +0200
   165.3 @@ -0,0 +1,326 @@
   165.4 +/*
   165.5 + * Copyright (c) 2003, 2007, 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 +/*
  165.30 + * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved.
  165.31 + */
  165.32 +
  165.33 +package java.math;
  165.34 +import java.io.*;
  165.35 +
  165.36 +/**
  165.37 + * Immutable objects which encapsulate the context settings which
  165.38 + * describe certain rules for numerical operators, such as those
  165.39 + * implemented by the {@link BigDecimal} class.
  165.40 + *
  165.41 + * <p>The base-independent settings are:
  165.42 + * <ol>
  165.43 + * <li>{@code precision}:
  165.44 + * the number of digits to be used for an operation; results are
  165.45 + * rounded to this precision
  165.46 + *
  165.47 + * <li>{@code roundingMode}:
  165.48 + * a {@link RoundingMode} object which specifies the algorithm to be
  165.49 + * used for rounding.
  165.50 + * </ol>
  165.51 + *
  165.52 + * @see     BigDecimal
  165.53 + * @see     RoundingMode
  165.54 + * @author  Mike Cowlishaw
  165.55 + * @author  Joseph D. Darcy
  165.56 + * @since 1.5
  165.57 + */
  165.58 +
  165.59 +public final class MathContext implements Serializable {
  165.60 +
  165.61 +    /* ----- Constants ----- */
  165.62 +
  165.63 +    // defaults for constructors
  165.64 +    private static final int DEFAULT_DIGITS = 9;
  165.65 +    private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;
  165.66 +    // Smallest values for digits (Maximum is Integer.MAX_VALUE)
  165.67 +    private static final int MIN_DIGITS = 0;
  165.68 +
  165.69 +    // Serialization version
  165.70 +    private static final long serialVersionUID = 5579720004786848255L;
  165.71 +
  165.72 +    /* ----- Public Properties ----- */
  165.73 +    /**
  165.74 +     *  A {@code MathContext} object whose settings have the values
  165.75 +     *  required for unlimited precision arithmetic.
  165.76 +     *  The values of the settings are:
  165.77 +     *  <code>
  165.78 +     *  precision=0 roundingMode=HALF_UP
  165.79 +     *  </code>
  165.80 +     */
  165.81 +    public static final MathContext UNLIMITED =
  165.82 +        new MathContext(0, RoundingMode.HALF_UP);
  165.83 +
  165.84 +    /**
  165.85 +     *  A {@code MathContext} object with a precision setting
  165.86 +     *  matching the IEEE 754R Decimal32 format, 7 digits, and a
  165.87 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  165.88 +     *  IEEE 754R default.
  165.89 +     */
  165.90 +    public static final MathContext DECIMAL32 =
  165.91 +        new MathContext(7, RoundingMode.HALF_EVEN);
  165.92 +
  165.93 +    /**
  165.94 +     *  A {@code MathContext} object with a precision setting
  165.95 +     *  matching the IEEE 754R Decimal64 format, 16 digits, and a
  165.96 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  165.97 +     *  IEEE 754R default.
  165.98 +     */
  165.99 +    public static final MathContext DECIMAL64 =
 165.100 +        new MathContext(16, RoundingMode.HALF_EVEN);
 165.101 +
 165.102 +    /**
 165.103 +     *  A {@code MathContext} object with a precision setting
 165.104 +     *  matching the IEEE 754R Decimal128 format, 34 digits, and a
 165.105 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
 165.106 +     *  IEEE 754R default.
 165.107 +     */
 165.108 +    public static final MathContext DECIMAL128 =
 165.109 +        new MathContext(34, RoundingMode.HALF_EVEN);
 165.110 +
 165.111 +    /* ----- Shared Properties ----- */
 165.112 +    /**
 165.113 +     * The number of digits to be used for an operation.  A value of 0
 165.114 +     * indicates that unlimited precision (as many digits as are
 165.115 +     * required) will be used.  Note that leading zeros (in the
 165.116 +     * coefficient of a number) are never significant.
 165.117 +     *
 165.118 +     * <p>{@code precision} will always be non-negative.
 165.119 +     *
 165.120 +     * @serial
 165.121 +     */
 165.122 +    final int precision;
 165.123 +
 165.124 +    /**
 165.125 +     * The rounding algorithm to be used for an operation.
 165.126 +     *
 165.127 +     * @see RoundingMode
 165.128 +     * @serial
 165.129 +     */
 165.130 +    final RoundingMode roundingMode;
 165.131 +
 165.132 +    /* ----- Constructors ----- */
 165.133 +
 165.134 +    /**
 165.135 +     * Constructs a new {@code MathContext} with the specified
 165.136 +     * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding
 165.137 +     * mode.
 165.138 +     *
 165.139 +     * @param setPrecision The non-negative {@code int} precision setting.
 165.140 +     * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
 165.141 +     *         than zero.
 165.142 +     */
 165.143 +    public MathContext(int setPrecision) {
 165.144 +        this(setPrecision, DEFAULT_ROUNDINGMODE);
 165.145 +        return;
 165.146 +    }
 165.147 +
 165.148 +    /**
 165.149 +     * Constructs a new {@code MathContext} with a specified
 165.150 +     * precision and rounding mode.
 165.151 +     *
 165.152 +     * @param setPrecision The non-negative {@code int} precision setting.
 165.153 +     * @param setRoundingMode The rounding mode to use.
 165.154 +     * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
 165.155 +     *         than zero.
 165.156 +     * @throws NullPointerException if the rounding mode argument is {@code null}
 165.157 +     */
 165.158 +    public MathContext(int setPrecision,
 165.159 +                       RoundingMode setRoundingMode) {
 165.160 +        if (setPrecision < MIN_DIGITS)
 165.161 +            throw new IllegalArgumentException("Digits < 0");
 165.162 +        if (setRoundingMode == null)
 165.163 +            throw new NullPointerException("null RoundingMode");
 165.164 +
 165.165 +        precision = setPrecision;
 165.166 +        roundingMode = setRoundingMode;
 165.167 +        return;
 165.168 +    }
 165.169 +
 165.170 +    /**
 165.171 +     * Constructs a new {@code MathContext} from a string.
 165.172 +     *
 165.173 +     * The string must be in the same format as that produced by the
 165.174 +     * {@link #toString} method.
 165.175 +     *
 165.176 +     * <p>An {@code IllegalArgumentException} is thrown if the precision
 165.177 +     * section of the string is out of range ({@code < 0}) or the string is
 165.178 +     * not in the format created by the {@link #toString} method.
 165.179 +     *
 165.180 +     * @param val The string to be parsed
 165.181 +     * @throws IllegalArgumentException if the precision section is out of range
 165.182 +     * or of incorrect format
 165.183 +     * @throws NullPointerException if the argument is {@code null}
 165.184 +     */
 165.185 +    public MathContext(String val) {
 165.186 +        boolean bad = false;
 165.187 +        int setPrecision;
 165.188 +        if (val == null)
 165.189 +            throw new NullPointerException("null String");
 165.190 +        try { // any error here is a string format problem
 165.191 +            if (!val.startsWith("precision=")) throw new RuntimeException();
 165.192 +            int fence = val.indexOf(' ');    // could be -1
 165.193 +            int off = 10;                     // where value starts
 165.194 +            setPrecision = Integer.parseInt(val.substring(10, fence));
 165.195 +
 165.196 +            if (!val.startsWith("roundingMode=", fence+1))
 165.197 +                throw new RuntimeException();
 165.198 +            off = fence + 1 + 13;
 165.199 +            String str = val.substring(off, val.length());
 165.200 +            roundingMode = RoundingMode.valueOf(str);
 165.201 +        } catch (RuntimeException re) {
 165.202 +            throw new IllegalArgumentException("bad string format");
 165.203 +        }
 165.204 +
 165.205 +        if (setPrecision < MIN_DIGITS)
 165.206 +            throw new IllegalArgumentException("Digits < 0");
 165.207 +        // the other parameters cannot be invalid if we got here
 165.208 +        precision = setPrecision;
 165.209 +    }
 165.210 +
 165.211 +    /**
 165.212 +     * Returns the {@code precision} setting.
 165.213 +     * This value is always non-negative.
 165.214 +     *
 165.215 +     * @return an {@code int} which is the value of the {@code precision}
 165.216 +     *         setting
 165.217 +     */
 165.218 +    public int getPrecision() {
 165.219 +        return precision;
 165.220 +    }
 165.221 +
 165.222 +    /**
 165.223 +     * Returns the roundingMode setting.
 165.224 +     * This will be one of
 165.225 +     * {@link  RoundingMode#CEILING},
 165.226 +     * {@link  RoundingMode#DOWN},
 165.227 +     * {@link  RoundingMode#FLOOR},
 165.228 +     * {@link  RoundingMode#HALF_DOWN},
 165.229 +     * {@link  RoundingMode#HALF_EVEN},
 165.230 +     * {@link  RoundingMode#HALF_UP},
 165.231 +     * {@link  RoundingMode#UNNECESSARY}, or
 165.232 +     * {@link  RoundingMode#UP}.
 165.233 +     *
 165.234 +     * @return a {@code RoundingMode} object which is the value of the
 165.235 +     *         {@code roundingMode} setting
 165.236 +     */
 165.237 +
 165.238 +    public RoundingMode getRoundingMode() {
 165.239 +        return roundingMode;
 165.240 +    }
 165.241 +
 165.242 +    /**
 165.243 +     * Compares this {@code MathContext} with the specified
 165.244 +     * {@code Object} for equality.
 165.245 +     *
 165.246 +     * @param  x {@code Object} to which this {@code MathContext} is to
 165.247 +     *         be compared.
 165.248 +     * @return {@code true} if and only if the specified {@code Object} is
 165.249 +     *         a {@code MathContext} object which has exactly the same
 165.250 +     *         settings as this object
 165.251 +     */
 165.252 +    public boolean equals(Object x){
 165.253 +        MathContext mc;
 165.254 +        if (!(x instanceof MathContext))
 165.255 +            return false;
 165.256 +        mc = (MathContext) x;
 165.257 +        return mc.precision == this.precision
 165.258 +            && mc.roundingMode == this.roundingMode; // no need for .equals()
 165.259 +    }
 165.260 +
 165.261 +    /**
 165.262 +     * Returns the hash code for this {@code MathContext}.
 165.263 +     *
 165.264 +     * @return hash code for this {@code MathContext}
 165.265 +     */
 165.266 +    public int hashCode() {
 165.267 +        return this.precision + roundingMode.hashCode() * 59;
 165.268 +    }
 165.269 +
 165.270 +    /**
 165.271 +     * Returns the string representation of this {@code MathContext}.
 165.272 +     * The {@code String} returned represents the settings of the
 165.273 +     * {@code MathContext} object as two space-delimited words
 165.274 +     * (separated by a single space character, <tt>'&#92;u0020'</tt>,
 165.275 +     * and with no leading or trailing white space), as follows:
 165.276 +     * <ol>
 165.277 +     * <li>
 165.278 +     * The string {@code "precision="}, immediately followed
 165.279 +     * by the value of the precision setting as a numeric string as if
 165.280 +     * generated by the {@link Integer#toString(int) Integer.toString}
 165.281 +     * method.
 165.282 +     *
 165.283 +     * <li>
 165.284 +     * The string {@code "roundingMode="}, immediately
 165.285 +     * followed by the value of the {@code roundingMode} setting as a
 165.286 +     * word.  This word will be the same as the name of the
 165.287 +     * corresponding public constant in the {@link RoundingMode}
 165.288 +     * enum.
 165.289 +     * </ol>
 165.290 +     * <p>
 165.291 +     * For example:
 165.292 +     * <pre>
 165.293 +     * precision=9 roundingMode=HALF_UP
 165.294 +     * </pre>
 165.295 +     *
 165.296 +     * Additional words may be appended to the result of
 165.297 +     * {@code toString} in the future if more properties are added to
 165.298 +     * this class.
 165.299 +     *
 165.300 +     * @return a {@code String} representing the context settings
 165.301 +     */
 165.302 +    public java.lang.String toString() {
 165.303 +        return "precision=" +           precision + " " +
 165.304 +               "roundingMode=" +        roundingMode.toString();
 165.305 +    }
 165.306 +
 165.307 +    // Private methods
 165.308 +
 165.309 +    /**
 165.310 +     * Reconstitute the {@code MathContext} instance from a stream (that is,
 165.311 +     * deserialize it).
 165.312 +     *
 165.313 +     * @param s the stream being read.
 165.314 +     */
 165.315 +    private void readObject(java.io.ObjectInputStream s)
 165.316 +        throws java.io.IOException, ClassNotFoundException {
 165.317 +        s.defaultReadObject();     // read in all fields
 165.318 +        // validate possibly bad fields
 165.319 +        if (precision < MIN_DIGITS) {
 165.320 +            String message = "MathContext: invalid digits in stream";
 165.321 +            throw new java.io.StreamCorruptedException(message);
 165.322 +        }
 165.323 +        if (roundingMode == null) {
 165.324 +            String message = "MathContext: null roundingMode in stream";
 165.325 +            throw new java.io.StreamCorruptedException(message);
 165.326 +        }
 165.327 +    }
 165.328 +
 165.329 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/rt/emul/compact/src/main/java/java/math/MutableBigInteger.java	Wed Apr 30 15:04:10 2014 +0200
   166.3 @@ -0,0 +1,1477 @@
   166.4 +/*
   166.5 + * Copyright (c) 1999, 2007, 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.math;
  166.30 +
  166.31 +/**
  166.32 + * A class used to represent multiprecision integers that makes efficient
  166.33 + * use of allocated space by allowing a number to occupy only part of
  166.34 + * an array so that the arrays do not have to be reallocated as often.
  166.35 + * When performing an operation with many iterations the array used to
  166.36 + * hold a number is only reallocated when necessary and does not have to
  166.37 + * be the same size as the number it represents. A mutable number allows
  166.38 + * calculations to occur on the same number without having to create
  166.39 + * a new number for every step of the calculation as occurs with
  166.40 + * BigIntegers.
  166.41 + *
  166.42 + * @see     BigInteger
  166.43 + * @author  Michael McCloskey
  166.44 + * @since   1.3
  166.45 + */
  166.46 +
  166.47 +import java.util.Arrays;
  166.48 +
  166.49 +import static java.math.BigInteger.LONG_MASK;
  166.50 +import static java.math.BigDecimal.INFLATED;
  166.51 +
  166.52 +class MutableBigInteger {
  166.53 +    /**
  166.54 +     * Holds the magnitude of this MutableBigInteger in big endian order.
  166.55 +     * The magnitude may start at an offset into the value array, and it may
  166.56 +     * end before the length of the value array.
  166.57 +     */
  166.58 +    int[] value;
  166.59 +
  166.60 +    /**
  166.61 +     * The number of ints of the value array that are currently used
  166.62 +     * to hold the magnitude of this MutableBigInteger. The magnitude starts
  166.63 +     * at an offset and offset + intLen may be less than value.length.
  166.64 +     */
  166.65 +    int intLen;
  166.66 +
  166.67 +    /**
  166.68 +     * The offset into the value array where the magnitude of this
  166.69 +     * MutableBigInteger begins.
  166.70 +     */
  166.71 +    int offset = 0;
  166.72 +
  166.73 +    // Constants
  166.74 +    /**
  166.75 +     * MutableBigInteger with one element value array with the value 1. Used by
  166.76 +     * BigDecimal divideAndRound to increment the quotient. Use this constant
  166.77 +     * only when the method is not going to modify this object.
  166.78 +     */
  166.79 +    static final MutableBigInteger ONE = new MutableBigInteger(1);
  166.80 +
  166.81 +    // Constructors
  166.82 +
  166.83 +    /**
  166.84 +     * The default constructor. An empty MutableBigInteger is created with
  166.85 +     * a one word capacity.
  166.86 +     */
  166.87 +    MutableBigInteger() {
  166.88 +        value = new int[1];
  166.89 +        intLen = 0;
  166.90 +    }
  166.91 +
  166.92 +    /**
  166.93 +     * Construct a new MutableBigInteger with a magnitude specified by
  166.94 +     * the int val.
  166.95 +     */
  166.96 +    MutableBigInteger(int val) {
  166.97 +        value = new int[1];
  166.98 +        intLen = 1;
  166.99 +        value[0] = val;
 166.100 +    }
 166.101 +
 166.102 +    /**
 166.103 +     * Construct a new MutableBigInteger with the specified value array
 166.104 +     * up to the length of the array supplied.
 166.105 +     */
 166.106 +    MutableBigInteger(int[] val) {
 166.107 +        value = val;
 166.108 +        intLen = val.length;
 166.109 +    }
 166.110 +
 166.111 +    /**
 166.112 +     * Construct a new MutableBigInteger with a magnitude equal to the
 166.113 +     * specified BigInteger.
 166.114 +     */
 166.115 +    MutableBigInteger(BigInteger b) {
 166.116 +        intLen = b.mag.length;
 166.117 +        value = Arrays.copyOf(b.mag, intLen);
 166.118 +    }
 166.119 +
 166.120 +    /**
 166.121 +     * Construct a new MutableBigInteger with a magnitude equal to the
 166.122 +     * specified MutableBigInteger.
 166.123 +     */
 166.124 +    MutableBigInteger(MutableBigInteger val) {
 166.125 +        intLen = val.intLen;
 166.126 +        value = Arrays.copyOfRange(val.value, val.offset, val.offset + intLen);
 166.127 +    }
 166.128 +
 166.129 +    /**
 166.130 +     * Internal helper method to return the magnitude array. The caller is not
 166.131 +     * supposed to modify the returned array.
 166.132 +     */
 166.133 +    private int[] getMagnitudeArray() {
 166.134 +        if (offset > 0 || value.length != intLen)
 166.135 +            return Arrays.copyOfRange(value, offset, offset + intLen);
 166.136 +        return value;
 166.137 +    }
 166.138 +
 166.139 +    /**
 166.140 +     * Convert this MutableBigInteger to a long value. The caller has to make
 166.141 +     * sure this MutableBigInteger can be fit into long.
 166.142 +     */
 166.143 +    private long toLong() {
 166.144 +        assert (intLen <= 2) : "this MutableBigInteger exceeds the range of long";
 166.145 +        if (intLen == 0)
 166.146 +            return 0;
 166.147 +        long d = value[offset] & LONG_MASK;
 166.148 +        return (intLen == 2) ? d << 32 | (value[offset + 1] & LONG_MASK) : d;
 166.149 +    }
 166.150 +
 166.151 +    /**
 166.152 +     * Convert this MutableBigInteger to a BigInteger object.
 166.153 +     */
 166.154 +    BigInteger toBigInteger(int sign) {
 166.155 +        if (intLen == 0 || sign == 0)
 166.156 +            return BigInteger.ZERO;
 166.157 +        return new BigInteger(getMagnitudeArray(), sign);
 166.158 +    }
 166.159 +
 166.160 +    /**
 166.161 +     * Convert this MutableBigInteger to BigDecimal object with the specified sign
 166.162 +     * and scale.
 166.163 +     */
 166.164 +    BigDecimal toBigDecimal(int sign, int scale) {
 166.165 +        if (intLen == 0 || sign == 0)
 166.166 +            return BigDecimal.valueOf(0, scale);
 166.167 +        int[] mag = getMagnitudeArray();
 166.168 +        int len = mag.length;
 166.169 +        int d = mag[0];
 166.170 +        // If this MutableBigInteger can't be fit into long, we need to
 166.171 +        // make a BigInteger object for the resultant BigDecimal object.
 166.172 +        if (len > 2 || (d < 0 && len == 2))
 166.173 +            return new BigDecimal(new BigInteger(mag, sign), INFLATED, scale, 0);
 166.174 +        long v = (len == 2) ?
 166.175 +            ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) :
 166.176 +            d & LONG_MASK;
 166.177 +        return new BigDecimal(null, sign == -1 ? -v : v, scale, 0);
 166.178 +    }
 166.179 +
 166.180 +    /**
 166.181 +     * Clear out a MutableBigInteger for reuse.
 166.182 +     */
 166.183 +    void clear() {
 166.184 +        offset = intLen = 0;
 166.185 +        for (int index=0, n=value.length; index < n; index++)
 166.186 +            value[index] = 0;
 166.187 +    }
 166.188 +
 166.189 +    /**
 166.190 +     * Set a MutableBigInteger to zero, removing its offset.
 166.191 +     */
 166.192 +    void reset() {
 166.193 +        offset = intLen = 0;
 166.194 +    }
 166.195 +
 166.196 +    /**
 166.197 +     * Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1
 166.198 +     * as this MutableBigInteger is numerically less than, equal to, or
 166.199 +     * greater than <tt>b</tt>.
 166.200 +     */
 166.201 +    final int compare(MutableBigInteger b) {
 166.202 +        int blen = b.intLen;
 166.203 +        if (intLen < blen)
 166.204 +            return -1;
 166.205 +        if (intLen > blen)
 166.206 +           return 1;
 166.207 +
 166.208 +        // Add Integer.MIN_VALUE to make the comparison act as unsigned integer
 166.209 +        // comparison.
 166.210 +        int[] bval = b.value;
 166.211 +        for (int i = offset, j = b.offset; i < intLen + offset; i++, j++) {
 166.212 +            int b1 = value[i] + 0x80000000;
 166.213 +            int b2 = bval[j]  + 0x80000000;
 166.214 +            if (b1 < b2)
 166.215 +                return -1;
 166.216 +            if (b1 > b2)
 166.217 +                return 1;
 166.218 +        }
 166.219 +        return 0;
 166.220 +    }
 166.221 +
 166.222 +    /**
 166.223 +     * Compare this against half of a MutableBigInteger object (Needed for
 166.224 +     * remainder tests).
 166.225 +     * Assumes no leading unnecessary zeros, which holds for results
 166.226 +     * from divide().
 166.227 +     */
 166.228 +    final int compareHalf(MutableBigInteger b) {
 166.229 +        int blen = b.intLen;
 166.230 +        int len = intLen;
 166.231 +        if (len <= 0)
 166.232 +            return blen <=0 ? 0 : -1;
 166.233 +        if (len > blen)
 166.234 +            return 1;
 166.235 +        if (len < blen - 1)
 166.236 +            return -1;
 166.237 +        int[] bval = b.value;
 166.238 +        int bstart = 0;
 166.239 +        int carry = 0;
 166.240 +        // Only 2 cases left:len == blen or len == blen - 1
 166.241 +        if (len != blen) { // len == blen - 1
 166.242 +            if (bval[bstart] == 1) {
 166.243 +                ++bstart;
 166.244 +                carry = 0x80000000;
 166.245 +            } else
 166.246 +                return -1;
 166.247 +        }
 166.248 +        // compare values with right-shifted values of b,
 166.249 +        // carrying shifted-out bits across words
 166.250 +        int[] val = value;
 166.251 +        for (int i = offset, j = bstart; i < len + offset;) {
 166.252 +            int bv = bval[j++];
 166.253 +            long hb = ((bv >>> 1) + carry) & LONG_MASK;
 166.254 +            long v = val[i++] & LONG_MASK;
 166.255 +            if (v != hb)
 166.256 +                return v < hb ? -1 : 1;
 166.257 +            carry = (bv & 1) << 31; // carray will be either 0x80000000 or 0
 166.258 +        }
 166.259 +        return carry == 0? 0 : -1;
 166.260 +    }
 166.261 +
 166.262 +    /**
 166.263 +     * Return the index of the lowest set bit in this MutableBigInteger. If the
 166.264 +     * magnitude of this MutableBigInteger is zero, -1 is returned.
 166.265 +     */
 166.266 +    private final int getLowestSetBit() {
 166.267 +        if (intLen == 0)
 166.268 +            return -1;
 166.269 +        int j, b;
 166.270 +        for (j=intLen-1; (j>0) && (value[j+offset]==0); j--)
 166.271 +            ;
 166.272 +        b = value[j+offset];
 166.273 +        if (b==0)
 166.274 +            return -1;
 166.275 +        return ((intLen-1-j)<<5) + Integer.numberOfTrailingZeros(b);
 166.276 +    }
 166.277 +
 166.278 +    /**
 166.279 +     * Return the int in use in this MutableBigInteger at the specified
 166.280 +     * index. This method is not used because it is not inlined on all
 166.281 +     * platforms.
 166.282 +     */
 166.283 +    private final int getInt(int index) {
 166.284 +        return value[offset+index];
 166.285 +    }
 166.286 +
 166.287 +    /**
 166.288 +     * Return a long which is equal to the unsigned value of the int in
 166.289 +     * use in this MutableBigInteger at the specified index. This method is
 166.290 +     * not used because it is not inlined on all platforms.
 166.291 +     */
 166.292 +    private final long getLong(int index) {
 166.293 +        return value[offset+index] & LONG_MASK;
 166.294 +    }
 166.295 +
 166.296 +    /**
 166.297 +     * Ensure that the MutableBigInteger is in normal form, specifically
 166.298 +     * making sure that there are no leading zeros, and that if the
 166.299 +     * magnitude is zero, then intLen is zero.
 166.300 +     */
 166.301 +    final void normalize() {
 166.302 +        if (intLen == 0) {
 166.303 +            offset = 0;
 166.304 +            return;
 166.305 +        }
 166.306 +
 166.307 +        int index = offset;
 166.308 +        if (value[index] != 0)
 166.309 +            return;
 166.310 +
 166.311 +        int indexBound = index+intLen;
 166.312 +        do {
 166.313 +            index++;
 166.314 +        } while(index < indexBound && value[index]==0);
 166.315 +
 166.316 +        int numZeros = index - offset;
 166.317 +        intLen -= numZeros;
 166.318 +        offset = (intLen==0 ?  0 : offset+numZeros);
 166.319 +    }
 166.320 +
 166.321 +    /**
 166.322 +     * If this MutableBigInteger cannot hold len words, increase the size
 166.323 +     * of the value array to len words.
 166.324 +     */
 166.325 +    private final void ensureCapacity(int len) {
 166.326 +        if (value.length < len) {
 166.327 +            value = new int[len];
 166.328 +            offset = 0;
 166.329 +            intLen = len;
 166.330 +        }
 166.331 +    }
 166.332 +
 166.333 +    /**
 166.334 +     * Convert this MutableBigInteger into an int array with no leading
 166.335 +     * zeros, of a length that is equal to this MutableBigInteger's intLen.
 166.336 +     */
 166.337 +    int[] toIntArray() {
 166.338 +        int[] result = new int[intLen];
 166.339 +        for(int i=0; i<intLen; i++)
 166.340 +            result[i] = value[offset+i];
 166.341 +        return result;
 166.342 +    }
 166.343 +
 166.344 +    /**
 166.345 +     * Sets the int at index+offset in this MutableBigInteger to val.
 166.346 +     * This does not get inlined on all platforms so it is not used
 166.347 +     * as often as originally intended.
 166.348 +     */
 166.349 +    void setInt(int index, int val) {
 166.350 +        value[offset + index] = val;
 166.351 +    }
 166.352 +
 166.353 +    /**
 166.354 +     * Sets this MutableBigInteger's value array to the specified array.
 166.355 +     * The intLen is set to the specified length.
 166.356 +     */
 166.357 +    void setValue(int[] val, int length) {
 166.358 +        value = val;
 166.359 +        intLen = length;
 166.360 +        offset = 0;
 166.361 +    }
 166.362 +
 166.363 +    /**
 166.364 +     * Sets this MutableBigInteger's value array to a copy of the specified
 166.365 +     * array. The intLen is set to the length of the new array.
 166.366 +     */
 166.367 +    void copyValue(MutableBigInteger src) {
 166.368 +        int len = src.intLen;
 166.369 +        if (value.length < len)
 166.370 +            value = new int[len];
 166.371 +        System.arraycopy(src.value, src.offset, value, 0, len);
 166.372 +        intLen = len;
 166.373 +        offset = 0;
 166.374 +    }
 166.375 +
 166.376 +    /**
 166.377 +     * Sets this MutableBigInteger's value array to a copy of the specified
 166.378 +     * array. The intLen is set to the length of the specified array.
 166.379 +     */
 166.380 +    void copyValue(int[] val) {
 166.381 +        int len = val.length;
 166.382 +        if (value.length < len)
 166.383 +            value = new int[len];
 166.384 +        System.arraycopy(val, 0, value, 0, len);
 166.385 +        intLen = len;
 166.386 +        offset = 0;
 166.387 +    }
 166.388 +
 166.389 +    /**
 166.390 +     * Returns true iff this MutableBigInteger has a value of one.
 166.391 +     */
 166.392 +    boolean isOne() {
 166.393 +        return (intLen == 1) && (value[offset] == 1);
 166.394 +    }
 166.395 +
 166.396 +    /**
 166.397 +     * Returns true iff this MutableBigInteger has a value of zero.
 166.398 +     */
 166.399 +    boolean isZero() {
 166.400 +        return (intLen == 0);
 166.401 +    }
 166.402 +
 166.403 +    /**
 166.404 +     * Returns true iff this MutableBigInteger is even.
 166.405 +     */
 166.406 +    boolean isEven() {
 166.407 +        return (intLen == 0) || ((value[offset + intLen - 1] & 1) == 0);
 166.408 +    }
 166.409 +
 166.410 +    /**
 166.411 +     * Returns true iff this MutableBigInteger is odd.
 166.412 +     */
 166.413 +    boolean isOdd() {
 166.414 +        return isZero() ? false : ((value[offset + intLen - 1] & 1) == 1);
 166.415 +    }
 166.416 +
 166.417 +    /**
 166.418 +     * Returns true iff this MutableBigInteger is in normal form. A
 166.419 +     * MutableBigInteger is in normal form if it has no leading zeros
 166.420 +     * after the offset, and intLen + offset <= value.length.
 166.421 +     */
 166.422 +    boolean isNormal() {
 166.423 +        if (intLen + offset > value.length)
 166.424 +            return false;
 166.425 +        if (intLen ==0)
 166.426 +            return true;
 166.427 +        return (value[offset] != 0);
 166.428 +    }
 166.429 +
 166.430 +    /**
 166.431 +     * Returns a String representation of this MutableBigInteger in radix 10.
 166.432 +     */
 166.433 +    public String toString() {
 166.434 +        BigInteger b = toBigInteger(1);
 166.435 +        return b.toString();
 166.436 +    }
 166.437 +
 166.438 +    /**
 166.439 +     * Right shift this MutableBigInteger n bits. The MutableBigInteger is left
 166.440 +     * in normal form.
 166.441 +     */
 166.442 +    void rightShift(int n) {
 166.443 +        if (intLen == 0)
 166.444 +            return;
 166.445 +        int nInts = n >>> 5;
 166.446 +        int nBits = n & 0x1F;
 166.447 +        this.intLen -= nInts;
 166.448 +        if (nBits == 0)
 166.449 +            return;
 166.450 +        int bitsInHighWord = BigInteger.bitLengthForInt(value[offset]);
 166.451 +        if (nBits >= bitsInHighWord) {
 166.452 +            this.primitiveLeftShift(32 - nBits);
 166.453 +            this.intLen--;
 166.454 +        } else {
 166.455 +            primitiveRightShift(nBits);
 166.456 +        }
 166.457 +    }
 166.458 +
 166.459 +    /**
 166.460 +     * Left shift this MutableBigInteger n bits.
 166.461 +     */
 166.462 +    void leftShift(int n) {
 166.463 +        /*
 166.464 +         * If there is enough storage space in this MutableBigInteger already
 166.465 +         * the available space will be used. Space to the right of the used
 166.466 +         * ints in the value array is faster to utilize, so the extra space
 166.467 +         * will be taken from the right if possible.
 166.468 +         */
 166.469 +        if (intLen == 0)
 166.470 +           return;
 166.471 +        int nInts = n >>> 5;
 166.472 +        int nBits = n&0x1F;
 166.473 +        int bitsInHighWord = BigInteger.bitLengthForInt(value[offset]);
 166.474 +
 166.475 +        // If shift can be done without moving words, do so
 166.476 +        if (n <= (32-bitsInHighWord)) {
 166.477 +            primitiveLeftShift(nBits);
 166.478 +            return;
 166.479 +        }
 166.480 +
 166.481 +        int newLen = intLen + nInts +1;
 166.482 +        if (nBits <= (32-bitsInHighWord))
 166.483 +            newLen--;
 166.484 +        if (value.length < newLen) {
 166.485 +            // The array must grow
 166.486 +            int[] result = new int[newLen];
 166.487 +            for (int i=0; i<intLen; i++)
 166.488 +                result[i] = value[offset+i];
 166.489 +            setValue(result, newLen);
 166.490 +        } else if (value.length - offset >= newLen) {
 166.491 +            // Use space on right
 166.492 +            for(int i=0; i<newLen - intLen; i++)
 166.493 +                value[offset+intLen+i] = 0;
 166.494 +        } else {
 166.495 +            // Must use space on left
 166.496 +            for (int i=0; i<intLen; i++)
 166.497 +                value[i] = value[offset+i];
 166.498 +            for (int i=intLen; i<newLen; i++)
 166.499 +                value[i] = 0;
 166.500 +            offset = 0;
 166.501 +        }
 166.502 +        intLen = newLen;
 166.503 +        if (nBits == 0)
 166.504 +            return;
 166.505 +        if (nBits <= (32-bitsInHighWord))
 166.506 +            primitiveLeftShift(nBits);
 166.507 +        else
 166.508 +            primitiveRightShift(32 -nBits);
 166.509 +    }
 166.510 +
 166.511 +    /**
 166.512 +     * A primitive used for division. This method adds in one multiple of the
 166.513 +     * divisor a back to the dividend result at a specified offset. It is used
 166.514 +     * when qhat was estimated too large, and must be adjusted.
 166.515 +     */
 166.516 +    private int divadd(int[] a, int[] result, int offset) {
 166.517 +        long carry = 0;
 166.518 +
 166.519 +        for (int j=a.length-1; j >= 0; j--) {
 166.520 +            long sum = (a[j] & LONG_MASK) +
 166.521 +                       (result[j+offset] & LONG_MASK) + carry;
 166.522 +            result[j+offset] = (int)sum;
 166.523 +            carry = sum >>> 32;
 166.524 +        }
 166.525 +        return (int)carry;
 166.526 +    }
 166.527 +
 166.528 +    /**
 166.529 +     * This method is used for division. It multiplies an n word input a by one
 166.530 +     * word input x, and subtracts the n word product from q. This is needed
 166.531 +     * when subtracting qhat*divisor from dividend.
 166.532 +     */
 166.533 +    private int mulsub(int[] q, int[] a, int x, int len, int offset) {
 166.534 +        long xLong = x & LONG_MASK;
 166.535 +        long carry = 0;
 166.536 +        offset += len;
 166.537 +
 166.538 +        for (int j=len-1; j >= 0; j--) {
 166.539 +            long product = (a[j] & LONG_MASK) * xLong + carry;
 166.540 +            long difference = q[offset] - product;
 166.541 +            q[offset--] = (int)difference;
 166.542 +            carry = (product >>> 32)
 166.543 +                     + (((difference & LONG_MASK) >
 166.544 +                         (((~(int)product) & LONG_MASK))) ? 1:0);
 166.545 +        }
 166.546 +        return (int)carry;
 166.547 +    }
 166.548 +
 166.549 +    /**
 166.550 +     * Right shift this MutableBigInteger n bits, where n is
 166.551 +     * less than 32.
 166.552 +     * Assumes that intLen > 0, n > 0 for speed
 166.553 +     */
 166.554 +    private final void primitiveRightShift(int n) {
 166.555 +        int[] val = value;
 166.556 +        int n2 = 32 - n;
 166.557 +        for (int i=offset+intLen-1, c=val[i]; i>offset; i--) {
 166.558 +            int b = c;
 166.559 +            c = val[i-1];
 166.560 +            val[i] = (c << n2) | (b >>> n);
 166.561 +        }
 166.562 +        val[offset] >>>= n;
 166.563 +    }
 166.564 +
 166.565 +    /**
 166.566 +     * Left shift this MutableBigInteger n bits, where n is
 166.567 +     * less than 32.
 166.568 +     * Assumes that intLen > 0, n > 0 for speed
 166.569 +     */
 166.570 +    private final void primitiveLeftShift(int n) {
 166.571 +        int[] val = value;
 166.572 +        int n2 = 32 - n;
 166.573 +        for (int i=offset, c=val[i], m=i+intLen-1; i<m; i++) {
 166.574 +            int b = c;
 166.575 +            c = val[i+1];
 166.576 +            val[i] = (b << n) | (c >>> n2);
 166.577 +        }
 166.578 +        val[offset+intLen-1] <<= n;
 166.579 +    }
 166.580 +
 166.581 +    /**
 166.582 +     * Adds the contents of two MutableBigInteger objects.The result
 166.583 +     * is placed within this MutableBigInteger.
 166.584 +     * The contents of the addend are not changed.
 166.585 +     */
 166.586 +    void add(MutableBigInteger addend) {
 166.587 +        int x = intLen;
 166.588 +        int y = addend.intLen;
 166.589 +        int resultLen = (intLen > addend.intLen ? intLen : addend.intLen);
 166.590 +        int[] result = (value.length < resultLen ? new int[resultLen] : value);
 166.591 +
 166.592 +        int rstart = result.length-1;
 166.593 +        long sum;
 166.594 +        long carry = 0;
 166.595 +
 166.596 +        // Add common parts of both numbers
 166.597 +        while(x>0 && y>0) {
 166.598 +            x--; y--;
 166.599 +            sum = (value[x+offset] & LONG_MASK) +
 166.600 +                (addend.value[y+addend.offset] & LONG_MASK) + carry;
 166.601 +            result[rstart--] = (int)sum;
 166.602 +            carry = sum >>> 32;
 166.603 +        }
 166.604 +
 166.605 +        // Add remainder of the longer number
 166.606 +        while(x>0) {
 166.607 +            x--;
 166.608 +            if (carry == 0 && result == value && rstart == (x + offset))
 166.609 +                return;
 166.610 +            sum = (value[x+offset] & LONG_MASK) + carry;
 166.611 +            result[rstart--] = (int)sum;
 166.612 +            carry = sum >>> 32;
 166.613 +        }
 166.614 +        while(y>0) {
 166.615 +            y--;
 166.616 +            sum = (addend.value[y+addend.offset] & LONG_MASK) + carry;
 166.617 +            result[rstart--] = (int)sum;
 166.618 +            carry = sum >>> 32;
 166.619 +        }
 166.620 +
 166.621 +        if (carry > 0) { // Result must grow in length
 166.622 +            resultLen++;
 166.623 +            if (result.length < resultLen) {
 166.624 +                int temp[] = new int[resultLen];
 166.625 +                // Result one word longer from carry-out; copy low-order
 166.626 +                // bits into new result.
 166.627 +                System.arraycopy(result, 0, temp, 1, result.length);
 166.628 +                temp[0] = 1;
 166.629 +                result = temp;
 166.630 +            } else {
 166.631 +                result[rstart--] = 1;
 166.632 +            }
 166.633 +        }
 166.634 +
 166.635 +        value = result;
 166.636 +        intLen = resultLen;
 166.637 +        offset = result.length - resultLen;
 166.638 +    }
 166.639 +
 166.640 +
 166.641 +    /**
 166.642 +     * Subtracts the smaller of this and b from the larger and places the
 166.643 +     * result into this MutableBigInteger.
 166.644 +     */
 166.645 +    int subtract(MutableBigInteger b) {
 166.646 +        MutableBigInteger a = this;
 166.647 +
 166.648 +        int[] result = value;
 166.649 +        int sign = a.compare(b);
 166.650 +
 166.651 +        if (sign == 0) {
 166.652 +            reset();
 166.653 +            return 0;
 166.654 +        }
 166.655 +        if (sign < 0) {
 166.656 +            MutableBigInteger tmp = a;
 166.657 +            a = b;
 166.658 +            b = tmp;
 166.659 +        }
 166.660 +
 166.661 +        int resultLen = a.intLen;
 166.662 +        if (result.length < resultLen)
 166.663 +            result = new int[resultLen];
 166.664 +
 166.665 +        long diff = 0;
 166.666 +        int x = a.intLen;
 166.667 +        int y = b.intLen;
 166.668 +        int rstart = result.length - 1;
 166.669 +
 166.670 +        // Subtract common parts of both numbers
 166.671 +        while (y>0) {
 166.672 +            x--; y--;
 166.673 +
 166.674 +            diff = (a.value[x+a.offset] & LONG_MASK) -
 166.675 +                   (b.value[y+b.offset] & LONG_MASK) - ((int)-(diff>>32));
 166.676 +            result[rstart--] = (int)diff;
 166.677 +        }
 166.678 +        // Subtract remainder of longer number
 166.679 +        while (x>0) {
 166.680 +            x--;
 166.681 +            diff = (a.value[x+a.offset] & LONG_MASK) - ((int)-(diff>>32));
 166.682 +            result[rstart--] = (int)diff;
 166.683 +        }
 166.684 +
 166.685 +        value = result;
 166.686 +        intLen = resultLen;
 166.687 +        offset = value.length - resultLen;
 166.688 +        normalize();
 166.689 +        return sign;
 166.690 +    }
 166.691 +
 166.692 +    /**
 166.693 +     * Subtracts the smaller of a and b from the larger and places the result
 166.694 +     * into the larger. Returns 1 if the answer is in a, -1 if in b, 0 if no
 166.695 +     * operation was performed.
 166.696 +     */
 166.697 +    private int difference(MutableBigInteger b) {
 166.698 +        MutableBigInteger a = this;
 166.699 +        int sign = a.compare(b);
 166.700 +        if (sign ==0)
 166.701 +            return 0;
 166.702 +        if (sign < 0) {
 166.703 +            MutableBigInteger tmp = a;
 166.704 +            a = b;
 166.705 +            b = tmp;
 166.706 +        }
 166.707 +
 166.708 +        long diff = 0;
 166.709 +        int x = a.intLen;
 166.710 +        int y = b.intLen;
 166.711 +
 166.712 +        // Subtract common parts of both numbers
 166.713 +        while (y>0) {
 166.714 +            x--; y--;
 166.715 +            diff = (a.value[a.offset+ x] & LONG_MASK) -
 166.716 +                (b.value[b.offset+ y] & LONG_MASK) - ((int)-(diff>>32));
 166.717 +            a.value[a.offset+x] = (int)diff;
 166.718 +        }
 166.719 +        // Subtract remainder of longer number
 166.720 +        while (x>0) {
 166.721 +            x--;
 166.722 +            diff = (a.value[a.offset+ x] & LONG_MASK) - ((int)-(diff>>32));
 166.723 +            a.value[a.offset+x] = (int)diff;
 166.724 +        }
 166.725 +
 166.726 +        a.normalize();
 166.727 +        return sign;
 166.728 +    }
 166.729 +
 166.730 +    /**
 166.731 +     * Multiply the contents of two MutableBigInteger objects. The result is
 166.732 +     * placed into MutableBigInteger z. The contents of y are not changed.
 166.733 +     */
 166.734 +    void multiply(MutableBigInteger y, MutableBigInteger z) {
 166.735 +        int xLen = intLen;
 166.736 +        int yLen = y.intLen;
 166.737 +        int newLen = xLen + yLen;
 166.738 +
 166.739 +        // Put z into an appropriate state to receive product
 166.740 +        if (z.value.length < newLen)
 166.741 +            z.value = new int[newLen];
 166.742 +        z.offset = 0;
 166.743 +        z.intLen = newLen;
 166.744 +
 166.745 +        // The first iteration is hoisted out of the loop to avoid extra add
 166.746 +        long carry = 0;
 166.747 +        for (int j=yLen-1, k=yLen+xLen-1; j >= 0; j--, k--) {
 166.748 +                long product = (y.value[j+y.offset] & LONG_MASK) *
 166.749 +                               (value[xLen-1+offset] & LONG_MASK) + carry;
 166.750 +                z.value[k] = (int)product;
 166.751 +                carry = product >>> 32;
 166.752 +        }
 166.753 +        z.value[xLen-1] = (int)carry;
 166.754 +
 166.755 +        // Perform the multiplication word by word
 166.756 +        for (int i = xLen-2; i >= 0; i--) {
 166.757 +            carry = 0;
 166.758 +            for (int j=yLen-1, k=yLen+i; j >= 0; j--, k--) {
 166.759 +                long product = (y.value[j+y.offset] & LONG_MASK) *
 166.760 +                               (value[i+offset] & LONG_MASK) +
 166.761 +                               (z.value[k] & LONG_MASK) + carry;
 166.762 +                z.value[k] = (int)product;
 166.763 +                carry = product >>> 32;
 166.764 +            }
 166.765 +            z.value[i] = (int)carry;
 166.766 +        }
 166.767 +
 166.768 +        // Remove leading zeros from product
 166.769 +        z.normalize();
 166.770 +    }
 166.771 +
 166.772 +    /**
 166.773 +     * Multiply the contents of this MutableBigInteger by the word y. The
 166.774 +     * result is placed into z.
 166.775 +     */
 166.776 +    void mul(int y, MutableBigInteger z) {
 166.777 +        if (y == 1) {
 166.778 +            z.copyValue(this);
 166.779 +            return;
 166.780 +        }
 166.781 +
 166.782 +        if (y == 0) {
 166.783 +            z.clear();
 166.784 +            return;
 166.785 +        }
 166.786 +
 166.787 +        // Perform the multiplication word by word
 166.788 +        long ylong = y & LONG_MASK;
 166.789 +        int[] zval = (z.value.length<intLen+1 ? new int[intLen + 1]
 166.790 +                                              : z.value);
 166.791 +        long carry = 0;
 166.792 +        for (int i = intLen-1; i >= 0; i--) {
 166.793 +            long product = ylong * (value[i+offset] & LONG_MASK) + carry;
 166.794 +            zval[i+1] = (int)product;
 166.795 +            carry = product >>> 32;
 166.796 +        }
 166.797 +
 166.798 +        if (carry == 0) {
 166.799 +            z.offset = 1;
 166.800 +            z.intLen = intLen;
 166.801 +        } else {
 166.802 +            z.offset = 0;
 166.803 +            z.intLen = intLen + 1;
 166.804 +            zval[0] = (int)carry;
 166.805 +        }
 166.806 +        z.value = zval;
 166.807 +    }
 166.808 +
 166.809 +     /**
 166.810 +     * This method is used for division of an n word dividend by a one word
 166.811 +     * divisor. The quotient is placed into quotient. The one word divisor is
 166.812 +     * specified by divisor.
 166.813 +     *
 166.814 +     * @return the remainder of the division is returned.
 166.815 +     *
 166.816 +     */
 166.817 +    int divideOneWord(int divisor, MutableBigInteger quotient) {
 166.818 +        long divisorLong = divisor & LONG_MASK;
 166.819 +
 166.820 +        // Special case of one word dividend
 166.821 +        if (intLen == 1) {
 166.822 +            long dividendValue = value[offset] & LONG_MASK;
 166.823 +            int q = (int) (dividendValue / divisorLong);
 166.824 +            int r = (int) (dividendValue - q * divisorLong);
 166.825 +            quotient.value[0] = q;
 166.826 +            quotient.intLen = (q == 0) ? 0 : 1;
 166.827 +            quotient.offset = 0;
 166.828 +            return r;
 166.829 +        }
 166.830 +
 166.831 +        if (quotient.value.length < intLen)
 166.832 +            quotient.value = new int[intLen];
 166.833 +        quotient.offset = 0;
 166.834 +        quotient.intLen = intLen;
 166.835 +
 166.836 +        // Normalize the divisor
 166.837 +        int shift = Integer.numberOfLeadingZeros(divisor);
 166.838 +
 166.839 +        int rem = value[offset];
 166.840 +        long remLong = rem & LONG_MASK;
 166.841 +        if (remLong < divisorLong) {
 166.842 +            quotient.value[0] = 0;
 166.843 +        } else {
 166.844 +            quotient.value[0] = (int)(remLong / divisorLong);
 166.845 +            rem = (int) (remLong - (quotient.value[0] * divisorLong));
 166.846 +            remLong = rem & LONG_MASK;
 166.847 +        }
 166.848 +
 166.849 +        int xlen = intLen;
 166.850 +        int[] qWord = new int[2];
 166.851 +        while (--xlen > 0) {
 166.852 +            long dividendEstimate = (remLong<<32) |
 166.853 +                (value[offset + intLen - xlen] & LONG_MASK);
 166.854 +            if (dividendEstimate >= 0) {
 166.855 +                qWord[0] = (int) (dividendEstimate / divisorLong);
 166.856 +                qWord[1] = (int) (dividendEstimate - qWord[0] * divisorLong);
 166.857 +            } else {
 166.858 +                divWord(qWord, dividendEstimate, divisor);
 166.859 +            }
 166.860 +            quotient.value[intLen - xlen] = qWord[0];
 166.861 +            rem = qWord[1];
 166.862 +            remLong = rem & LONG_MASK;
 166.863 +        }
 166.864 +
 166.865 +        quotient.normalize();
 166.866 +        // Unnormalize
 166.867 +        if (shift > 0)
 166.868 +            return rem % divisor;
 166.869 +        else
 166.870 +            return rem;
 166.871 +    }
 166.872 +
 166.873 +    /**
 166.874 +     * Calculates the quotient of this div b and places the quotient in the
 166.875 +     * provided MutableBigInteger objects and the remainder object is returned.
 166.876 +     *
 166.877 +     * Uses Algorithm D in Knuth section 4.3.1.
 166.878 +     * Many optimizations to that algorithm have been adapted from the Colin
 166.879 +     * Plumb C library.
 166.880 +     * It special cases one word divisors for speed. The content of b is not
 166.881 +     * changed.
 166.882 +     *
 166.883 +     */
 166.884 +    MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) {
 166.885 +        if (b.intLen == 0)
 166.886 +            throw new ArithmeticException("BigInteger divide by zero");
 166.887 +
 166.888 +        // Dividend is zero
 166.889 +        if (intLen == 0) {
 166.890 +            quotient.intLen = quotient.offset;
 166.891 +            return new MutableBigInteger();
 166.892 +        }
 166.893 +
 166.894 +        int cmp = compare(b);
 166.895 +        // Dividend less than divisor
 166.896 +        if (cmp < 0) {
 166.897 +            quotient.intLen = quotient.offset = 0;
 166.898 +            return new MutableBigInteger(this);
 166.899 +        }
 166.900 +        // Dividend equal to divisor
 166.901 +        if (cmp == 0) {
 166.902 +            quotient.value[0] = quotient.intLen = 1;
 166.903 +            quotient.offset = 0;
 166.904 +            return new MutableBigInteger();
 166.905 +        }
 166.906 +
 166.907 +        quotient.clear();
 166.908 +        // Special case one word divisor
 166.909 +        if (b.intLen == 1) {
 166.910 +            int r = divideOneWord(b.value[b.offset], quotient);
 166.911 +            if (r == 0)
 166.912 +                return new MutableBigInteger();
 166.913 +            return new MutableBigInteger(r);
 166.914 +        }
 166.915 +
 166.916 +        // Copy divisor value to protect divisor
 166.917 +        int[] div = Arrays.copyOfRange(b.value, b.offset, b.offset + b.intLen);
 166.918 +        return divideMagnitude(div, quotient);
 166.919 +    }
 166.920 +
 166.921 +    /**
 166.922 +     * Internally used  to calculate the quotient of this div v and places the
 166.923 +     * quotient in the provided MutableBigInteger object and the remainder is
 166.924 +     * returned.
 166.925 +     *
 166.926 +     * @return the remainder of the division will be returned.
 166.927 +     */
 166.928 +    long divide(long v, MutableBigInteger quotient) {
 166.929 +        if (v == 0)
 166.930 +            throw new ArithmeticException("BigInteger divide by zero");
 166.931 +
 166.932 +        // Dividend is zero
 166.933 +        if (intLen == 0) {
 166.934 +            quotient.intLen = quotient.offset = 0;
 166.935 +            return 0;
 166.936 +        }
 166.937 +        if (v < 0)
 166.938 +            v = -v;
 166.939 +
 166.940 +        int d = (int)(v >>> 32);
 166.941 +        quotient.clear();
 166.942 +        // Special case on word divisor
 166.943 +        if (d == 0)
 166.944 +            return divideOneWord((int)v, quotient) & LONG_MASK;
 166.945 +        else {
 166.946 +            int[] div = new int[]{ d, (int)(v & LONG_MASK) };
 166.947 +            return divideMagnitude(div, quotient).toLong();
 166.948 +        }
 166.949 +    }
 166.950 +
 166.951 +    /**
 166.952 +     * Divide this MutableBigInteger by the divisor represented by its magnitude
 166.953 +     * array. The quotient will be placed into the provided quotient object &
 166.954 +     * the remainder object is returned.
 166.955 +     */
 166.956 +    private MutableBigInteger divideMagnitude(int[] divisor,
 166.957 +                                              MutableBigInteger quotient) {
 166.958 +
 166.959 +        // Remainder starts as dividend with space for a leading zero
 166.960 +        MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]);
 166.961 +        System.arraycopy(value, offset, rem.value, 1, intLen);
 166.962 +        rem.intLen = intLen;
 166.963 +        rem.offset = 1;
 166.964 +
 166.965 +        int nlen = rem.intLen;
 166.966 +
 166.967 +        // Set the quotient size
 166.968 +        int dlen = divisor.length;
 166.969 +        int limit = nlen - dlen + 1;
 166.970 +        if (quotient.value.length < limit) {
 166.971 +            quotient.value = new int[limit];
 166.972 +            quotient.offset = 0;
 166.973 +        }
 166.974 +        quotient.intLen = limit;
 166.975 +        int[] q = quotient.value;
 166.976 +
 166.977 +        // D1 normalize the divisor
 166.978 +        int shift = Integer.numberOfLeadingZeros(divisor[0]);
 166.979 +        if (shift > 0) {
 166.980 +            // First shift will not grow array
 166.981 +            BigInteger.primitiveLeftShift(divisor, dlen, shift);
 166.982 +            // But this one might
 166.983 +            rem.leftShift(shift);
 166.984 +        }
 166.985 +
 166.986 +        // Must insert leading 0 in rem if its length did not change
 166.987 +        if (rem.intLen == nlen) {
 166.988 +            rem.offset = 0;
 166.989 +            rem.value[0] = 0;
 166.990 +            rem.intLen++;
 166.991 +        }
 166.992 +
 166.993 +        int dh = divisor[0];
 166.994 +        long dhLong = dh & LONG_MASK;
 166.995 +        int dl = divisor[1];
 166.996 +        int[] qWord = new int[2];
 166.997 +
 166.998 +        // D2 Initialize j
 166.999 +        for(int j=0; j<limit; j++) {
166.1000 +            // D3 Calculate qhat
166.1001 +            // estimate qhat
166.1002 +            int qhat = 0;
166.1003 +            int qrem = 0;
166.1004 +            boolean skipCorrection = false;
166.1005 +            int nh = rem.value[j+rem.offset];
166.1006 +            int nh2 = nh + 0x80000000;
166.1007 +            int nm = rem.value[j+1+rem.offset];
166.1008 +
166.1009 +            if (nh == dh) {
166.1010 +                qhat = ~0;
166.1011 +                qrem = nh + nm;
166.1012 +                skipCorrection = qrem + 0x80000000 < nh2;
166.1013 +            } else {
166.1014 +                long nChunk = (((long)nh) << 32) | (nm & LONG_MASK);
166.1015 +                if (nChunk >= 0) {
166.1016 +                    qhat = (int) (nChunk / dhLong);
166.1017 +                    qrem = (int) (nChunk - (qhat * dhLong));
166.1018 +                } else {
166.1019 +                    divWord(qWord, nChunk, dh);
166.1020 +                    qhat = qWord[0];
166.1021 +                    qrem = qWord[1];
166.1022 +                }
166.1023 +            }
166.1024 +
166.1025 +            if (qhat == 0)
166.1026 +                continue;
166.1027 +
166.1028 +            if (!skipCorrection) { // Correct qhat
166.1029 +                long nl = rem.value[j+2+rem.offset] & LONG_MASK;
166.1030 +                long rs = ((qrem & LONG_MASK) << 32) | nl;
166.1031 +                long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK);
166.1032 +
166.1033 +                if (unsignedLongCompare(estProduct, rs)) {
166.1034 +                    qhat--;
166.1035 +                    qrem = (int)((qrem & LONG_MASK) + dhLong);
166.1036 +                    if ((qrem & LONG_MASK) >=  dhLong) {
166.1037 +                        estProduct -= (dl & LONG_MASK);
166.1038 +                        rs = ((qrem & LONG_MASK) << 32) | nl;
166.1039 +                        if (unsignedLongCompare(estProduct, rs))
166.1040 +                            qhat--;
166.1041 +                    }
166.1042 +                }
166.1043 +            }
166.1044 +
166.1045 +            // D4 Multiply and subtract
166.1046 +            rem.value[j+rem.offset] = 0;
166.1047 +            int borrow = mulsub(rem.value, divisor, qhat, dlen, j+rem.offset);
166.1048 +
166.1049 +            // D5 Test remainder
166.1050 +            if (borrow + 0x80000000 > nh2) {
166.1051 +                // D6 Add back
166.1052 +                divadd(divisor, rem.value, j+1+rem.offset);
166.1053 +                qhat--;
166.1054 +            }
166.1055 +
166.1056 +            // Store the quotient digit
166.1057 +            q[j] = qhat;
166.1058 +        } // D7 loop on j
166.1059 +
166.1060 +        // D8 Unnormalize
166.1061 +        if (shift > 0)
166.1062 +            rem.rightShift(shift);
166.1063 +
166.1064 +        quotient.normalize();
166.1065 +        rem.normalize();
166.1066 +        return rem;
166.1067 +    }
166.1068 +
166.1069 +    /**
166.1070 +     * Compare two longs as if they were unsigned.
166.1071 +     * Returns true iff one is bigger than two.
166.1072 +     */
166.1073 +    private boolean unsignedLongCompare(long one, long two) {
166.1074 +        return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE);
166.1075 +    }
166.1076 +
166.1077 +    /**
166.1078 +     * This method divides a long quantity by an int to estimate
166.1079 +     * qhat for two multi precision numbers. It is used when
166.1080 +     * the signed value of n is less than zero.
166.1081 +     */
166.1082 +    private void divWord(int[] result, long n, int d) {
166.1083 +        long dLong = d & LONG_MASK;
166.1084 +
166.1085 +        if (dLong == 1) {
166.1086 +            result[0] = (int)n;
166.1087 +            result[1] = 0;
166.1088 +            return;
166.1089 +        }
166.1090 +
166.1091 +        // Approximate the quotient and remainder
166.1092 +        long q = (n >>> 1) / (dLong >>> 1);
166.1093 +        long r = n - q*dLong;
166.1094 +
166.1095 +        // Correct the approximation
166.1096 +        while (r < 0) {
166.1097 +            r += dLong;
166.1098 +            q--;
166.1099 +        }
166.1100 +        while (r >= dLong) {
166.1101 +            r -= dLong;
166.1102 +            q++;
166.1103 +        }
166.1104 +
166.1105 +        // n - q*dlong == r && 0 <= r <dLong, hence we're done.
166.1106 +        result[0] = (int)q;
166.1107 +        result[1] = (int)r;
166.1108 +    }
166.1109 +
166.1110 +    /**
166.1111 +     * Calculate GCD of this and b. This and b are changed by the computation.
166.1112 +     */
166.1113 +    MutableBigInteger hybridGCD(MutableBigInteger b) {
166.1114 +        // Use Euclid's algorithm until the numbers are approximately the
166.1115 +        // same length, then use the binary GCD algorithm to find the GCD.
166.1116 +        MutableBigInteger a = this;
166.1117 +        MutableBigInteger q = new MutableBigInteger();
166.1118 +
166.1119 +        while (b.intLen != 0) {
166.1120 +            if (Math.abs(a.intLen - b.intLen) < 2)
166.1121 +                return a.binaryGCD(b);
166.1122 +
166.1123 +            MutableBigInteger r = a.divide(b, q);
166.1124 +            a = b;
166.1125 +            b = r;
166.1126 +        }
166.1127 +        return a;
166.1128 +    }
166.1129 +
166.1130 +    /**
166.1131 +     * Calculate GCD of this and v.
166.1132 +     * Assumes that this and v are not zero.
166.1133 +     */
166.1134 +    private MutableBigInteger binaryGCD(MutableBigInteger v) {
166.1135 +        // Algorithm B from Knuth section 4.5.2
166.1136 +        MutableBigInteger u = this;
166.1137 +        MutableBigInteger r = new MutableBigInteger();
166.1138 +
166.1139 +        // step B1
166.1140 +        int s1 = u.getLowestSetBit();
166.1141 +        int s2 = v.getLowestSetBit();
166.1142 +        int k = (s1 < s2) ? s1 : s2;
166.1143 +        if (k != 0) {
166.1144 +            u.rightShift(k);
166.1145 +            v.rightShift(k);
166.1146 +        }
166.1147 +
166.1148 +        // step B2
166.1149 +        boolean uOdd = (k==s1);
166.1150 +        MutableBigInteger t = uOdd ? v: u;
166.1151 +        int tsign = uOdd ? -1 : 1;
166.1152 +
166.1153 +        int lb;
166.1154 +        while ((lb = t.getLowestSetBit()) >= 0) {
166.1155 +            // steps B3 and B4
166.1156 +            t.rightShift(lb);
166.1157 +            // step B5
166.1158 +            if (tsign > 0)
166.1159 +                u = t;
166.1160 +            else
166.1161 +                v = t;
166.1162 +
166.1163 +            // Special case one word numbers
166.1164 +            if (u.intLen < 2 && v.intLen < 2) {
166.1165 +                int x = u.value[u.offset];
166.1166 +                int y = v.value[v.offset];
166.1167 +                x  = binaryGcd(x, y);
166.1168 +                r.value[0] = x;
166.1169 +                r.intLen = 1;
166.1170 +                r.offset = 0;
166.1171 +                if (k > 0)
166.1172 +                    r.leftShift(k);
166.1173 +                return r;
166.1174 +            }
166.1175 +
166.1176 +            // step B6
166.1177 +            if ((tsign = u.difference(v)) == 0)
166.1178 +                break;
166.1179 +            t = (tsign >= 0) ? u : v;
166.1180 +        }
166.1181 +
166.1182 +        if (k > 0)
166.1183 +            u.leftShift(k);
166.1184 +        return u;
166.1185 +    }
166.1186 +
166.1187 +    /**
166.1188 +     * Calculate GCD of a and b interpreted as unsigned integers.
166.1189 +     */
166.1190 +    static int binaryGcd(int a, int b) {
166.1191 +        if (b==0)
166.1192 +            return a;
166.1193 +        if (a==0)
166.1194 +            return b;
166.1195 +
166.1196 +        // Right shift a & b till their last bits equal to 1.
166.1197 +        int aZeros = Integer.numberOfTrailingZeros(a);
166.1198 +        int bZeros = Integer.numberOfTrailingZeros(b);
166.1199 +        a >>>= aZeros;
166.1200 +        b >>>= bZeros;
166.1201 +
166.1202 +        int t = (aZeros < bZeros ? aZeros : bZeros);
166.1203 +
166.1204 +        while (a != b) {
166.1205 +            if ((a+0x80000000) > (b+0x80000000)) {  // a > b as unsigned
166.1206 +                a -= b;
166.1207 +                a >>>= Integer.numberOfTrailingZeros(a);
166.1208 +            } else {
166.1209 +                b -= a;
166.1210 +                b >>>= Integer.numberOfTrailingZeros(b);
166.1211 +            }
166.1212 +        }
166.1213 +        return a<<t;
166.1214 +    }
166.1215 +
166.1216 +    /**
166.1217 +     * Returns the modInverse of this mod p. This and p are not affected by
166.1218 +     * the operation.
166.1219 +     */
166.1220 +    MutableBigInteger mutableModInverse(MutableBigInteger p) {
166.1221 +        // Modulus is odd, use Schroeppel's algorithm
166.1222 +        if (p.isOdd())
166.1223 +            return modInverse(p);
166.1224 +
166.1225 +        // Base and modulus are even, throw exception
166.1226 +        if (isEven())
166.1227 +            throw new ArithmeticException("BigInteger not invertible.");
166.1228 +
166.1229 +        // Get even part of modulus expressed as a power of 2
166.1230 +        int powersOf2 = p.getLowestSetBit();
166.1231 +
166.1232 +        // Construct odd part of modulus
166.1233 +        MutableBigInteger oddMod = new MutableBigInteger(p);
166.1234 +        oddMod.rightShift(powersOf2);
166.1235 +
166.1236 +        if (oddMod.isOne())
166.1237 +            return modInverseMP2(powersOf2);
166.1238 +
166.1239 +        // Calculate 1/a mod oddMod
166.1240 +        MutableBigInteger oddPart = modInverse(oddMod);
166.1241 +
166.1242 +        // Calculate 1/a mod evenMod
166.1243 +        MutableBigInteger evenPart = modInverseMP2(powersOf2);
166.1244 +
166.1245 +        // Combine the results using Chinese Remainder Theorem
166.1246 +        MutableBigInteger y1 = modInverseBP2(oddMod, powersOf2);
166.1247 +        MutableBigInteger y2 = oddMod.modInverseMP2(powersOf2);
166.1248 +
166.1249 +        MutableBigInteger temp1 = new MutableBigInteger();
166.1250 +        MutableBigInteger temp2 = new MutableBigInteger();
166.1251 +        MutableBigInteger result = new MutableBigInteger();
166.1252 +
166.1253 +        oddPart.leftShift(powersOf2);
166.1254 +        oddPart.multiply(y1, result);
166.1255 +
166.1256 +        evenPart.multiply(oddMod, temp1);
166.1257 +        temp1.multiply(y2, temp2);
166.1258 +
166.1259 +        result.add(temp2);
166.1260 +        return result.divide(p, temp1);
166.1261 +    }
166.1262 +
166.1263 +    /*
166.1264 +     * Calculate the multiplicative inverse of this mod 2^k.
166.1265 +     */
166.1266 +    MutableBigInteger modInverseMP2(int k) {
166.1267 +        if (isEven())
166.1268 +            throw new ArithmeticException("Non-invertible. (GCD != 1)");
166.1269 +
166.1270 +        if (k > 64)
166.1271 +            return euclidModInverse(k);
166.1272 +
166.1273 +        int t = inverseMod32(value[offset+intLen-1]);
166.1274 +
166.1275 +        if (k < 33) {
166.1276 +            t = (k == 32 ? t : t & ((1 << k) - 1));
166.1277 +            return new MutableBigInteger(t);
166.1278 +        }
166.1279 +
166.1280 +        long pLong = (value[offset+intLen-1] & LONG_MASK);
166.1281 +        if (intLen > 1)
166.1282 +            pLong |=  ((long)value[offset+intLen-2] << 32);
166.1283 +        long tLong = t & LONG_MASK;
166.1284 +        tLong = tLong * (2 - pLong * tLong);  // 1 more Newton iter step
166.1285 +        tLong = (k == 64 ? tLong : tLong & ((1L << k) - 1));
166.1286 +
166.1287 +        MutableBigInteger result = new MutableBigInteger(new int[2]);
166.1288 +        result.value[0] = (int)(tLong >>> 32);
166.1289 +        result.value[1] = (int)tLong;
166.1290 +        result.intLen = 2;
166.1291 +        result.normalize();
166.1292 +        return result;
166.1293 +    }
166.1294 +
166.1295 +    /*
166.1296 +     * Returns the multiplicative inverse of val mod 2^32.  Assumes val is odd.
166.1297 +     */
166.1298 +    static int inverseMod32(int val) {
166.1299 +        // Newton's iteration!
166.1300 +        int t = val;
166.1301 +        t *= 2 - val*t;
166.1302 +        t *= 2 - val*t;
166.1303 +        t *= 2 - val*t;
166.1304 +        t *= 2 - val*t;
166.1305 +        return t;
166.1306 +    }
166.1307 +
166.1308 +    /*
166.1309 +     * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd.
166.1310 +     */
166.1311 +    static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) {
166.1312 +        // Copy the mod to protect original
166.1313 +        return fixup(new MutableBigInteger(1), new MutableBigInteger(mod), k);
166.1314 +    }
166.1315 +
166.1316 +    /**
166.1317 +     * Calculate the multiplicative inverse of this mod mod, where mod is odd.
166.1318 +     * This and mod are not changed by the calculation.
166.1319 +     *
166.1320 +     * This method implements an algorithm due to Richard Schroeppel, that uses
166.1321 +     * the same intermediate representation as Montgomery Reduction
166.1322 +     * ("Montgomery Form").  The algorithm is described in an unpublished
166.1323 +     * manuscript entitled "Fast Modular Reciprocals."
166.1324 +     */
166.1325 +    private MutableBigInteger modInverse(MutableBigInteger mod) {
166.1326 +        MutableBigInteger p = new MutableBigInteger(mod);
166.1327 +        MutableBigInteger f = new MutableBigInteger(this);
166.1328 +        MutableBigInteger g = new MutableBigInteger(p);
166.1329 +        SignedMutableBigInteger c = new SignedMutableBigInteger(1);
166.1330 +        SignedMutableBigInteger d = new SignedMutableBigInteger();
166.1331 +        MutableBigInteger temp = null;
166.1332 +        SignedMutableBigInteger sTemp = null;
166.1333 +
166.1334 +        int k = 0;
166.1335 +        // Right shift f k times until odd, left shift d k times
166.1336 +        if (f.isEven()) {
166.1337 +            int trailingZeros = f.getLowestSetBit();
166.1338 +            f.rightShift(trailingZeros);
166.1339 +            d.leftShift(trailingZeros);
166.1340 +            k = trailingZeros;
166.1341 +        }
166.1342 +
166.1343 +        // The Almost Inverse Algorithm
166.1344 +        while(!f.isOne()) {
166.1345 +            // If gcd(f, g) != 1, number is not invertible modulo mod
166.1346 +            if (f.isZero())
166.1347 +                throw new ArithmeticException("BigInteger not invertible.");
166.1348 +
166.1349 +            // If f < g exchange f, g and c, d
166.1350 +            if (f.compare(g) < 0) {
166.1351 +                temp = f; f = g; g = temp;
166.1352 +                sTemp = d; d = c; c = sTemp;
166.1353 +            }
166.1354 +
166.1355 +            // If f == g (mod 4)
166.1356 +            if (((f.value[f.offset + f.intLen - 1] ^
166.1357 +                 g.value[g.offset + g.intLen - 1]) & 3) == 0) {
166.1358 +                f.subtract(g);
166.1359 +                c.signedSubtract(d);
166.1360 +            } else { // If f != g (mod 4)
166.1361 +                f.add(g);
166.1362 +                c.signedAdd(d);
166.1363 +            }
166.1364 +
166.1365 +            // Right shift f k times until odd, left shift d k times
166.1366 +            int trailingZeros = f.getLowestSetBit();
166.1367 +            f.rightShift(trailingZeros);
166.1368 +            d.leftShift(trailingZeros);
166.1369 +            k += trailingZeros;
166.1370 +        }
166.1371 +
166.1372 +        while (c.sign < 0)
166.1373 +           c.signedAdd(p);
166.1374 +
166.1375 +        return fixup(c, p, k);
166.1376 +    }
166.1377 +
166.1378 +    /*
166.1379 +     * The Fixup Algorithm
166.1380 +     * Calculates X such that X = C * 2^(-k) (mod P)
166.1381 +     * Assumes C<P and P is odd.
166.1382 +     */
166.1383 +    static MutableBigInteger fixup(MutableBigInteger c, MutableBigInteger p,
166.1384 +                                                                      int k) {
166.1385 +        MutableBigInteger temp = new MutableBigInteger();
166.1386 +        // Set r to the multiplicative inverse of p mod 2^32
166.1387 +        int r = -inverseMod32(p.value[p.offset+p.intLen-1]);
166.1388 +
166.1389 +        for(int i=0, numWords = k >> 5; i<numWords; i++) {
166.1390 +            // V = R * c (mod 2^j)
166.1391 +            int  v = r * c.value[c.offset + c.intLen-1];
166.1392 +            // c = c + (v * p)
166.1393 +            p.mul(v, temp);
166.1394 +            c.add(temp);
166.1395 +            // c = c / 2^j
166.1396 +            c.intLen--;
166.1397 +        }
166.1398 +        int numBits = k & 0x1f;
166.1399 +        if (numBits != 0) {
166.1400 +            // V = R * c (mod 2^j)
166.1401 +            int v = r * c.value[c.offset + c.intLen-1];
166.1402 +            v &= ((1<<numBits) - 1);
166.1403 +            // c = c + (v * p)
166.1404 +            p.mul(v, temp);
166.1405 +            c.add(temp);
166.1406 +            // c = c / 2^j
166.1407 +            c.rightShift(numBits);
166.1408 +        }
166.1409 +
166.1410 +        // In theory, c may be greater than p at this point (Very rare!)
166.1411 +        while (c.compare(p) >= 0)
166.1412 +            c.subtract(p);
166.1413 +
166.1414 +        return c;
166.1415 +    }
166.1416 +
166.1417 +    /**
166.1418 +     * Uses the extended Euclidean algorithm to compute the modInverse of base
166.1419 +     * mod a modulus that is a power of 2. The modulus is 2^k.
166.1420 +     */
166.1421 +    MutableBigInteger euclidModInverse(int k) {
166.1422 +        MutableBigInteger b = new MutableBigInteger(1);
166.1423 +        b.leftShift(k);
166.1424 +        MutableBigInteger mod = new MutableBigInteger(b);
166.1425 +
166.1426 +        MutableBigInteger a = new MutableBigInteger(this);
166.1427 +        MutableBigInteger q = new MutableBigInteger();
166.1428 +        MutableBigInteger r = b.divide(a, q);
166.1429 +
166.1430 +        MutableBigInteger swapper = b;
166.1431 +        // swap b & r
166.1432 +        b = r;
166.1433 +        r = swapper;
166.1434 +
166.1435 +        MutableBigInteger t1 = new MutableBigInteger(q);
166.1436 +        MutableBigInteger t0 = new MutableBigInteger(1);
166.1437 +        MutableBigInteger temp = new MutableBigInteger();
166.1438 +
166.1439 +        while (!b.isOne()) {
166.1440 +            r = a.divide(b, q);
166.1441 +
166.1442 +            if (r.intLen == 0)
166.1443 +                throw new ArithmeticException("BigInteger not invertible.");
166.1444 +
166.1445 +            swapper = r;
166.1446 +            a = swapper;
166.1447 +
166.1448 +            if (q.intLen == 1)
166.1449 +                t1.mul(q.value[q.offset], temp);
166.1450 +            else
166.1451 +                q.multiply(t1, temp);
166.1452 +            swapper = q;
166.1453 +            q = temp;
166.1454 +            temp = swapper;
166.1455 +            t0.add(q);
166.1456 +
166.1457 +            if (a.isOne())
166.1458 +                return t0;
166.1459 +
166.1460 +            r = b.divide(a, q);
166.1461 +
166.1462 +            if (r.intLen == 0)
166.1463 +                throw new ArithmeticException("BigInteger not invertible.");
166.1464 +
166.1465 +            swapper = b;
166.1466 +            b =  r;
166.1467 +
166.1468 +            if (q.intLen == 1)
166.1469 +                t0.mul(q.value[q.offset], temp);
166.1470 +            else
166.1471 +                q.multiply(t0, temp);
166.1472 +            swapper = q; q = temp; temp = swapper;
166.1473 +
166.1474 +            t1.add(q);
166.1475 +        }
166.1476 +        mod.subtract(t1);
166.1477 +        return mod;
166.1478 +    }
166.1479 +
166.1480 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/rt/emul/compact/src/main/java/java/math/RoundingMode.java	Wed Apr 30 15:04:10 2014 +0200
   167.3 @@ -0,0 +1,349 @@
   167.4 +/*
   167.5 + * Copyright (c) 2003, 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 + * Portions Copyright IBM Corporation, 2001. All Rights Reserved.
  167.31 + */
  167.32 +package java.math;
  167.33 +
  167.34 +/**
  167.35 + * Specifies a <i>rounding behavior</i> for numerical operations
  167.36 + * capable of discarding precision. Each rounding mode indicates how
  167.37 + * the least significant returned digit of a rounded result is to be
  167.38 + * calculated.  If fewer digits are returned than the digits needed to
  167.39 + * represent the exact numerical result, the discarded digits will be
  167.40 + * referred to as the <i>discarded fraction</i> regardless the digits'
  167.41 + * contribution to the value of the number.  In other words,
  167.42 + * considered as a numerical value, the discarded fraction could have
  167.43 + * an absolute value greater than one.
  167.44 + *
  167.45 + * <p>Each rounding mode description includes a table listing how
  167.46 + * different two-digit decimal values would round to a one digit
  167.47 + * decimal value under the rounding mode in question.  The result
  167.48 + * column in the tables could be gotten by creating a
  167.49 + * {@code BigDecimal} number with the specified value, forming a
  167.50 + * {@link MathContext} object with the proper settings
  167.51 + * ({@code precision} set to {@code 1}, and the
  167.52 + * {@code roundingMode} set to the rounding mode in question), and
  167.53 + * calling {@link BigDecimal#round round} on this number with the
  167.54 + * proper {@code MathContext}.  A summary table showing the results
  167.55 + * of these rounding operations for all rounding modes appears below.
  167.56 + *
  167.57 + *<p>
  167.58 + *<table border>
  167.59 + * <caption><b>Summary of Rounding Operations Under Different Rounding Modes</b></caption>
  167.60 + * <tr><th></th><th colspan=8>Result of rounding input to one digit with the given
  167.61 + *                           rounding mode</th>
  167.62 + * <tr valign=top>
  167.63 + * <th>Input Number</th>         <th>{@code UP}</th>
  167.64 + *                                           <th>{@code DOWN}</th>
  167.65 + *                                                        <th>{@code CEILING}</th>
  167.66 + *                                                                       <th>{@code FLOOR}</th>
  167.67 + *                                                                                    <th>{@code HALF_UP}</th>
  167.68 + *                                                                                                   <th>{@code HALF_DOWN}</th>
  167.69 + *                                                                                                                    <th>{@code HALF_EVEN}</th>
  167.70 + *                                                                                                                                     <th>{@code UNNECESSARY}</th>
  167.71 + *
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.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>
  167.82 + *</table>
  167.83 + *
  167.84 + *
  167.85 + * <p>This {@code enum} is intended to replace the integer-based
  167.86 + * enumeration of rounding mode constants in {@link BigDecimal}
  167.87 + * ({@link BigDecimal#ROUND_UP}, {@link BigDecimal#ROUND_DOWN},
  167.88 + * etc. ).
  167.89 + *
  167.90 + * @see     BigDecimal
  167.91 + * @see     MathContext
  167.92 + * @author  Josh Bloch
  167.93 + * @author  Mike Cowlishaw
  167.94 + * @author  Joseph D. Darcy
  167.95 + * @since 1.5
  167.96 + */
  167.97 +public enum RoundingMode {
  167.98 +
  167.99 +        /**
 167.100 +         * Rounding mode to round away from zero.  Always increments the
 167.101 +         * digit prior to a non-zero discarded fraction.  Note that this
 167.102 +         * rounding mode never decreases the magnitude of the calculated
 167.103 +         * value.
 167.104 +         *
 167.105 +         *<p>Example:
 167.106 +         *<table border>
 167.107 +         *<tr valign=top><th>Input Number</th>
 167.108 +         *    <th>Input rounded to one digit<br> with {@code UP} rounding
 167.109 +         *<tr align=right><td>5.5</td>  <td>6</td>
 167.110 +         *<tr align=right><td>2.5</td>  <td>3</td>
 167.111 +         *<tr align=right><td>1.6</td>  <td>2</td>
 167.112 +         *<tr align=right><td>1.1</td>  <td>2</td>
 167.113 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.114 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.115 +         *<tr align=right><td>-1.1</td> <td>-2</td>
 167.116 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 167.117 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 167.118 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 167.119 +         *</table>
 167.120 +         */
 167.121 +    UP(BigDecimal.ROUND_UP),
 167.122 +
 167.123 +        /**
 167.124 +         * Rounding mode to round towards zero.  Never increments the digit
 167.125 +         * prior to a discarded fraction (i.e., truncates).  Note that this
 167.126 +         * rounding mode never increases the magnitude of the calculated value.
 167.127 +         *
 167.128 +         *<p>Example:
 167.129 +         *<table border>
 167.130 +         *<tr valign=top><th>Input Number</th>
 167.131 +         *    <th>Input rounded to one digit<br> with {@code DOWN} rounding
 167.132 +         *<tr align=right><td>5.5</td>  <td>5</td>
 167.133 +         *<tr align=right><td>2.5</td>  <td>2</td>
 167.134 +         *<tr align=right><td>1.6</td>  <td>1</td>
 167.135 +         *<tr align=right><td>1.1</td>  <td>1</td>
 167.136 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.137 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.138 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 167.139 +         *<tr align=right><td>-1.6</td> <td>-1</td>
 167.140 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 167.141 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 167.142 +         *</table>
 167.143 +         */
 167.144 +    DOWN(BigDecimal.ROUND_DOWN),
 167.145 +
 167.146 +        /**
 167.147 +         * Rounding mode to round towards positive infinity.  If the
 167.148 +         * result is positive, behaves as for {@code RoundingMode.UP};
 167.149 +         * if negative, behaves as for {@code RoundingMode.DOWN}.  Note
 167.150 +         * that this rounding mode never decreases the calculated value.
 167.151 +         *
 167.152 +         *<p>Example:
 167.153 +         *<table border>
 167.154 +         *<tr valign=top><th>Input Number</th>
 167.155 +         *    <th>Input rounded to one digit<br> with {@code CEILING} rounding
 167.156 +         *<tr align=right><td>5.5</td>  <td>6</td>
 167.157 +         *<tr align=right><td>2.5</td>  <td>3</td>
 167.158 +         *<tr align=right><td>1.6</td>  <td>2</td>
 167.159 +         *<tr align=right><td>1.1</td>  <td>2</td>
 167.160 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.161 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.162 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 167.163 +         *<tr align=right><td>-1.6</td> <td>-1</td>
 167.164 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 167.165 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 167.166 +         *</table>
 167.167 +         */
 167.168 +    CEILING(BigDecimal.ROUND_CEILING),
 167.169 +
 167.170 +        /**
 167.171 +         * Rounding mode to round towards negative infinity.  If the
 167.172 +         * result is positive, behave as for {@code RoundingMode.DOWN};
 167.173 +         * if negative, behave as for {@code RoundingMode.UP}.  Note that
 167.174 +         * this rounding mode never increases the calculated value.
 167.175 +         *
 167.176 +         *<p>Example:
 167.177 +         *<table border>
 167.178 +         *<tr valign=top><th>Input Number</th>
 167.179 +         *    <th>Input rounded to one digit<br> with {@code FLOOR} rounding
 167.180 +         *<tr align=right><td>5.5</td>  <td>5</td>
 167.181 +         *<tr align=right><td>2.5</td>  <td>2</td>
 167.182 +         *<tr align=right><td>1.6</td>  <td>1</td>
 167.183 +         *<tr align=right><td>1.1</td>  <td>1</td>
 167.184 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.185 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.186 +         *<tr align=right><td>-1.1</td> <td>-2</td>
 167.187 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 167.188 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 167.189 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 167.190 +         *</table>
 167.191 +         */
 167.192 +    FLOOR(BigDecimal.ROUND_FLOOR),
 167.193 +
 167.194 +        /**
 167.195 +         * Rounding mode to round towards {@literal "nearest neighbor"}
 167.196 +         * unless both neighbors are equidistant, in which case round up.
 167.197 +         * Behaves as for {@code RoundingMode.UP} if the discarded
 167.198 +         * fraction is &ge; 0.5; otherwise, behaves as for
 167.199 +         * {@code RoundingMode.DOWN}.  Note that this is the rounding
 167.200 +         * mode commonly taught at school.
 167.201 +         *
 167.202 +         *<p>Example:
 167.203 +         *<table border>
 167.204 +         *<tr valign=top><th>Input Number</th>
 167.205 +         *    <th>Input rounded to one digit<br> with {@code HALF_UP} rounding
 167.206 +         *<tr align=right><td>5.5</td>  <td>6</td>
 167.207 +         *<tr align=right><td>2.5</td>  <td>3</td>
 167.208 +         *<tr align=right><td>1.6</td>  <td>2</td>
 167.209 +         *<tr align=right><td>1.1</td>  <td>1</td>
 167.210 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.211 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.212 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 167.213 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 167.214 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 167.215 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 167.216 +         *</table>
 167.217 +         */
 167.218 +    HALF_UP(BigDecimal.ROUND_HALF_UP),
 167.219 +
 167.220 +        /**
 167.221 +         * Rounding mode to round towards {@literal "nearest neighbor"}
 167.222 +         * unless both neighbors are equidistant, in which case round
 167.223 +         * down.  Behaves as for {@code RoundingMode.UP} if the discarded
 167.224 +         * fraction is &gt; 0.5; otherwise, behaves as for
 167.225 +         * {@code RoundingMode.DOWN}.
 167.226 +         *
 167.227 +         *<p>Example:
 167.228 +         *<table border>
 167.229 +         *<tr valign=top><th>Input Number</th>
 167.230 +         *    <th>Input rounded to one digit<br> with {@code HALF_DOWN} rounding
 167.231 +         *<tr align=right><td>5.5</td>  <td>5</td>
 167.232 +         *<tr align=right><td>2.5</td>  <td>2</td>
 167.233 +         *<tr align=right><td>1.6</td>  <td>2</td>
 167.234 +         *<tr align=right><td>1.1</td>  <td>1</td>
 167.235 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.236 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.237 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 167.238 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 167.239 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 167.240 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 167.241 +         *</table>
 167.242 +         */
 167.243 +    HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
 167.244 +
 167.245 +        /**
 167.246 +         * Rounding mode to round towards the {@literal "nearest neighbor"}
 167.247 +         * unless both neighbors are equidistant, in which case, round
 167.248 +         * towards the even neighbor.  Behaves as for
 167.249 +         * {@code RoundingMode.HALF_UP} if the digit to the left of the
 167.250 +         * discarded fraction is odd; behaves as for
 167.251 +         * {@code RoundingMode.HALF_DOWN} if it's even.  Note that this
 167.252 +         * is the rounding mode that statistically minimizes cumulative
 167.253 +         * error when applied repeatedly over a sequence of calculations.
 167.254 +         * It is sometimes known as {@literal "Banker's rounding,"} and is
 167.255 +         * chiefly used in the USA.  This rounding mode is analogous to
 167.256 +         * the rounding policy used for {@code float} and {@code double}
 167.257 +         * arithmetic in Java.
 167.258 +         *
 167.259 +         *<p>Example:
 167.260 +         *<table border>
 167.261 +         *<tr valign=top><th>Input Number</th>
 167.262 +         *    <th>Input rounded to one digit<br> with {@code HALF_EVEN} rounding
 167.263 +         *<tr align=right><td>5.5</td>  <td>6</td>
 167.264 +         *<tr align=right><td>2.5</td>  <td>2</td>
 167.265 +         *<tr align=right><td>1.6</td>  <td>2</td>
 167.266 +         *<tr align=right><td>1.1</td>  <td>1</td>
 167.267 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.268 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.269 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 167.270 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 167.271 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 167.272 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 167.273 +         *</table>
 167.274 +         */
 167.275 +    HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
 167.276 +
 167.277 +        /**
 167.278 +         * Rounding mode to assert that the requested operation has an exact
 167.279 +         * result, hence no rounding is necessary.  If this rounding mode is
 167.280 +         * specified on an operation that yields an inexact result, an
 167.281 +         * {@code ArithmeticException} is thrown.
 167.282 +         *<p>Example:
 167.283 +         *<table border>
 167.284 +         *<tr valign=top><th>Input Number</th>
 167.285 +         *    <th>Input rounded to one digit<br> with {@code UNNECESSARY} rounding
 167.286 +         *<tr align=right><td>5.5</td>  <td>throw {@code ArithmeticException}</td>
 167.287 +         *<tr align=right><td>2.5</td>  <td>throw {@code ArithmeticException}</td>
 167.288 +         *<tr align=right><td>1.6</td>  <td>throw {@code ArithmeticException}</td>
 167.289 +         *<tr align=right><td>1.1</td>  <td>throw {@code ArithmeticException}</td>
 167.290 +         *<tr align=right><td>1.0</td>  <td>1</td>
 167.291 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 167.292 +         *<tr align=right><td>-1.1</td> <td>throw {@code ArithmeticException}</td>
 167.293 +         *<tr align=right><td>-1.6</td> <td>throw {@code ArithmeticException}</td>
 167.294 +         *<tr align=right><td>-2.5</td> <td>throw {@code ArithmeticException}</td>
 167.295 +         *<tr align=right><td>-5.5</td> <td>throw {@code ArithmeticException}</td>
 167.296 +         *</table>
 167.297 +         */
 167.298 +    UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
 167.299 +
 167.300 +    // Corresponding BigDecimal rounding constant
 167.301 +    final int oldMode;
 167.302 +
 167.303 +    /**
 167.304 +     * Constructor
 167.305 +     *
 167.306 +     * @param oldMode The {@code BigDecimal} constant corresponding to
 167.307 +     *        this mode
 167.308 +     */
 167.309 +    private RoundingMode(int oldMode) {
 167.310 +        this.oldMode = oldMode;
 167.311 +    }
 167.312 +
 167.313 +    /**
 167.314 +     * Returns the {@code RoundingMode} object corresponding to a
 167.315 +     * legacy integer rounding mode constant in {@link BigDecimal}.
 167.316 +     *
 167.317 +     * @param  rm legacy integer rounding mode to convert
 167.318 +     * @return {@code RoundingMode} corresponding to the given integer.
 167.319 +     * @throws IllegalArgumentException integer is out of range
 167.320 +     */
 167.321 +    public static RoundingMode valueOf(int rm) {
 167.322 +        switch(rm) {
 167.323 +
 167.324 +        case BigDecimal.ROUND_UP:
 167.325 +            return UP;
 167.326 +
 167.327 +        case BigDecimal.ROUND_DOWN:
 167.328 +            return DOWN;
 167.329 +
 167.330 +        case BigDecimal.ROUND_CEILING:
 167.331 +            return CEILING;
 167.332 +
 167.333 +        case BigDecimal.ROUND_FLOOR:
 167.334 +            return FLOOR;
 167.335 +
 167.336 +        case BigDecimal.ROUND_HALF_UP:
 167.337 +            return HALF_UP;
 167.338 +
 167.339 +        case BigDecimal.ROUND_HALF_DOWN:
 167.340 +            return HALF_DOWN;
 167.341 +
 167.342 +        case BigDecimal.ROUND_HALF_EVEN:
 167.343 +            return HALF_EVEN;
 167.344 +
 167.345 +        case BigDecimal.ROUND_UNNECESSARY:
 167.346 +            return UNNECESSARY;
 167.347 +
 167.348 +        default:
 167.349 +            throw new IllegalArgumentException("argument out of range");
 167.350 +        }
 167.351 +    }
 167.352 +}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/rt/emul/compact/src/main/java/java/math/SignedMutableBigInteger.java	Wed Apr 30 15:04:10 2014 +0200
   168.3 @@ -0,0 +1,135 @@
   168.4 +/*
   168.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   168.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   168.7 + *
   168.8 + * This code is free software; you can redistribute it and/or modify it
   168.9 + * under the terms of the GNU General Public License version 2 only, as
  168.10 + * published by the Free Software Foundation.  Oracle designates this
  168.11 + * particular file as subject to the "Classpath" exception as provided
  168.12 + * by Oracle in the LICENSE file that accompanied this code.
  168.13 + *
  168.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  168.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  168.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  168.17 + * version 2 for more details (a copy is included in the LICENSE file that
  168.18 + * accompanied this code).
  168.19 + *
  168.20 + * You should have received a copy of the GNU General Public License version
  168.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  168.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  168.23 + *
  168.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  168.25 + * or visit www.oracle.com if you need additional information or have any
  168.26 + * questions.
  168.27 + */
  168.28 +
  168.29 +package java.math;
  168.30 +
  168.31 +/**
  168.32 + * A class used to represent multiprecision integers that makes efficient
  168.33 + * use of allocated space by allowing a number to occupy only part of
  168.34 + * an array so that the arrays do not have to be reallocated as often.
  168.35 + * When performing an operation with many iterations the array used to
  168.36 + * hold a number is only increased when necessary and does not have to
  168.37 + * be the same size as the number it represents. A mutable number allows
  168.38 + * calculations to occur on the same number without having to create
  168.39 + * a new number for every step of the calculation as occurs with
  168.40 + * BigIntegers.
  168.41 + *
  168.42 + * Note that SignedMutableBigIntegers only support signed addition and
  168.43 + * subtraction. All other operations occur as with MutableBigIntegers.
  168.44 + *
  168.45 + * @see     BigInteger
  168.46 + * @author  Michael McCloskey
  168.47 + * @since   1.3
  168.48 + */
  168.49 +
  168.50 +class SignedMutableBigInteger extends MutableBigInteger {
  168.51 +
  168.52 +   /**
  168.53 +     * The sign of this MutableBigInteger.
  168.54 +     */
  168.55 +    int sign = 1;
  168.56 +
  168.57 +    // Constructors
  168.58 +
  168.59 +    /**
  168.60 +     * The default constructor. An empty MutableBigInteger is created with
  168.61 +     * a one word capacity.
  168.62 +     */
  168.63 +    SignedMutableBigInteger() {
  168.64 +        super();
  168.65 +    }
  168.66 +
  168.67 +    /**
  168.68 +     * Construct a new MutableBigInteger with a magnitude specified by
  168.69 +     * the int val.
  168.70 +     */
  168.71 +    SignedMutableBigInteger(int val) {
  168.72 +        super(val);
  168.73 +    }
  168.74 +
  168.75 +    /**
  168.76 +     * Construct a new MutableBigInteger with a magnitude equal to the
  168.77 +     * specified MutableBigInteger.
  168.78 +     */
  168.79 +    SignedMutableBigInteger(MutableBigInteger val) {
  168.80 +        super(val);
  168.81 +    }
  168.82 +
  168.83 +   // Arithmetic Operations
  168.84 +
  168.85 +   /**
  168.86 +     * Signed addition built upon unsigned add and subtract.
  168.87 +     */
  168.88 +    void signedAdd(SignedMutableBigInteger addend) {
  168.89 +        if (sign == addend.sign)
  168.90 +            add(addend);
  168.91 +        else
  168.92 +            sign = sign * subtract(addend);
  168.93 +
  168.94 +    }
  168.95 +
  168.96 +   /**
  168.97 +     * Signed addition built upon unsigned add and subtract.
  168.98 +     */
  168.99 +    void signedAdd(MutableBigInteger addend) {
 168.100 +        if (sign == 1)
 168.101 +            add(addend);
 168.102 +        else
 168.103 +            sign = sign * subtract(addend);
 168.104 +
 168.105 +    }
 168.106 +
 168.107 +   /**
 168.108 +     * Signed subtraction built upon unsigned add and subtract.
 168.109 +     */
 168.110 +    void signedSubtract(SignedMutableBigInteger addend) {
 168.111 +        if (sign == addend.sign)
 168.112 +            sign = sign * subtract(addend);
 168.113 +        else
 168.114 +            add(addend);
 168.115 +
 168.116 +    }
 168.117 +
 168.118 +   /**
 168.119 +     * Signed subtraction built upon unsigned add and subtract.
 168.120 +     */
 168.121 +    void signedSubtract(MutableBigInteger addend) {
 168.122 +        if (sign == 1)
 168.123 +            sign = sign * subtract(addend);
 168.124 +        else
 168.125 +            add(addend);
 168.126 +        if (intLen == 0)
 168.127 +             sign = 1;
 168.128 +    }
 168.129 +
 168.130 +    /**
 168.131 +     * Print out the first intLen ints of this MutableBigInteger's value
 168.132 +     * array starting at offset.
 168.133 +     */
 168.134 +    public String toString() {
 168.135 +        return this.toBigInteger(sign).toString();
 168.136 +    }
 168.137 +
 168.138 +}
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/rt/emul/compact/src/main/java/java/math/package-info.java	Wed Apr 30 15:04:10 2014 +0200
   169.3 @@ -0,0 +1,45 @@
   169.4 +/*
   169.5 + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
   169.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   169.7 + *
   169.8 + * This code is free software; you can redistribute it and/or modify it
   169.9 + * under the terms of the GNU General Public License version 2 only, as
  169.10 + * published by the Free Software Foundation.  Oracle designates this
  169.11 + * particular file as subject to the "Classpath" exception as provided
  169.12 + * by Oracle in the LICENSE file that accompanied this code.
  169.13 + *
  169.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  169.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  169.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  169.17 + * version 2 for more details (a copy is included in the LICENSE file that
  169.18 + * accompanied this code).
  169.19 + *
  169.20 + * You should have received a copy of the GNU General Public License version
  169.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  169.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  169.23 + *
  169.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  169.25 + * or visit www.oracle.com if you need additional information or have any
  169.26 + * questions.
  169.27 + */
  169.28 +
  169.29 +/**
  169.30 + * Provides classes for performing arbitrary-precision integer
  169.31 + * arithmetic ({@code BigInteger}) and arbitrary-precision decimal
  169.32 + * arithmetic ({@code BigDecimal}).  {@code BigInteger} is analogous
  169.33 + * to the primitive integer types except that it provides arbitrary
  169.34 + * precision, hence operations on {@code BigInteger}s do not overflow
  169.35 + * or lose precision.  In addition to standard arithmetic operations,
  169.36 + * {@code BigInteger} provides modular arithmetic, GCD calculation,
  169.37 + * primality testing, prime generation, bit manipulation, and a few
  169.38 + * other miscellaneous operations.
  169.39 + *
  169.40 + * {@code BigDecimal} provides arbitrary-precision signed decimal
  169.41 + * numbers suitable for currency calculations and the like.  {@code
  169.42 + * BigDecimal} gives the user complete control over rounding behavior,
  169.43 + * allowing the user to choose from a comprehensive set of eight
  169.44 + * rounding modes.
  169.45 + *
  169.46 + * @since JDK1.1
  169.47 + */
  169.48 +package java.math;
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/rt/emul/compact/src/main/java/java/net/URI.java	Wed Apr 30 15:04:10 2014 +0200
   170.3 @@ -0,0 +1,3520 @@
   170.4 +/*
   170.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   170.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   170.7 + *
   170.8 + * This code is free software; you can redistribute it and/or modify it
   170.9 + * under the terms of the GNU General Public License version 2 only, as
  170.10 + * published by the Free Software Foundation.  Oracle designates this
  170.11 + * particular file as subject to the "Classpath" exception as provided
  170.12 + * by Oracle in the LICENSE file that accompanied this code.
  170.13 + *
  170.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  170.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  170.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  170.17 + * version 2 for more details (a copy is included in the LICENSE file that
  170.18 + * accompanied this code).
  170.19 + *
  170.20 + * You should have received a copy of the GNU General Public License version
  170.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  170.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  170.23 + *
  170.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  170.25 + * or visit www.oracle.com if you need additional information or have any
  170.26 + * questions.
  170.27 + */
  170.28 +
  170.29 +package java.net;
  170.30 +
  170.31 +import java.io.IOException;
  170.32 +import java.io.InvalidObjectException;
  170.33 +import java.io.ObjectInputStream;
  170.34 +import java.io.ObjectOutputStream;
  170.35 +import java.io.Serializable;
  170.36 +
  170.37 +import java.lang.Character;             // for javadoc
  170.38 +import java.lang.NullPointerException;  // for javadoc
  170.39 +
  170.40 +
  170.41 +/**
  170.42 + * Represents a Uniform Resource Identifier (URI) reference.
  170.43 + *
  170.44 + * <p> Aside from some minor deviations noted below, an instance of this
  170.45 + * class represents a URI reference as defined by
  170.46 + * <a href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
  170.47 + * Resource Identifiers (URI): Generic Syntax</i></a>, amended by <a
  170.48 + * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
  170.49 + * Literal IPv6 Addresses in URLs</i></a>. The Literal IPv6 address format
  170.50 + * also supports scope_ids. The syntax and usage of scope_ids is described
  170.51 + * <a href="Inet6Address.html#scoped">here</a>.
  170.52 + * This class provides constructors for creating URI instances from
  170.53 + * their components or by parsing their string forms, methods for accessing the
  170.54 + * various components of an instance, and methods for normalizing, resolving,
  170.55 + * and relativizing URI instances.  Instances of this class are immutable.
  170.56 + *
  170.57 + *
  170.58 + * <h4> URI syntax and components </h4>
  170.59 + *
  170.60 + * At the highest level a URI reference (hereinafter simply "URI") in string
  170.61 + * form has the syntax
  170.62 + *
  170.63 + * <blockquote>
  170.64 + * [<i>scheme</i><tt><b>:</b></tt><i></i>]<i>scheme-specific-part</i>[<tt><b>#</b></tt><i>fragment</i>]
  170.65 + * </blockquote>
  170.66 + *
  170.67 + * where square brackets [...] delineate optional components and the characters
  170.68 + * <tt><b>:</b></tt> and <tt><b>#</b></tt> stand for themselves.
  170.69 + *
  170.70 + * <p> An <i>absolute</i> URI specifies a scheme; a URI that is not absolute is
  170.71 + * said to be <i>relative</i>.  URIs are also classified according to whether
  170.72 + * they are <i>opaque</i> or <i>hierarchical</i>.
  170.73 + *
  170.74 + * <p> An <i>opaque</i> URI is an absolute URI whose scheme-specific part does
  170.75 + * not begin with a slash character (<tt>'/'</tt>).  Opaque URIs are not
  170.76 + * subject to further parsing.  Some examples of opaque URIs are:
  170.77 + *
  170.78 + * <blockquote><table cellpadding=0 cellspacing=0 summary="layout">
  170.79 + * <tr><td><tt>mailto:java-net@java.sun.com</tt><td></tr>
  170.80 + * <tr><td><tt>news:comp.lang.java</tt><td></tr>
  170.81 + * <tr><td><tt>urn:isbn:096139210x</tt></td></tr>
  170.82 + * </table></blockquote>
  170.83 + *
  170.84 + * <p> A <i>hierarchical</i> URI is either an absolute URI whose
  170.85 + * scheme-specific part begins with a slash character, or a relative URI, that
  170.86 + * is, a URI that does not specify a scheme.  Some examples of hierarchical
  170.87 + * URIs are:
  170.88 + *
  170.89 + * <blockquote>
  170.90 + * <tt>http://java.sun.com/j2se/1.3/</tt><br>
  170.91 + * <tt>docs/guide/collections/designfaq.html#28</tt><br>
  170.92 + * <tt>../../../demo/jfc/SwingSet2/src/SwingSet2.java</tt><br>
  170.93 + * <tt>file:///~/calendar</tt>
  170.94 + * </blockquote>
  170.95 + *
  170.96 + * <p> A hierarchical URI is subject to further parsing according to the syntax
  170.97 + *
  170.98 + * <blockquote>
  170.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>]
 170.100 + * </blockquote>
 170.101 + *
 170.102 + * where the characters <tt><b>:</b></tt>, <tt><b>/</b></tt>,
 170.103 + * <tt><b>?</b></tt>, and <tt><b>#</b></tt> stand for themselves.  The
 170.104 + * scheme-specific part of a hierarchical URI consists of the characters
 170.105 + * between the scheme and fragment components.
 170.106 + *
 170.107 + * <p> The authority component of a hierarchical URI is, if specified, either
 170.108 + * <i>server-based</i> or <i>registry-based</i>.  A server-based authority
 170.109 + * parses according to the familiar syntax
 170.110 + *
 170.111 + * <blockquote>
 170.112 + * [<i>user-info</i><tt><b>@</b></tt>]<i>host</i>[<tt><b>:</b></tt><i>port</i>]
 170.113 + * </blockquote>
 170.114 + *
 170.115 + * where the characters <tt><b>@</b></tt> and <tt><b>:</b></tt> stand for
 170.116 + * themselves.  Nearly all URI schemes currently in use are server-based.  An
 170.117 + * authority component that does not parse in this way is considered to be
 170.118 + * registry-based.
 170.119 + *
 170.120 + * <p> The path component of a hierarchical URI is itself said to be absolute
 170.121 + * if it begins with a slash character (<tt>'/'</tt>); otherwise it is
 170.122 + * relative.  The path of a hierarchical URI that is either absolute or
 170.123 + * specifies an authority is always absolute.
 170.124 + *
 170.125 + * <p> All told, then, a URI instance has the following nine components:
 170.126 + *
 170.127 + * <blockquote><table summary="Describes the components of a URI:scheme,scheme-specific-part,authority,user-info,host,port,path,query,fragment">
 170.128 + * <tr><th><i>Component</i></th><th><i>Type</i></th></tr>
 170.129 + * <tr><td>scheme</td><td><tt>String</tt></td></tr>
 170.130 + * <tr><td>scheme-specific-part&nbsp;&nbsp;&nbsp;&nbsp;</td><td><tt>String</tt></td></tr>
 170.131 + * <tr><td>authority</td><td><tt>String</tt></td></tr>
 170.132 + * <tr><td>user-info</td><td><tt>String</tt></td></tr>
 170.133 + * <tr><td>host</td><td><tt>String</tt></td></tr>
 170.134 + * <tr><td>port</td><td><tt>int</tt></td></tr>
 170.135 + * <tr><td>path</td><td><tt>String</tt></td></tr>
 170.136 + * <tr><td>query</td><td><tt>String</tt></td></tr>
 170.137 + * <tr><td>fragment</td><td><tt>String</tt></td></tr>
 170.138 + * </table></blockquote>
 170.139 + *
 170.140 + * In a given instance any particular component is either <i>undefined</i> or
 170.141 + * <i>defined</i> with a distinct value.  Undefined string components are
 170.142 + * represented by <tt>null</tt>, while undefined integer components are
 170.143 + * represented by <tt>-1</tt>.  A string component may be defined to have the
 170.144 + * empty string as its value; this is not equivalent to that component being
 170.145 + * undefined.
 170.146 + *
 170.147 + * <p> Whether a particular component is or is not defined in an instance
 170.148 + * depends upon the type of the URI being represented.  An absolute URI has a
 170.149 + * scheme component.  An opaque URI has a scheme, a scheme-specific part, and
 170.150 + * possibly a fragment, but has no other components.  A hierarchical URI always
 170.151 + * has a path (though it may be empty) and a scheme-specific-part (which at
 170.152 + * least contains the path), and may have any of the other components.  If the
 170.153 + * authority component is present and is server-based then the host component
 170.154 + * will be defined and the user-information and port components may be defined.
 170.155 + *
 170.156 + *
 170.157 + * <h4> Operations on URI instances </h4>
 170.158 + *
 170.159 + * The key operations supported by this class are those of
 170.160 + * <i>normalization</i>, <i>resolution</i>, and <i>relativization</i>.
 170.161 + *
 170.162 + * <p> <i>Normalization</i> is the process of removing unnecessary <tt>"."</tt>
 170.163 + * and <tt>".."</tt> segments from the path component of a hierarchical URI.
 170.164 + * Each <tt>"."</tt> segment is simply removed.  A <tt>".."</tt> segment is
 170.165 + * removed only if it is preceded by a non-<tt>".."</tt> segment.
 170.166 + * Normalization has no effect upon opaque URIs.
 170.167 + *
 170.168 + * <p> <i>Resolution</i> is the process of resolving one URI against another,
 170.169 + * <i>base</i> URI.  The resulting URI is constructed from components of both
 170.170 + * URIs in the manner specified by RFC&nbsp;2396, taking components from the
 170.171 + * base URI for those not specified in the original.  For hierarchical URIs,
 170.172 + * the path of the original is resolved against the path of the base and then
 170.173 + * normalized.  The result, for example, of resolving
 170.174 + *
 170.175 + * <blockquote>
 170.176 + * <tt>docs/guide/collections/designfaq.html#28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt>(1)
 170.177 + * </blockquote>
 170.178 + *
 170.179 + * against the base URI <tt>http://java.sun.com/j2se/1.3/</tt> is the result
 170.180 + * URI
 170.181 + *
 170.182 + * <blockquote>
 170.183 + * <tt>http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28</tt>
 170.184 + * </blockquote>
 170.185 + *
 170.186 + * Resolving the relative URI
 170.187 + *
 170.188 + * <blockquote>
 170.189 + * <tt>../../../demo/jfc/SwingSet2/src/SwingSet2.java&nbsp;&nbsp;&nbsp;&nbsp;</tt>(2)
 170.190 + * </blockquote>
 170.191 + *
 170.192 + * against this result yields, in turn,
 170.193 + *
 170.194 + * <blockquote>
 170.195 + * <tt>http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java</tt>
 170.196 + * </blockquote>
 170.197 + *
 170.198 + * Resolution of both absolute and relative URIs, and of both absolute and
 170.199 + * relative paths in the case of hierarchical URIs, is supported.  Resolving
 170.200 + * the URI <tt>file:///~calendar</tt> against any other URI simply yields the
 170.201 + * original URI, since it is absolute.  Resolving the relative URI (2) above
 170.202 + * against the relative base URI (1) yields the normalized, but still relative,
 170.203 + * URI
 170.204 + *
 170.205 + * <blockquote>
 170.206 + * <tt>demo/jfc/SwingSet2/src/SwingSet2.java</tt>
 170.207 + * </blockquote>
 170.208 + *
 170.209 + * <p> <i>Relativization</i>, finally, is the inverse of resolution: For any
 170.210 + * two normalized URIs <i>u</i> and&nbsp;<i>v</i>,
 170.211 + *
 170.212 + * <blockquote>
 170.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>
 170.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>
 170.215 + * </blockquote>
 170.216 + *
 170.217 + * This operation is often useful when constructing a document containing URIs
 170.218 + * that must be made relative to the base URI of the document wherever
 170.219 + * possible.  For example, relativizing the URI
 170.220 + *
 170.221 + * <blockquote>
 170.222 + * <tt>http://java.sun.com/j2se/1.3/docs/guide/index.html</tt>
 170.223 + * </blockquote>
 170.224 + *
 170.225 + * against the base URI
 170.226 + *
 170.227 + * <blockquote>
 170.228 + * <tt>http://java.sun.com/j2se/1.3</tt>
 170.229 + * </blockquote>
 170.230 + *
 170.231 + * yields the relative URI <tt>docs/guide/index.html</tt>.
 170.232 + *
 170.233 + *
 170.234 + * <h4> Character categories </h4>
 170.235 + *
 170.236 + * RFC&nbsp;2396 specifies precisely which characters are permitted in the
 170.237 + * various components of a URI reference.  The following categories, most of
 170.238 + * which are taken from that specification, are used below to describe these
 170.239 + * constraints:
 170.240 + *
 170.241 + * <blockquote><table cellspacing=2 summary="Describes categories alpha,digit,alphanum,unreserved,punct,reserved,escaped,and other">
 170.242 + *   <tr><th valign=top><i>alpha</i></th>
 170.243 + *       <td>The US-ASCII alphabetic characters,
 170.244 + *        <tt>'A'</tt>&nbsp;through&nbsp;<tt>'Z'</tt>
 170.245 + *        and <tt>'a'</tt>&nbsp;through&nbsp;<tt>'z'</tt></td></tr>
 170.246 + *   <tr><th valign=top><i>digit</i></th>
 170.247 + *       <td>The US-ASCII decimal digit characters,
 170.248 + *       <tt>'0'</tt>&nbsp;through&nbsp;<tt>'9'</tt></td></tr>
 170.249 + *   <tr><th valign=top><i>alphanum</i></th>
 170.250 + *       <td>All <i>alpha</i> and <i>digit</i> characters</td></tr>
 170.251 + *   <tr><th valign=top><i>unreserved</i>&nbsp;&nbsp;&nbsp;&nbsp;</th>
 170.252 + *       <td>All <i>alphanum</i> characters together with those in the string
 170.253 + *        <tt>"_-!.~'()*"</tt></td></tr>
 170.254 + *   <tr><th valign=top><i>punct</i></th>
 170.255 + *       <td>The characters in the string <tt>",;:$&+="</tt></td></tr>
 170.256 + *   <tr><th valign=top><i>reserved</i></th>
 170.257 + *       <td>All <i>punct</i> characters together with those in the string
 170.258 + *        <tt>"?/[]@"</tt></td></tr>
 170.259 + *   <tr><th valign=top><i>escaped</i></th>
 170.260 + *       <td>Escaped octets, that is, triplets consisting of the percent
 170.261 + *           character (<tt>'%'</tt>) followed by two hexadecimal digits
 170.262 + *           (<tt>'0'</tt>-<tt>'9'</tt>, <tt>'A'</tt>-<tt>'F'</tt>, and
 170.263 + *           <tt>'a'</tt>-<tt>'f'</tt>)</td></tr>
 170.264 + *   <tr><th valign=top><i>other</i></th>
 170.265 + *       <td>The Unicode characters that are not in the US-ASCII character set,
 170.266 + *           are not control characters (according to the {@link
 170.267 + *           java.lang.Character#isISOControl(char) Character.isISOControl}
 170.268 + *           method), and are not space characters (according to the {@link
 170.269 + *           java.lang.Character#isSpaceChar(char) Character.isSpaceChar}
 170.270 + *           method)&nbsp;&nbsp;<i>(<b>Deviation from RFC 2396</b>, which is
 170.271 + *           limited to US-ASCII)</i></td></tr>
 170.272 + * </table></blockquote>
 170.273 + *
 170.274 + * <p><a name="legal-chars"></a> The set of all legal URI characters consists of
 170.275 + * the <i>unreserved</i>, <i>reserved</i>, <i>escaped</i>, and <i>other</i>
 170.276 + * characters.
 170.277 + *
 170.278 + *
 170.279 + * <h4> Escaped octets, quotation, encoding, and decoding </h4>
 170.280 + *
 170.281 + * RFC 2396 allows escaped octets to appear in the user-info, path, query, and
 170.282 + * fragment components.  Escaping serves two purposes in URIs:
 170.283 + *
 170.284 + * <ul>
 170.285 + *
 170.286 + *   <li><p> To <i>encode</i> non-US-ASCII characters when a URI is required to
 170.287 + *   conform strictly to RFC&nbsp;2396 by not containing any <i>other</i>
 170.288 + *   characters.  </p></li>
 170.289 + *
 170.290 + *   <li><p> To <i>quote</i> characters that are otherwise illegal in a
 170.291 + *   component.  The user-info, path, query, and fragment components differ
 170.292 + *   slightly in terms of which characters are considered legal and illegal.
 170.293 + *   </p></li>
 170.294 + *
 170.295 + * </ul>
 170.296 + *
 170.297 + * These purposes are served in this class by three related operations:
 170.298 + *
 170.299 + * <ul>
 170.300 + *
 170.301 + *   <li><p><a name="encode"></a> A character is <i>encoded</i> by replacing it
 170.302 + *   with the sequence of escaped octets that represent that character in the
 170.303 + *   UTF-8 character set.  The Euro currency symbol (<tt>'&#92;u20AC'</tt>),
 170.304 + *   for example, is encoded as <tt>"%E2%82%AC"</tt>.  <i>(<b>Deviation from
 170.305 + *   RFC&nbsp;2396</b>, which does not specify any particular character
 170.306 + *   set.)</i> </p></li>
 170.307 + *
 170.308 + *   <li><p><a name="quote"></a> An illegal character is <i>quoted</i> simply by
 170.309 + *   encoding it.  The space character, for example, is quoted by replacing it
 170.310 + *   with <tt>"%20"</tt>.  UTF-8 contains US-ASCII, hence for US-ASCII
 170.311 + *   characters this transformation has exactly the effect required by
 170.312 + *   RFC&nbsp;2396. </p></li>
 170.313 + *
 170.314 + *   <li><p><a name="decode"></a>
 170.315 + *   A sequence of escaped octets is <i>decoded</i> by
 170.316 + *   replacing it with the sequence of characters that it represents in the
 170.317 + *   UTF-8 character set.  UTF-8 contains US-ASCII, hence decoding has the
 170.318 + *   effect of de-quoting any quoted US-ASCII characters as well as that of
 170.319 + *   decoding any encoded non-US-ASCII characters.  If a <a
 170.320 + *   href="../nio/charset/CharsetDecoder.html#ce">decoding error</a> occurs
 170.321 + *   when decoding the escaped octets then the erroneous octets are replaced by
 170.322 + *   <tt>'&#92;uFFFD'</tt>, the Unicode replacement character.  </p></li>
 170.323 + *
 170.324 + * </ul>
 170.325 + *
 170.326 + * These operations are exposed in the constructors and methods of this class
 170.327 + * as follows:
 170.328 + *
 170.329 + * <ul>
 170.330 + *
 170.331 + *   <li><p> The {@link #URI(java.lang.String) <code>single-argument
 170.332 + *   constructor</code>} requires any illegal characters in its argument to be
 170.333 + *   quoted and preserves any escaped octets and <i>other</i> characters that
 170.334 + *   are present.  </p></li>
 170.335 + *
 170.336 + *   <li><p> The {@link
 170.337 + *   #URI(java.lang.String,java.lang.String,java.lang.String,int,java.lang.String,java.lang.String,java.lang.String)
 170.338 + *   <code>multi-argument constructors</code>} quote illegal characters as
 170.339 + *   required by the components in which they appear.  The percent character
 170.340 + *   (<tt>'%'</tt>) is always quoted by these constructors.  Any <i>other</i>
 170.341 + *   characters are preserved.  </p></li>
 170.342 + *
 170.343 + *   <li><p> The {@link #getRawUserInfo() getRawUserInfo}, {@link #getRawPath()
 170.344 + *   getRawPath}, {@link #getRawQuery() getRawQuery}, {@link #getRawFragment()
 170.345 + *   getRawFragment}, {@link #getRawAuthority() getRawAuthority}, and {@link
 170.346 + *   #getRawSchemeSpecificPart() getRawSchemeSpecificPart} methods return the
 170.347 + *   values of their corresponding components in raw form, without interpreting
 170.348 + *   any escaped octets.  The strings returned by these methods may contain
 170.349 + *   both escaped octets and <i>other</i> characters, and will not contain any
 170.350 + *   illegal characters.  </p></li>
 170.351 + *
 170.352 + *   <li><p> The {@link #getUserInfo() getUserInfo}, {@link #getPath()
 170.353 + *   getPath}, {@link #getQuery() getQuery}, {@link #getFragment()
 170.354 + *   getFragment}, {@link #getAuthority() getAuthority}, and {@link
 170.355 + *   #getSchemeSpecificPart() getSchemeSpecificPart} methods decode any escaped
 170.356 + *   octets in their corresponding components.  The strings returned by these
 170.357 + *   methods may contain both <i>other</i> characters and illegal characters,
 170.358 + *   and will not contain any escaped octets.  </p></li>
 170.359 + *
 170.360 + *   <li><p> The {@link #toString() toString} method returns a URI string with
 170.361 + *   all necessary quotation but which may contain <i>other</i> characters.
 170.362 + *   </p></li>
 170.363 + *
 170.364 + *   <li><p> The {@link #toASCIIString() toASCIIString} method returns a fully
 170.365 + *   quoted and encoded URI string that does not contain any <i>other</i>
 170.366 + *   characters.  </p></li>
 170.367 + *
 170.368 + * </ul>
 170.369 + *
 170.370 + *
 170.371 + * <h4> Identities </h4>
 170.372 + *
 170.373 + * For any URI <i>u</i>, it is always the case that
 170.374 + *
 170.375 + * <blockquote>
 170.376 + * <tt>new URI(</tt><i>u</i><tt>.toString()).equals(</tt><i>u</i><tt>)</tt>&nbsp;.
 170.377 + * </blockquote>
 170.378 + *
 170.379 + * For any URI <i>u</i> that does not contain redundant syntax such as two
 170.380 + * slashes before an empty authority (as in <tt>file:///tmp/</tt>&nbsp;) or a
 170.381 + * colon following a host name but no port (as in
 170.382 + * <tt>http://java.sun.com:</tt>&nbsp;), and that does not encode characters
 170.383 + * except those that must be quoted, the following identities also hold:
 170.384 + *
 170.385 + * <blockquote>
 170.386 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 170.387 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getSchemeSpecificPart(),<br>
 170.388 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 170.389 + * .equals(</tt><i>u</i><tt>)</tt>
 170.390 + * </blockquote>
 170.391 + *
 170.392 + * in all cases,
 170.393 + *
 170.394 + * <blockquote>
 170.395 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 170.396 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getUserInfo(),&nbsp;</tt><i>u</i><tt>.getAuthority(),<br>
 170.397 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getPath(),&nbsp;</tt><i>u</i><tt>.getQuery(),<br>
 170.398 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 170.399 + * .equals(</tt><i>u</i><tt>)</tt>
 170.400 + * </blockquote>
 170.401 + *
 170.402 + * if <i>u</i> is hierarchical, and
 170.403 + *
 170.404 + * <blockquote>
 170.405 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 170.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>
 170.407 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getPath(),&nbsp;</tt><i>u</i><tt>.getQuery(),<br>
 170.408 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 170.409 + * .equals(</tt><i>u</i><tt>)</tt>
 170.410 + * </blockquote>
 170.411 + *
 170.412 + * if <i>u</i> is hierarchical and has either no authority or a server-based
 170.413 + * authority.
 170.414 + *
 170.415 + *
 170.416 + * <h4> URIs, URLs, and URNs </h4>
 170.417 + *
 170.418 + * A URI is a uniform resource <i>identifier</i> while a URL is a uniform
 170.419 + * resource <i>locator</i>.  Hence every URL is a URI, abstractly speaking, but
 170.420 + * not every URI is a URL.  This is because there is another subcategory of
 170.421 + * URIs, uniform resource <i>names</i> (URNs), which name resources but do not
 170.422 + * specify how to locate them.  The <tt>mailto</tt>, <tt>news</tt>, and
 170.423 + * <tt>isbn</tt> URIs shown above are examples of URNs.
 170.424 + *
 170.425 + * <p> The conceptual distinction between URIs and URLs is reflected in the
 170.426 + * differences between this class and the {@link URL} class.
 170.427 + *
 170.428 + * <p> An instance of this class represents a URI reference in the syntactic
 170.429 + * sense defined by RFC&nbsp;2396.  A URI may be either absolute or relative.
 170.430 + * A URI string is parsed according to the generic syntax without regard to the
 170.431 + * scheme, if any, that it specifies.  No lookup of the host, if any, is
 170.432 + * performed, and no scheme-dependent stream handler is constructed.  Equality,
 170.433 + * hashing, and comparison are defined strictly in terms of the character
 170.434 + * content of the instance.  In other words, a URI instance is little more than
 170.435 + * a structured string that supports the syntactic, scheme-independent
 170.436 + * operations of comparison, normalization, resolution, and relativization.
 170.437 + *
 170.438 + * <p> An instance of the {@link URL} class, by contrast, represents the
 170.439 + * syntactic components of a URL together with some of the information required
 170.440 + * to access the resource that it describes.  A URL must be absolute, that is,
 170.441 + * it must always specify a scheme.  A URL string is parsed according to its
 170.442 + * scheme.  A stream handler is always established for a URL, and in fact it is
 170.443 + * impossible to create a URL instance for a scheme for which no handler is
 170.444 + * available.  Equality and hashing depend upon both the scheme and the
 170.445 + * Internet address of the host, if any; comparison is not defined.  In other
 170.446 + * words, a URL is a structured string that supports the syntactic operation of
 170.447 + * resolution as well as the network I/O operations of looking up the host and
 170.448 + * opening a connection to the specified resource.
 170.449 + *
 170.450 + *
 170.451 + * @author Mark Reinhold
 170.452 + * @since 1.4
 170.453 + *
 170.454 + * @see <a href="http://www.ietf.org/rfc/rfc2279.txt"><i>RFC&nbsp;2279: UTF-8, a
 170.455 + * transformation format of ISO 10646</i></a>, <br><a
 170.456 + * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IPv6 Addressing
 170.457 + * Architecture</i></a>, <br><a
 170.458 + * href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
 170.459 + * Resource Identifiers (URI): Generic Syntax</i></a>, <br><a
 170.460 + * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
 170.461 + * Literal IPv6 Addresses in URLs</i></a>, <br><a
 170.462 + * href="URISyntaxException.html">URISyntaxException</a>
 170.463 + */
 170.464 +
 170.465 +public final class URI
 170.466 +    implements Comparable<URI>, Serializable
 170.467 +{
 170.468 +
 170.469 +    // Note: Comments containing the word "ASSERT" indicate places where a
 170.470 +    // throw of an InternalError should be replaced by an appropriate assertion
 170.471 +    // statement once asserts are enabled in the build.
 170.472 +
 170.473 +    static final long serialVersionUID = -6052424284110960213L;
 170.474 +
 170.475 +
 170.476 +    // -- Properties and components of this instance --
 170.477 +
 170.478 +    // Components of all URIs: [<scheme>:]<scheme-specific-part>[#<fragment>]
 170.479 +    private transient String scheme;            // null ==> relative URI
 170.480 +    private transient String fragment;
 170.481 +
 170.482 +    // Hierarchical URI components: [//<authority>]<path>[?<query>]
 170.483 +    private transient String authority;         // Registry or server
 170.484 +
 170.485 +    // Server-based authority: [<userInfo>@]<host>[:<port>]
 170.486 +    private transient String userInfo;
 170.487 +    private transient String host;              // null ==> registry-based
 170.488 +    private transient int port = -1;            // -1 ==> undefined
 170.489 +
 170.490 +    // Remaining components of hierarchical URIs
 170.491 +    private transient String path;              // null ==> opaque
 170.492 +    private transient String query;
 170.493 +
 170.494 +    // The remaining fields may be computed on demand
 170.495 +
 170.496 +    private volatile transient String schemeSpecificPart;
 170.497 +    private volatile transient int hash;        // Zero ==> undefined
 170.498 +
 170.499 +    private volatile transient String decodedUserInfo = null;
 170.500 +    private volatile transient String decodedAuthority = null;
 170.501 +    private volatile transient String decodedPath = null;
 170.502 +    private volatile transient String decodedQuery = null;
 170.503 +    private volatile transient String decodedFragment = null;
 170.504 +    private volatile transient String decodedSchemeSpecificPart = null;
 170.505 +
 170.506 +    /**
 170.507 +     * The string form of this URI.
 170.508 +     *
 170.509 +     * @serial
 170.510 +     */
 170.511 +    private volatile String string;             // The only serializable field
 170.512 +
 170.513 +
 170.514 +
 170.515 +    // -- Constructors and factories --
 170.516 +
 170.517 +    private URI() { }                           // Used internally
 170.518 +
 170.519 +    /**
 170.520 +     * Constructs a URI by parsing the given string.
 170.521 +     *
 170.522 +     * <p> This constructor parses the given string exactly as specified by the
 170.523 +     * grammar in <a
 170.524 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 170.525 +     * Appendix&nbsp;A, <b><i>except for the following deviations:</i></b> </p>
 170.526 +     *
 170.527 +     * <ul type=disc>
 170.528 +     *
 170.529 +     *   <li><p> An empty authority component is permitted as long as it is
 170.530 +     *   followed by a non-empty path, a query component, or a fragment
 170.531 +     *   component.  This allows the parsing of URIs such as
 170.532 +     *   <tt>"file:///foo/bar"</tt>, which seems to be the intent of
 170.533 +     *   RFC&nbsp;2396 although the grammar does not permit it.  If the
 170.534 +     *   authority component is empty then the user-information, host, and port
 170.535 +     *   components are undefined. </p></li>
 170.536 +     *
 170.537 +     *   <li><p> Empty relative paths are permitted; this seems to be the
 170.538 +     *   intent of RFC&nbsp;2396 although the grammar does not permit it.  The
 170.539 +     *   primary consequence of this deviation is that a standalone fragment
 170.540 +     *   such as <tt>"#foo"</tt> parses as a relative URI with an empty path
 170.541 +     *   and the given fragment, and can be usefully <a
 170.542 +     *   href="#resolve-frag">resolved</a> against a base URI.
 170.543 +     *
 170.544 +     *   <li><p> IPv4 addresses in host components are parsed rigorously, as
 170.545 +     *   specified by <a
 170.546 +     *   href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>: Each
 170.547 +     *   element of a dotted-quad address must contain no more than three
 170.548 +     *   decimal digits.  Each element is further constrained to have a value
 170.549 +     *   no greater than 255. </p></li>
 170.550 +     *
 170.551 +     *   <li> <p> Hostnames in host components that comprise only a single
 170.552 +     *   domain label are permitted to start with an <i>alphanum</i>
 170.553 +     *   character. This seems to be the intent of <a
 170.554 +     *   href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>
 170.555 +     *   section&nbsp;3.2.2 although the grammar does not permit it. The
 170.556 +     *   consequence of this deviation is that the authority component of a
 170.557 +     *   hierarchical URI such as <tt>s://123</tt>, will parse as a server-based
 170.558 +     *   authority. </p></li>
 170.559 +     *
 170.560 +     *   <li><p> IPv6 addresses are permitted for the host component.  An IPv6
 170.561 +     *   address must be enclosed in square brackets (<tt>'['</tt> and
 170.562 +     *   <tt>']'</tt>) as specified by <a
 170.563 +     *   href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>.  The
 170.564 +     *   IPv6 address itself must parse according to <a
 170.565 +     *   href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>.  IPv6
 170.566 +     *   addresses are further constrained to describe no more than sixteen
 170.567 +     *   bytes of address information, a constraint implicit in RFC&nbsp;2373
 170.568 +     *   but not expressible in the grammar. </p></li>
 170.569 +     *
 170.570 +     *   <li><p> Characters in the <i>other</i> category are permitted wherever
 170.571 +     *   RFC&nbsp;2396 permits <i>escaped</i> octets, that is, in the
 170.572 +     *   user-information, path, query, and fragment components, as well as in
 170.573 +     *   the authority component if the authority is registry-based.  This
 170.574 +     *   allows URIs to contain Unicode characters beyond those in the US-ASCII
 170.575 +     *   character set. </p></li>
 170.576 +     *
 170.577 +     * </ul>
 170.578 +     *
 170.579 +     * @param  str   The string to be parsed into a URI
 170.580 +     *
 170.581 +     * @throws  NullPointerException
 170.582 +     *          If <tt>str</tt> is <tt>null</tt>
 170.583 +     *
 170.584 +     * @throws  URISyntaxException
 170.585 +     *          If the given string violates RFC&nbsp;2396, as augmented
 170.586 +     *          by the above deviations
 170.587 +     */
 170.588 +    public URI(String str) throws URISyntaxException {
 170.589 +        new Parser(str).parse(false);
 170.590 +    }
 170.591 +
 170.592 +    /**
 170.593 +     * Constructs a hierarchical URI from the given components.
 170.594 +     *
 170.595 +     * <p> If a scheme is given then the path, if also given, must either be
 170.596 +     * empty or begin with a slash character (<tt>'/'</tt>).  Otherwise a
 170.597 +     * component of the new URI may be left undefined by passing <tt>null</tt>
 170.598 +     * for the corresponding parameter or, in the case of the <tt>port</tt>
 170.599 +     * parameter, by passing <tt>-1</tt>.
 170.600 +     *
 170.601 +     * <p> This constructor first builds a URI string from the given components
 170.602 +     * according to the rules specified in <a
 170.603 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 170.604 +     * section&nbsp;5.2, step&nbsp;7: </p>
 170.605 +     *
 170.606 +     * <ol>
 170.607 +     *
 170.608 +     *   <li><p> Initially, the result string is empty. </p></li>
 170.609 +     *
 170.610 +     *   <li><p> If a scheme is given then it is appended to the result,
 170.611 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 170.612 +     *
 170.613 +     *   <li><p> If user information, a host, or a port are given then the
 170.614 +     *   string <tt>"//"</tt> is appended.  </p></li>
 170.615 +     *
 170.616 +     *   <li><p> If user information is given then it is appended, followed by
 170.617 +     *   a commercial-at character (<tt>'@'</tt>).  Any character not in the
 170.618 +     *   <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 170.619 +     *   categories is <a href="#quote">quoted</a>.  </p></li>
 170.620 +     *
 170.621 +     *   <li><p> If a host is given then it is appended.  If the host is a
 170.622 +     *   literal IPv6 address but is not enclosed in square brackets
 170.623 +     *   (<tt>'['</tt> and <tt>']'</tt>) then the square brackets are added.
 170.624 +     *   </p></li>
 170.625 +     *
 170.626 +     *   <li><p> If a port number is given then a colon character
 170.627 +     *   (<tt>':'</tt>) is appended, followed by the port number in decimal.
 170.628 +     *   </p></li>
 170.629 +     *
 170.630 +     *   <li><p> If a path is given then it is appended.  Any character not in
 170.631 +     *   the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 170.632 +     *   categories, and not equal to the slash character (<tt>'/'</tt>) or the
 170.633 +     *   commercial-at character (<tt>'@'</tt>), is quoted.  </p></li>
 170.634 +     *
 170.635 +     *   <li><p> If a query is given then a question-mark character
 170.636 +     *   (<tt>'?'</tt>) is appended, followed by the query.  Any character that
 170.637 +     *   is not a <a href="#legal-chars">legal URI character</a> is quoted.
 170.638 +     *   </p></li>
 170.639 +     *
 170.640 +     *   <li><p> Finally, if a fragment is given then a hash character
 170.641 +     *   (<tt>'#'</tt>) is appended, followed by the fragment.  Any character
 170.642 +     *   that is not a legal URI character is quoted.  </p></li>
 170.643 +     *
 170.644 +     * </ol>
 170.645 +     *
 170.646 +     * <p> The resulting URI string is then parsed as if by invoking the {@link
 170.647 +     * #URI(String)} constructor and then invoking the {@link
 170.648 +     * #parseServerAuthority()} method upon the result; this may cause a {@link
 170.649 +     * URISyntaxException} to be thrown.  </p>
 170.650 +     *
 170.651 +     * @param   scheme    Scheme name
 170.652 +     * @param   userInfo  User name and authorization information
 170.653 +     * @param   host      Host name
 170.654 +     * @param   port      Port number
 170.655 +     * @param   path      Path
 170.656 +     * @param   query     Query
 170.657 +     * @param   fragment  Fragment
 170.658 +     *
 170.659 +     * @throws URISyntaxException
 170.660 +     *         If both a scheme and a path are given but the path is relative,
 170.661 +     *         if the URI string constructed from the given components violates
 170.662 +     *         RFC&nbsp;2396, or if the authority component of the string is
 170.663 +     *         present but cannot be parsed as a server-based authority
 170.664 +     */
 170.665 +    public URI(String scheme,
 170.666 +               String userInfo, String host, int port,
 170.667 +               String path, String query, String fragment)
 170.668 +        throws URISyntaxException
 170.669 +    {
 170.670 +        String s = toString(scheme, null,
 170.671 +                            null, userInfo, host, port,
 170.672 +                            path, query, fragment);
 170.673 +        checkPath(s, scheme, path);
 170.674 +        new Parser(s).parse(true);
 170.675 +    }
 170.676 +
 170.677 +    /**
 170.678 +     * Constructs a hierarchical URI from the given components.
 170.679 +     *
 170.680 +     * <p> If a scheme is given then the path, if also given, must either be
 170.681 +     * empty or begin with a slash character (<tt>'/'</tt>).  Otherwise a
 170.682 +     * component of the new URI may be left undefined by passing <tt>null</tt>
 170.683 +     * for the corresponding parameter.
 170.684 +     *
 170.685 +     * <p> This constructor first builds a URI string from the given components
 170.686 +     * according to the rules specified in <a
 170.687 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 170.688 +     * section&nbsp;5.2, step&nbsp;7: </p>
 170.689 +     *
 170.690 +     * <ol>
 170.691 +     *
 170.692 +     *   <li><p> Initially, the result string is empty.  </p></li>
 170.693 +     *
 170.694 +     *   <li><p> If a scheme is given then it is appended to the result,
 170.695 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 170.696 +     *
 170.697 +     *   <li><p> If an authority is given then the string <tt>"//"</tt> is
 170.698 +     *   appended, followed by the authority.  If the authority contains a
 170.699 +     *   literal IPv6 address then the address must be enclosed in square
 170.700 +     *   brackets (<tt>'['</tt> and <tt>']'</tt>).  Any character not in the
 170.701 +     *   <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 170.702 +     *   categories, and not equal to the commercial-at character
 170.703 +     *   (<tt>'@'</tt>), is <a href="#quote">quoted</a>.  </p></li>
 170.704 +     *
 170.705 +     *   <li><p> If a path is given then it is appended.  Any character not in
 170.706 +     *   the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 170.707 +     *   categories, and not equal to the slash character (<tt>'/'</tt>) or the
 170.708 +     *   commercial-at character (<tt>'@'</tt>), is quoted.  </p></li>
 170.709 +     *
 170.710 +     *   <li><p> If a query is given then a question-mark character
 170.711 +     *   (<tt>'?'</tt>) is appended, followed by the query.  Any character that
 170.712 +     *   is not a <a href="#legal-chars">legal URI character</a> is quoted.
 170.713 +     *   </p></li>
 170.714 +     *
 170.715 +     *   <li><p> Finally, if a fragment is given then a hash character
 170.716 +     *   (<tt>'#'</tt>) is appended, followed by the fragment.  Any character
 170.717 +     *   that is not a legal URI character is quoted.  </p></li>
 170.718 +     *
 170.719 +     * </ol>
 170.720 +     *
 170.721 +     * <p> The resulting URI string is then parsed as if by invoking the {@link
 170.722 +     * #URI(String)} constructor and then invoking the {@link
 170.723 +     * #parseServerAuthority()} method upon the result; this may cause a {@link
 170.724 +     * URISyntaxException} to be thrown.  </p>
 170.725 +     *
 170.726 +     * @param   scheme     Scheme name
 170.727 +     * @param   authority  Authority
 170.728 +     * @param   path       Path
 170.729 +     * @param   query      Query
 170.730 +     * @param   fragment   Fragment
 170.731 +     *
 170.732 +     * @throws URISyntaxException
 170.733 +     *         If both a scheme and a path are given but the path is relative,
 170.734 +     *         if the URI string constructed from the given components violates
 170.735 +     *         RFC&nbsp;2396, or if the authority component of the string is
 170.736 +     *         present but cannot be parsed as a server-based authority
 170.737 +     */
 170.738 +    public URI(String scheme,
 170.739 +               String authority,
 170.740 +               String path, String query, String fragment)
 170.741 +        throws URISyntaxException
 170.742 +    {
 170.743 +        String s = toString(scheme, null,
 170.744 +                            authority, null, null, -1,
 170.745 +                            path, query, fragment);
 170.746 +        checkPath(s, scheme, path);
 170.747 +        new Parser(s).parse(false);
 170.748 +    }
 170.749 +
 170.750 +    /**
 170.751 +     * Constructs a hierarchical URI from the given components.
 170.752 +     *
 170.753 +     * <p> A component may be left undefined by passing <tt>null</tt>.
 170.754 +     *
 170.755 +     * <p> This convenience constructor works as if by invoking the
 170.756 +     * seven-argument constructor as follows:
 170.757 +     *
 170.758 +     * <blockquote><tt>
 170.759 +     * new&nbsp;{@link #URI(String, String, String, int, String, String, String)
 170.760 +     * URI}(scheme,&nbsp;null,&nbsp;host,&nbsp;-1,&nbsp;path,&nbsp;null,&nbsp;fragment);
 170.761 +     * </tt></blockquote>
 170.762 +     *
 170.763 +     * @param   scheme    Scheme name
 170.764 +     * @param   host      Host name
 170.765 +     * @param   path      Path
 170.766 +     * @param   fragment  Fragment
 170.767 +     *
 170.768 +     * @throws  URISyntaxException
 170.769 +     *          If the URI string constructed from the given components
 170.770 +     *          violates RFC&nbsp;2396
 170.771 +     */
 170.772 +    public URI(String scheme, String host, String path, String fragment)
 170.773 +        throws URISyntaxException
 170.774 +    {
 170.775 +        this(scheme, null, host, -1, path, null, fragment);
 170.776 +    }
 170.777 +
 170.778 +    /**
 170.779 +     * Constructs a URI from the given components.
 170.780 +     *
 170.781 +     * <p> A component may be left undefined by passing <tt>null</tt>.
 170.782 +     *
 170.783 +     * <p> This constructor first builds a URI in string form using the given
 170.784 +     * components as follows:  </p>
 170.785 +     *
 170.786 +     * <ol>
 170.787 +     *
 170.788 +     *   <li><p> Initially, the result string is empty.  </p></li>
 170.789 +     *
 170.790 +     *   <li><p> If a scheme is given then it is appended to the result,
 170.791 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 170.792 +     *
 170.793 +     *   <li><p> If a scheme-specific part is given then it is appended.  Any
 170.794 +     *   character that is not a <a href="#legal-chars">legal URI character</a>
 170.795 +     *   is <a href="#quote">quoted</a>.  </p></li>
 170.796 +     *
 170.797 +     *   <li><p> Finally, if a fragment is given then a hash character
 170.798 +     *   (<tt>'#'</tt>) is appended to the string, followed by the fragment.
 170.799 +     *   Any character that is not a legal URI character is quoted.  </p></li>
 170.800 +     *
 170.801 +     * </ol>
 170.802 +     *
 170.803 +     * <p> The resulting URI string is then parsed in order to create the new
 170.804 +     * URI instance as if by invoking the {@link #URI(String)} constructor;
 170.805 +     * this may cause a {@link URISyntaxException} to be thrown.  </p>
 170.806 +     *
 170.807 +     * @param   scheme    Scheme name
 170.808 +     * @param   ssp       Scheme-specific part
 170.809 +     * @param   fragment  Fragment
 170.810 +     *
 170.811 +     * @throws  URISyntaxException
 170.812 +     *          If the URI string constructed from the given components
 170.813 +     *          violates RFC&nbsp;2396
 170.814 +     */
 170.815 +    public URI(String scheme, String ssp, String fragment)
 170.816 +        throws URISyntaxException
 170.817 +    {
 170.818 +        new Parser(toString(scheme, ssp,
 170.819 +                            null, null, null, -1,
 170.820 +                            null, null, fragment))
 170.821 +            .parse(false);
 170.822 +    }
 170.823 +
 170.824 +    /**
 170.825 +     * Creates a URI by parsing the given string.
 170.826 +     *
 170.827 +     * <p> This convenience factory method works as if by invoking the {@link
 170.828 +     * #URI(String)} constructor; any {@link URISyntaxException} thrown by the
 170.829 +     * constructor is caught and wrapped in a new {@link
 170.830 +     * IllegalArgumentException} object, which is then thrown.
 170.831 +     *
 170.832 +     * <p> This method is provided for use in situations where it is known that
 170.833 +     * the given string is a legal URI, for example for URI constants declared
 170.834 +     * within in a program, and so it would be considered a programming error
 170.835 +     * for the string not to parse as such.  The constructors, which throw
 170.836 +     * {@link URISyntaxException} directly, should be used situations where a
 170.837 +     * URI is being constructed from user input or from some other source that
 170.838 +     * may be prone to errors.  </p>
 170.839 +     *
 170.840 +     * @param  str   The string to be parsed into a URI
 170.841 +     * @return The new URI
 170.842 +     *
 170.843 +     * @throws  NullPointerException
 170.844 +     *          If <tt>str</tt> is <tt>null</tt>
 170.845 +     *
 170.846 +     * @throws  IllegalArgumentException
 170.847 +     *          If the given string violates RFC&nbsp;2396
 170.848 +     */
 170.849 +    public static URI create(String str) {
 170.850 +        try {
 170.851 +            return new URI(str);
 170.852 +        } catch (URISyntaxException x) {
 170.853 +            throw new IllegalArgumentException(x.getMessage(), x);
 170.854 +        }
 170.855 +    }
 170.856 +
 170.857 +
 170.858 +    // -- Operations --
 170.859 +
 170.860 +    /**
 170.861 +     * Attempts to parse this URI's authority component, if defined, into
 170.862 +     * user-information, host, and port components.
 170.863 +     *
 170.864 +     * <p> If this URI's authority component has already been recognized as
 170.865 +     * being server-based then it will already have been parsed into
 170.866 +     * user-information, host, and port components.  In this case, or if this
 170.867 +     * URI has no authority component, this method simply returns this URI.
 170.868 +     *
 170.869 +     * <p> Otherwise this method attempts once more to parse the authority
 170.870 +     * component into user-information, host, and port components, and throws
 170.871 +     * an exception describing why the authority component could not be parsed
 170.872 +     * in that way.
 170.873 +     *
 170.874 +     * <p> This method is provided because the generic URI syntax specified in
 170.875 +     * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>
 170.876 +     * cannot always distinguish a malformed server-based authority from a
 170.877 +     * legitimate registry-based authority.  It must therefore treat some
 170.878 +     * instances of the former as instances of the latter.  The authority
 170.879 +     * component in the URI string <tt>"//foo:bar"</tt>, for example, is not a
 170.880 +     * legal server-based authority but it is legal as a registry-based
 170.881 +     * authority.
 170.882 +     *
 170.883 +     * <p> In many common situations, for example when working URIs that are
 170.884 +     * known to be either URNs or URLs, the hierarchical URIs being used will
 170.885 +     * always be server-based.  They therefore must either be parsed as such or
 170.886 +     * treated as an error.  In these cases a statement such as
 170.887 +     *
 170.888 +     * <blockquote>
 170.889 +     * <tt>URI </tt><i>u</i><tt> = new URI(str).parseServerAuthority();</tt>
 170.890 +     * </blockquote>
 170.891 +     *
 170.892 +     * <p> can be used to ensure that <i>u</i> always refers to a URI that, if
 170.893 +     * it has an authority component, has a server-based authority with proper
 170.894 +     * user-information, host, and port components.  Invoking this method also
 170.895 +     * ensures that if the authority could not be parsed in that way then an
 170.896 +     * appropriate diagnostic message can be issued based upon the exception
 170.897 +     * that is thrown. </p>
 170.898 +     *
 170.899 +     * @return  A URI whose authority field has been parsed
 170.900 +     *          as a server-based authority
 170.901 +     *
 170.902 +     * @throws  URISyntaxException
 170.903 +     *          If the authority component of this URI is defined
 170.904 +     *          but cannot be parsed as a server-based authority
 170.905 +     *          according to RFC&nbsp;2396
 170.906 +     */
 170.907 +    public URI parseServerAuthority()
 170.908 +        throws URISyntaxException
 170.909 +    {
 170.910 +        // We could be clever and cache the error message and index from the
 170.911 +        // exception thrown during the original parse, but that would require
 170.912 +        // either more fields or a more-obscure representation.
 170.913 +        if ((host != null) || (authority == null))
 170.914 +            return this;
 170.915 +        defineString();
 170.916 +        new Parser(string).parse(true);
 170.917 +        return this;
 170.918 +    }
 170.919 +
 170.920 +    /**
 170.921 +     * Normalizes this URI's path.
 170.922 +     *
 170.923 +     * <p> If this URI is opaque, or if its path is already in normal form,
 170.924 +     * then this URI is returned.  Otherwise a new URI is constructed that is
 170.925 +     * identical to this URI except that its path is computed by normalizing
 170.926 +     * this URI's path in a manner consistent with <a
 170.927 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 170.928 +     * section&nbsp;5.2, step&nbsp;6, sub-steps&nbsp;c through&nbsp;f; that is:
 170.929 +     * </p>
 170.930 +     *
 170.931 +     * <ol>
 170.932 +     *
 170.933 +     *   <li><p> All <tt>"."</tt> segments are removed. </p></li>
 170.934 +     *
 170.935 +     *   <li><p> If a <tt>".."</tt> segment is preceded by a non-<tt>".."</tt>
 170.936 +     *   segment then both of these segments are removed.  This step is
 170.937 +     *   repeated until it is no longer applicable. </p></li>
 170.938 +     *
 170.939 +     *   <li><p> If the path is relative, and if its first segment contains a
 170.940 +     *   colon character (<tt>':'</tt>), then a <tt>"."</tt> segment is
 170.941 +     *   prepended.  This prevents a relative URI with a path such as
 170.942 +     *   <tt>"a:b/c/d"</tt> from later being re-parsed as an opaque URI with a
 170.943 +     *   scheme of <tt>"a"</tt> and a scheme-specific part of <tt>"b/c/d"</tt>.
 170.944 +     *   <b><i>(Deviation from RFC&nbsp;2396)</i></b> </p></li>
 170.945 +     *
 170.946 +     * </ol>
 170.947 +     *
 170.948 +     * <p> A normalized path will begin with one or more <tt>".."</tt> segments
 170.949 +     * if there were insufficient non-<tt>".."</tt> segments preceding them to
 170.950 +     * allow their removal.  A normalized path will begin with a <tt>"."</tt>
 170.951 +     * segment if one was inserted by step 3 above.  Otherwise, a normalized
 170.952 +     * path will not contain any <tt>"."</tt> or <tt>".."</tt> segments. </p>
 170.953 +     *
 170.954 +     * @return  A URI equivalent to this URI,
 170.955 +     *          but whose path is in normal form
 170.956 +     */
 170.957 +    public URI normalize() {
 170.958 +        return normalize(this);
 170.959 +    }
 170.960 +
 170.961 +    /**
 170.962 +     * Resolves the given URI against this URI.
 170.963 +     *
 170.964 +     * <p> If the given URI is already absolute, or if this URI is opaque, then
 170.965 +     * the given URI is returned.
 170.966 +     *
 170.967 +     * <p><a name="resolve-frag"></a> If the given URI's fragment component is
 170.968 +     * defined, its path component is empty, and its scheme, authority, and
 170.969 +     * query components are undefined, then a URI with the given fragment but
 170.970 +     * with all other components equal to those of this URI is returned.  This
 170.971 +     * allows a URI representing a standalone fragment reference, such as
 170.972 +     * <tt>"#foo"</tt>, to be usefully resolved against a base URI.
 170.973 +     *
 170.974 +     * <p> Otherwise this method constructs a new hierarchical URI in a manner
 170.975 +     * consistent with <a
 170.976 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 170.977 +     * section&nbsp;5.2; that is: </p>
 170.978 +     *
 170.979 +     * <ol>
 170.980 +     *
 170.981 +     *   <li><p> A new URI is constructed with this URI's scheme and the given
 170.982 +     *   URI's query and fragment components. </p></li>
 170.983 +     *
 170.984 +     *   <li><p> If the given URI has an authority component then the new URI's
 170.985 +     *   authority and path are taken from the given URI. </p></li>
 170.986 +     *
 170.987 +     *   <li><p> Otherwise the new URI's authority component is copied from
 170.988 +     *   this URI, and its path is computed as follows: </p>
 170.989 +     *
 170.990 +     *   <ol type=a>
 170.991 +     *
 170.992 +     *     <li><p> If the given URI's path is absolute then the new URI's path
 170.993 +     *     is taken from the given URI. </p></li>
 170.994 +     *
 170.995 +     *     <li><p> Otherwise the given URI's path is relative, and so the new
 170.996 +     *     URI's path is computed by resolving the path of the given URI
 170.997 +     *     against the path of this URI.  This is done by concatenating all but
 170.998 +     *     the last segment of this URI's path, if any, with the given URI's
 170.999 +     *     path and then normalizing the result as if by invoking the {@link
170.1000 +     *     #normalize() normalize} method. </p></li>
170.1001 +     *
170.1002 +     *   </ol></li>
170.1003 +     *
170.1004 +     * </ol>
170.1005 +     *
170.1006 +     * <p> The result of this method is absolute if, and only if, either this
170.1007 +     * URI is absolute or the given URI is absolute.  </p>
170.1008 +     *
170.1009 +     * @param  uri  The URI to be resolved against this URI
170.1010 +     * @return The resulting URI
170.1011 +     *
170.1012 +     * @throws  NullPointerException
170.1013 +     *          If <tt>uri</tt> is <tt>null</tt>
170.1014 +     */
170.1015 +    public URI resolve(URI uri) {
170.1016 +        return resolve(this, uri);
170.1017 +    }
170.1018 +
170.1019 +    /**
170.1020 +     * Constructs a new URI by parsing the given string and then resolving it
170.1021 +     * against this URI.
170.1022 +     *
170.1023 +     * <p> This convenience method works as if invoking it were equivalent to
170.1024 +     * evaluating the expression <tt>{@link #resolve(java.net.URI)
170.1025 +     * resolve}(URI.{@link #create(String) create}(str))</tt>. </p>
170.1026 +     *
170.1027 +     * @param  str   The string to be parsed into a URI
170.1028 +     * @return The resulting URI
170.1029 +     *
170.1030 +     * @throws  NullPointerException
170.1031 +     *          If <tt>str</tt> is <tt>null</tt>
170.1032 +     *
170.1033 +     * @throws  IllegalArgumentException
170.1034 +     *          If the given string violates RFC&nbsp;2396
170.1035 +     */
170.1036 +    public URI resolve(String str) {
170.1037 +        return resolve(URI.create(str));
170.1038 +    }
170.1039 +
170.1040 +    /**
170.1041 +     * Relativizes the given URI against this URI.
170.1042 +     *
170.1043 +     * <p> The relativization of the given URI against this URI is computed as
170.1044 +     * follows: </p>
170.1045 +     *
170.1046 +     * <ol>
170.1047 +     *
170.1048 +     *   <li><p> If either this URI or the given URI are opaque, or if the
170.1049 +     *   scheme and authority components of the two URIs are not identical, or
170.1050 +     *   if the path of this URI is not a prefix of the path of the given URI,
170.1051 +     *   then the given URI is returned. </p></li>
170.1052 +     *
170.1053 +     *   <li><p> Otherwise a new relative hierarchical URI is constructed with
170.1054 +     *   query and fragment components taken from the given URI and with a path
170.1055 +     *   component computed by removing this URI's path from the beginning of
170.1056 +     *   the given URI's path. </p></li>
170.1057 +     *
170.1058 +     * </ol>
170.1059 +     *
170.1060 +     * @param  uri  The URI to be relativized against this URI
170.1061 +     * @return The resulting URI
170.1062 +     *
170.1063 +     * @throws  NullPointerException
170.1064 +     *          If <tt>uri</tt> is <tt>null</tt>
170.1065 +     */
170.1066 +    public URI relativize(URI uri) {
170.1067 +        return relativize(this, uri);
170.1068 +    }
170.1069 +
170.1070 +    /**
170.1071 +     * Constructs a URL from this URI.
170.1072 +     *
170.1073 +     * <p> This convenience method works as if invoking it were equivalent to
170.1074 +     * evaluating the expression <tt>new&nbsp;URL(this.toString())</tt> after
170.1075 +     * first checking that this URI is absolute. </p>
170.1076 +     *
170.1077 +     * @return  A URL constructed from this URI
170.1078 +     *
170.1079 +     * @throws  IllegalArgumentException
170.1080 +     *          If this URL is not absolute
170.1081 +     *
170.1082 +     * @throws  MalformedURLException
170.1083 +     *          If a protocol handler for the URL could not be found,
170.1084 +     *          or if some other error occurred while constructing the URL
170.1085 +     */
170.1086 +    public URL toURL()
170.1087 +        throws MalformedURLException {
170.1088 +        if (!isAbsolute())
170.1089 +            throw new IllegalArgumentException("URI is not absolute");
170.1090 +        return new URL(toString());
170.1091 +    }
170.1092 +
170.1093 +    // -- Component access methods --
170.1094 +
170.1095 +    /**
170.1096 +     * Returns the scheme component of this URI.
170.1097 +     *
170.1098 +     * <p> The scheme component of a URI, if defined, only contains characters
170.1099 +     * in the <i>alphanum</i> category and in the string <tt>"-.+"</tt>.  A
170.1100 +     * scheme always starts with an <i>alpha</i> character. <p>
170.1101 +     *
170.1102 +     * The scheme component of a URI cannot contain escaped octets, hence this
170.1103 +     * method does not perform any decoding.
170.1104 +     *
170.1105 +     * @return  The scheme component of this URI,
170.1106 +     *          or <tt>null</tt> if the scheme is undefined
170.1107 +     */
170.1108 +    public String getScheme() {
170.1109 +        return scheme;
170.1110 +    }
170.1111 +
170.1112 +    /**
170.1113 +     * Tells whether or not this URI is absolute.
170.1114 +     *
170.1115 +     * <p> A URI is absolute if, and only if, it has a scheme component. </p>
170.1116 +     *
170.1117 +     * @return  <tt>true</tt> if, and only if, this URI is absolute
170.1118 +     */
170.1119 +    public boolean isAbsolute() {
170.1120 +        return scheme != null;
170.1121 +    }
170.1122 +
170.1123 +    /**
170.1124 +     * Tells whether or not this URI is opaque.
170.1125 +     *
170.1126 +     * <p> A URI is opaque if, and only if, it is absolute and its
170.1127 +     * scheme-specific part does not begin with a slash character ('/').
170.1128 +     * An opaque URI has a scheme, a scheme-specific part, and possibly
170.1129 +     * a fragment; all other components are undefined. </p>
170.1130 +     *
170.1131 +     * @return  <tt>true</tt> if, and only if, this URI is opaque
170.1132 +     */
170.1133 +    public boolean isOpaque() {
170.1134 +        return path == null;
170.1135 +    }
170.1136 +
170.1137 +    /**
170.1138 +     * Returns the raw scheme-specific part of this URI.  The scheme-specific
170.1139 +     * part is never undefined, though it may be empty.
170.1140 +     *
170.1141 +     * <p> The scheme-specific part of a URI only contains legal URI
170.1142 +     * characters. </p>
170.1143 +     *
170.1144 +     * @return  The raw scheme-specific part of this URI
170.1145 +     *          (never <tt>null</tt>)
170.1146 +     */
170.1147 +    public String getRawSchemeSpecificPart() {
170.1148 +        defineSchemeSpecificPart();
170.1149 +        return schemeSpecificPart;
170.1150 +    }
170.1151 +
170.1152 +    /**
170.1153 +     * Returns the decoded scheme-specific part of this URI.
170.1154 +     *
170.1155 +     * <p> The string returned by this method is equal to that returned by the
170.1156 +     * {@link #getRawSchemeSpecificPart() getRawSchemeSpecificPart} method
170.1157 +     * except that all sequences of escaped octets are <a
170.1158 +     * href="#decode">decoded</a>.  </p>
170.1159 +     *
170.1160 +     * @return  The decoded scheme-specific part of this URI
170.1161 +     *          (never <tt>null</tt>)
170.1162 +     */
170.1163 +    public String getSchemeSpecificPart() {
170.1164 +        if (decodedSchemeSpecificPart == null)
170.1165 +            decodedSchemeSpecificPart = decode(getRawSchemeSpecificPart());
170.1166 +        return decodedSchemeSpecificPart;
170.1167 +    }
170.1168 +
170.1169 +    /**
170.1170 +     * Returns the raw authority component of this URI.
170.1171 +     *
170.1172 +     * <p> The authority component of a URI, if defined, only contains the
170.1173 +     * commercial-at character (<tt>'@'</tt>) and characters in the
170.1174 +     * <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, and <i>other</i>
170.1175 +     * categories.  If the authority is server-based then it is further
170.1176 +     * constrained to have valid user-information, host, and port
170.1177 +     * components. </p>
170.1178 +     *
170.1179 +     * @return  The raw authority component of this URI,
170.1180 +     *          or <tt>null</tt> if the authority is undefined
170.1181 +     */
170.1182 +    public String getRawAuthority() {
170.1183 +        return authority;
170.1184 +    }
170.1185 +
170.1186 +    /**
170.1187 +     * Returns the decoded authority component of this URI.
170.1188 +     *
170.1189 +     * <p> The string returned by this method is equal to that returned by the
170.1190 +     * {@link #getRawAuthority() getRawAuthority} method except that all
170.1191 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
170.1192 +     *
170.1193 +     * @return  The decoded authority component of this URI,
170.1194 +     *          or <tt>null</tt> if the authority is undefined
170.1195 +     */
170.1196 +    public String getAuthority() {
170.1197 +        if (decodedAuthority == null)
170.1198 +            decodedAuthority = decode(authority);
170.1199 +        return decodedAuthority;
170.1200 +    }
170.1201 +
170.1202 +    /**
170.1203 +     * Returns the raw user-information component of this URI.
170.1204 +     *
170.1205 +     * <p> The user-information component of a URI, if defined, only contains
170.1206 +     * characters in the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, and
170.1207 +     * <i>other</i> categories. </p>
170.1208 +     *
170.1209 +     * @return  The raw user-information component of this URI,
170.1210 +     *          or <tt>null</tt> if the user information is undefined
170.1211 +     */
170.1212 +    public String getRawUserInfo() {
170.1213 +        return userInfo;
170.1214 +    }
170.1215 +
170.1216 +    /**
170.1217 +     * Returns the decoded user-information component of this URI.
170.1218 +     *
170.1219 +     * <p> The string returned by this method is equal to that returned by the
170.1220 +     * {@link #getRawUserInfo() getRawUserInfo} method except that all
170.1221 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
170.1222 +     *
170.1223 +     * @return  The decoded user-information component of this URI,
170.1224 +     *          or <tt>null</tt> if the user information is undefined
170.1225 +     */
170.1226 +    public String getUserInfo() {
170.1227 +        if ((decodedUserInfo == null) && (userInfo != null))
170.1228 +            decodedUserInfo = decode(userInfo);
170.1229 +        return decodedUserInfo;
170.1230 +    }
170.1231 +
170.1232 +    /**
170.1233 +     * Returns the host component of this URI.
170.1234 +     *
170.1235 +     * <p> The host component of a URI, if defined, will have one of the
170.1236 +     * following forms: </p>
170.1237 +     *
170.1238 +     * <ul type=disc>
170.1239 +     *
170.1240 +     *   <li><p> A domain name consisting of one or more <i>labels</i>
170.1241 +     *   separated by period characters (<tt>'.'</tt>), optionally followed by
170.1242 +     *   a period character.  Each label consists of <i>alphanum</i> characters
170.1243 +     *   as well as hyphen characters (<tt>'-'</tt>), though hyphens never
170.1244 +     *   occur as the first or last characters in a label. The rightmost
170.1245 +     *   label of a domain name consisting of two or more labels, begins
170.1246 +     *   with an <i>alpha</i> character. </li>
170.1247 +     *
170.1248 +     *   <li><p> A dotted-quad IPv4 address of the form
170.1249 +     *   <i>digit</i><tt>+.</tt><i>digit</i><tt>+.</tt><i>digit</i><tt>+.</tt><i>digit</i><tt>+</tt>,
170.1250 +     *   where no <i>digit</i> sequence is longer than three characters and no
170.1251 +     *   sequence has a value larger than 255. </p></li>
170.1252 +     *
170.1253 +     *   <li><p> An IPv6 address enclosed in square brackets (<tt>'['</tt> and
170.1254 +     *   <tt>']'</tt>) and consisting of hexadecimal digits, colon characters
170.1255 +     *   (<tt>':'</tt>), and possibly an embedded IPv4 address.  The full
170.1256 +     *   syntax of IPv6 addresses is specified in <a
170.1257 +     *   href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IPv6
170.1258 +     *   Addressing Architecture</i></a>.  </p></li>
170.1259 +     *
170.1260 +     * </ul>
170.1261 +     *
170.1262 +     * The host component of a URI cannot contain escaped octets, hence this
170.1263 +     * method does not perform any decoding.
170.1264 +     *
170.1265 +     * @return  The host component of this URI,
170.1266 +     *          or <tt>null</tt> if the host is undefined
170.1267 +     */
170.1268 +    public String getHost() {
170.1269 +        return host;
170.1270 +    }
170.1271 +
170.1272 +    /**
170.1273 +     * Returns the port number of this URI.
170.1274 +     *
170.1275 +     * <p> The port component of a URI, if defined, is a non-negative
170.1276 +     * integer. </p>
170.1277 +     *
170.1278 +     * @return  The port component of this URI,
170.1279 +     *          or <tt>-1</tt> if the port is undefined
170.1280 +     */
170.1281 +    public int getPort() {
170.1282 +        return port;
170.1283 +    }
170.1284 +
170.1285 +    /**
170.1286 +     * Returns the raw path component of this URI.
170.1287 +     *
170.1288 +     * <p> The path component of a URI, if defined, only contains the slash
170.1289 +     * character (<tt>'/'</tt>), the commercial-at character (<tt>'@'</tt>),
170.1290 +     * and characters in the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>,
170.1291 +     * and <i>other</i> categories. </p>
170.1292 +     *
170.1293 +     * @return  The path component of this URI,
170.1294 +     *          or <tt>null</tt> if the path is undefined
170.1295 +     */
170.1296 +    public String getRawPath() {
170.1297 +        return path;
170.1298 +    }
170.1299 +
170.1300 +    /**
170.1301 +     * Returns the decoded path component of this URI.
170.1302 +     *
170.1303 +     * <p> The string returned by this method is equal to that returned by the
170.1304 +     * {@link #getRawPath() getRawPath} method except that all sequences of
170.1305 +     * escaped octets are <a href="#decode">decoded</a>.  </p>
170.1306 +     *
170.1307 +     * @return  The decoded path component of this URI,
170.1308 +     *          or <tt>null</tt> if the path is undefined
170.1309 +     */
170.1310 +    public String getPath() {
170.1311 +        if ((decodedPath == null) && (path != null))
170.1312 +            decodedPath = decode(path);
170.1313 +        return decodedPath;
170.1314 +    }
170.1315 +
170.1316 +    /**
170.1317 +     * Returns the raw query component of this URI.
170.1318 +     *
170.1319 +     * <p> The query component of a URI, if defined, only contains legal URI
170.1320 +     * characters. </p>
170.1321 +     *
170.1322 +     * @return  The raw query component of this URI,
170.1323 +     *          or <tt>null</tt> if the query is undefined
170.1324 +     */
170.1325 +    public String getRawQuery() {
170.1326 +        return query;
170.1327 +    }
170.1328 +
170.1329 +    /**
170.1330 +     * Returns the decoded query component of this URI.
170.1331 +     *
170.1332 +     * <p> The string returned by this method is equal to that returned by the
170.1333 +     * {@link #getRawQuery() getRawQuery} method except that all sequences of
170.1334 +     * escaped octets are <a href="#decode">decoded</a>.  </p>
170.1335 +     *
170.1336 +     * @return  The decoded query component of this URI,
170.1337 +     *          or <tt>null</tt> if the query is undefined
170.1338 +     */
170.1339 +    public String getQuery() {
170.1340 +        if ((decodedQuery == null) && (query != null))
170.1341 +            decodedQuery = decode(query);
170.1342 +        return decodedQuery;
170.1343 +    }
170.1344 +
170.1345 +    /**
170.1346 +     * Returns the raw fragment component of this URI.
170.1347 +     *
170.1348 +     * <p> The fragment component of a URI, if defined, only contains legal URI
170.1349 +     * characters. </p>
170.1350 +     *
170.1351 +     * @return  The raw fragment component of this URI,
170.1352 +     *          or <tt>null</tt> if the fragment is undefined
170.1353 +     */
170.1354 +    public String getRawFragment() {
170.1355 +        return fragment;
170.1356 +    }
170.1357 +
170.1358 +    /**
170.1359 +     * Returns the decoded fragment component of this URI.
170.1360 +     *
170.1361 +     * <p> The string returned by this method is equal to that returned by the
170.1362 +     * {@link #getRawFragment() getRawFragment} method except that all
170.1363 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
170.1364 +     *
170.1365 +     * @return  The decoded fragment component of this URI,
170.1366 +     *          or <tt>null</tt> if the fragment is undefined
170.1367 +     */
170.1368 +    public String getFragment() {
170.1369 +        if ((decodedFragment == null) && (fragment != null))
170.1370 +            decodedFragment = decode(fragment);
170.1371 +        return decodedFragment;
170.1372 +    }
170.1373 +
170.1374 +
170.1375 +    // -- Equality, comparison, hash code, toString, and serialization --
170.1376 +
170.1377 +    /**
170.1378 +     * Tests this URI for equality with another object.
170.1379 +     *
170.1380 +     * <p> If the given object is not a URI then this method immediately
170.1381 +     * returns <tt>false</tt>.
170.1382 +     *
170.1383 +     * <p> For two URIs to be considered equal requires that either both are
170.1384 +     * opaque or both are hierarchical.  Their schemes must either both be
170.1385 +     * undefined or else be equal without regard to case. Their fragments
170.1386 +     * must either both be undefined or else be equal.
170.1387 +     *
170.1388 +     * <p> For two opaque URIs to be considered equal, their scheme-specific
170.1389 +     * parts must be equal.
170.1390 +     *
170.1391 +     * <p> For two hierarchical URIs to be considered equal, their paths must
170.1392 +     * be equal and their queries must either both be undefined or else be
170.1393 +     * equal.  Their authorities must either both be undefined, or both be
170.1394 +     * registry-based, or both be server-based.  If their authorities are
170.1395 +     * defined and are registry-based, then they must be equal.  If their
170.1396 +     * authorities are defined and are server-based, then their hosts must be
170.1397 +     * equal without regard to case, their port numbers must be equal, and
170.1398 +     * their user-information components must be equal.
170.1399 +     *
170.1400 +     * <p> When testing the user-information, path, query, fragment, authority,
170.1401 +     * or scheme-specific parts of two URIs for equality, the raw forms rather
170.1402 +     * than the encoded forms of these components are compared and the
170.1403 +     * hexadecimal digits of escaped octets are compared without regard to
170.1404 +     * case.
170.1405 +     *
170.1406 +     * <p> This method satisfies the general contract of the {@link
170.1407 +     * java.lang.Object#equals(Object) Object.equals} method. </p>
170.1408 +     *
170.1409 +     * @param   ob   The object to which this object is to be compared
170.1410 +     *
170.1411 +     * @return  <tt>true</tt> if, and only if, the given object is a URI that
170.1412 +     *          is identical to this URI
170.1413 +     */
170.1414 +    public boolean equals(Object ob) {
170.1415 +        if (ob == this)
170.1416 +            return true;
170.1417 +        if (!(ob instanceof URI))
170.1418 +            return false;
170.1419 +        URI that = (URI)ob;
170.1420 +        if (this.isOpaque() != that.isOpaque()) return false;
170.1421 +        if (!equalIgnoringCase(this.scheme, that.scheme)) return false;
170.1422 +        if (!equal(this.fragment, that.fragment)) return false;
170.1423 +
170.1424 +        // Opaque
170.1425 +        if (this.isOpaque())
170.1426 +            return equal(this.schemeSpecificPart, that.schemeSpecificPart);
170.1427 +
170.1428 +        // Hierarchical
170.1429 +        if (!equal(this.path, that.path)) return false;
170.1430 +        if (!equal(this.query, that.query)) return false;
170.1431 +
170.1432 +        // Authorities
170.1433 +        if (this.authority == that.authority) return true;
170.1434 +        if (this.host != null) {
170.1435 +            // Server-based
170.1436 +            if (!equal(this.userInfo, that.userInfo)) return false;
170.1437 +            if (!equalIgnoringCase(this.host, that.host)) return false;
170.1438 +            if (this.port != that.port) return false;
170.1439 +        } else if (this.authority != null) {
170.1440 +            // Registry-based
170.1441 +            if (!equal(this.authority, that.authority)) return false;
170.1442 +        } else if (this.authority != that.authority) {
170.1443 +            return false;
170.1444 +        }
170.1445 +
170.1446 +        return true;
170.1447 +    }
170.1448 +
170.1449 +    /**
170.1450 +     * Returns a hash-code value for this URI.  The hash code is based upon all
170.1451 +     * of the URI's components, and satisfies the general contract of the
170.1452 +     * {@link java.lang.Object#hashCode() Object.hashCode} method.
170.1453 +     *
170.1454 +     * @return  A hash-code value for this URI
170.1455 +     */
170.1456 +    public int hashCode() {
170.1457 +        if (hash != 0)
170.1458 +            return hash;
170.1459 +        int h = hashIgnoringCase(0, scheme);
170.1460 +        h = hash(h, fragment);
170.1461 +        if (isOpaque()) {
170.1462 +            h = hash(h, schemeSpecificPart);
170.1463 +        } else {
170.1464 +            h = hash(h, path);
170.1465 +            h = hash(h, query);
170.1466 +            if (host != null) {
170.1467 +                h = hash(h, userInfo);
170.1468 +                h = hashIgnoringCase(h, host);
170.1469 +                h += 1949 * port;
170.1470 +            } else {
170.1471 +                h = hash(h, authority);
170.1472 +            }
170.1473 +        }
170.1474 +        hash = h;
170.1475 +        return h;
170.1476 +    }
170.1477 +
170.1478 +    /**
170.1479 +     * Compares this URI to another object, which must be a URI.
170.1480 +     *
170.1481 +     * <p> When comparing corresponding components of two URIs, if one
170.1482 +     * component is undefined but the other is defined then the first is
170.1483 +     * considered to be less than the second.  Unless otherwise noted, string
170.1484 +     * components are ordered according to their natural, case-sensitive
170.1485 +     * ordering as defined by the {@link java.lang.String#compareTo(Object)
170.1486 +     * String.compareTo} method.  String components that are subject to
170.1487 +     * encoding are compared by comparing their raw forms rather than their
170.1488 +     * encoded forms.
170.1489 +     *
170.1490 +     * <p> The ordering of URIs is defined as follows: </p>
170.1491 +     *
170.1492 +     * <ul type=disc>
170.1493 +     *
170.1494 +     *   <li><p> Two URIs with different schemes are ordered according the
170.1495 +     *   ordering of their schemes, without regard to case. </p></li>
170.1496 +     *
170.1497 +     *   <li><p> A hierarchical URI is considered to be less than an opaque URI
170.1498 +     *   with an identical scheme. </p></li>
170.1499 +     *
170.1500 +     *   <li><p> Two opaque URIs with identical schemes are ordered according
170.1501 +     *   to the ordering of their scheme-specific parts. </p></li>
170.1502 +     *
170.1503 +     *   <li><p> Two opaque URIs with identical schemes and scheme-specific
170.1504 +     *   parts are ordered according to the ordering of their
170.1505 +     *   fragments. </p></li>
170.1506 +     *
170.1507 +     *   <li><p> Two hierarchical URIs with identical schemes are ordered
170.1508 +     *   according to the ordering of their authority components: </p>
170.1509 +     *
170.1510 +     *   <ul type=disc>
170.1511 +     *
170.1512 +     *     <li><p> If both authority components are server-based then the URIs
170.1513 +     *     are ordered according to their user-information components; if these
170.1514 +     *     components are identical then the URIs are ordered according to the
170.1515 +     *     ordering of their hosts, without regard to case; if the hosts are
170.1516 +     *     identical then the URIs are ordered according to the ordering of
170.1517 +     *     their ports. </p></li>
170.1518 +     *
170.1519 +     *     <li><p> If one or both authority components are registry-based then
170.1520 +     *     the URIs are ordered according to the ordering of their authority
170.1521 +     *     components. </p></li>
170.1522 +     *
170.1523 +     *   </ul></li>
170.1524 +     *
170.1525 +     *   <li><p> Finally, two hierarchical URIs with identical schemes and
170.1526 +     *   authority components are ordered according to the ordering of their
170.1527 +     *   paths; if their paths are identical then they are ordered according to
170.1528 +     *   the ordering of their queries; if the queries are identical then they
170.1529 +     *   are ordered according to the order of their fragments. </p></li>
170.1530 +     *
170.1531 +     * </ul>
170.1532 +     *
170.1533 +     * <p> This method satisfies the general contract of the {@link
170.1534 +     * java.lang.Comparable#compareTo(Object) Comparable.compareTo}
170.1535 +     * method. </p>
170.1536 +     *
170.1537 +     * @param   that
170.1538 +     *          The object to which this URI is to be compared
170.1539 +     *
170.1540 +     * @return  A negative integer, zero, or a positive integer as this URI is
170.1541 +     *          less than, equal to, or greater than the given URI
170.1542 +     *
170.1543 +     * @throws  ClassCastException
170.1544 +     *          If the given object is not a URI
170.1545 +     */
170.1546 +    public int compareTo(URI that) {
170.1547 +        int c;
170.1548 +
170.1549 +        if ((c = compareIgnoringCase(this.scheme, that.scheme)) != 0)
170.1550 +            return c;
170.1551 +
170.1552 +        if (this.isOpaque()) {
170.1553 +            if (that.isOpaque()) {
170.1554 +                // Both opaque
170.1555 +                if ((c = compare(this.schemeSpecificPart,
170.1556 +                                 that.schemeSpecificPart)) != 0)
170.1557 +                    return c;
170.1558 +                return compare(this.fragment, that.fragment);
170.1559 +            }
170.1560 +            return +1;                  // Opaque > hierarchical
170.1561 +        } else if (that.isOpaque()) {
170.1562 +            return -1;                  // Hierarchical < opaque
170.1563 +        }
170.1564 +
170.1565 +        // Hierarchical
170.1566 +        if ((this.host != null) && (that.host != null)) {
170.1567 +            // Both server-based
170.1568 +            if ((c = compare(this.userInfo, that.userInfo)) != 0)
170.1569 +                return c;
170.1570 +            if ((c = compareIgnoringCase(this.host, that.host)) != 0)
170.1571 +                return c;
170.1572 +            if ((c = this.port - that.port) != 0)
170.1573 +                return c;
170.1574 +        } else {
170.1575 +            // If one or both authorities are registry-based then we simply
170.1576 +            // compare them in the usual, case-sensitive way.  If one is
170.1577 +            // registry-based and one is server-based then the strings are
170.1578 +            // guaranteed to be unequal, hence the comparison will never return
170.1579 +            // zero and the compareTo and equals methods will remain
170.1580 +            // consistent.
170.1581 +            if ((c = compare(this.authority, that.authority)) != 0) return c;
170.1582 +        }
170.1583 +
170.1584 +        if ((c = compare(this.path, that.path)) != 0) return c;
170.1585 +        if ((c = compare(this.query, that.query)) != 0) return c;
170.1586 +        return compare(this.fragment, that.fragment);
170.1587 +    }
170.1588 +
170.1589 +    /**
170.1590 +     * Returns the content of this URI as a string.
170.1591 +     *
170.1592 +     * <p> If this URI was created by invoking one of the constructors in this
170.1593 +     * class then a string equivalent to the original input string, or to the
170.1594 +     * string computed from the originally-given components, as appropriate, is
170.1595 +     * returned.  Otherwise this URI was created by normalization, resolution,
170.1596 +     * or relativization, and so a string is constructed from this URI's
170.1597 +     * components according to the rules specified in <a
170.1598 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
170.1599 +     * section&nbsp;5.2, step&nbsp;7. </p>
170.1600 +     *
170.1601 +     * @return  The string form of this URI
170.1602 +     */
170.1603 +    public String toString() {
170.1604 +        defineString();
170.1605 +        return string;
170.1606 +    }
170.1607 +
170.1608 +    /**
170.1609 +     * Returns the content of this URI as a US-ASCII string.
170.1610 +     *
170.1611 +     * <p> If this URI does not contain any characters in the <i>other</i>
170.1612 +     * category then an invocation of this method will return the same value as
170.1613 +     * an invocation of the {@link #toString() toString} method.  Otherwise
170.1614 +     * this method works as if by invoking that method and then <a
170.1615 +     * href="#encode">encoding</a> the result.  </p>
170.1616 +     *
170.1617 +     * @return  The string form of this URI, encoded as needed
170.1618 +     *          so that it only contains characters in the US-ASCII
170.1619 +     *          charset
170.1620 +     */
170.1621 +    public String toASCIIString() {
170.1622 +        defineString();
170.1623 +        return encode(string);
170.1624 +    }
170.1625 +
170.1626 +
170.1627 +    // -- Serialization support --
170.1628 +
170.1629 +    /**
170.1630 +     * Saves the content of this URI to the given serial stream.
170.1631 +     *
170.1632 +     * <p> The only serializable field of a URI instance is its <tt>string</tt>
170.1633 +     * field.  That field is given a value, if it does not have one already,
170.1634 +     * and then the {@link java.io.ObjectOutputStream#defaultWriteObject()}
170.1635 +     * method of the given object-output stream is invoked. </p>
170.1636 +     *
170.1637 +     * @param  os  The object-output stream to which this object
170.1638 +     *             is to be written
170.1639 +     */
170.1640 +    private void writeObject(ObjectOutputStream os)
170.1641 +        throws IOException
170.1642 +    {
170.1643 +        defineString();
170.1644 +        os.defaultWriteObject();        // Writes the string field only
170.1645 +    }
170.1646 +
170.1647 +    /**
170.1648 +     * Reconstitutes a URI from the given serial stream.
170.1649 +     *
170.1650 +     * <p> The {@link java.io.ObjectInputStream#defaultReadObject()} method is
170.1651 +     * invoked to read the value of the <tt>string</tt> field.  The result is
170.1652 +     * then parsed in the usual way.
170.1653 +     *
170.1654 +     * @param  is  The object-input stream from which this object
170.1655 +     *             is being read
170.1656 +     */
170.1657 +    private void readObject(ObjectInputStream is)
170.1658 +        throws ClassNotFoundException, IOException
170.1659 +    {
170.1660 +        port = -1;                      // Argh
170.1661 +        is.defaultReadObject();
170.1662 +        try {
170.1663 +            new Parser(string).parse(false);
170.1664 +        } catch (URISyntaxException x) {
170.1665 +            IOException y = new InvalidObjectException("Invalid URI");
170.1666 +            y.initCause(x);
170.1667 +            throw y;
170.1668 +        }
170.1669 +    }
170.1670 +
170.1671 +
170.1672 +    // -- End of public methods --
170.1673 +
170.1674 +
170.1675 +    // -- Utility methods for string-field comparison and hashing --
170.1676 +
170.1677 +    // These methods return appropriate values for null string arguments,
170.1678 +    // thereby simplifying the equals, hashCode, and compareTo methods.
170.1679 +    //
170.1680 +    // The case-ignoring methods should only be applied to strings whose
170.1681 +    // characters are all known to be US-ASCII.  Because of this restriction,
170.1682 +    // these methods are faster than the similar methods in the String class.
170.1683 +
170.1684 +    // US-ASCII only
170.1685 +    private static int toLower(char c) {
170.1686 +        if ((c >= 'A') && (c <= 'Z'))
170.1687 +            return c + ('a' - 'A');
170.1688 +        return c;
170.1689 +    }
170.1690 +
170.1691 +    private static boolean equal(String s, String t) {
170.1692 +        if (s == t) return true;
170.1693 +        if ((s != null) && (t != null)) {
170.1694 +            if (s.length() != t.length())
170.1695 +                return false;
170.1696 +            if (s.indexOf('%') < 0)
170.1697 +                return s.equals(t);
170.1698 +            int n = s.length();
170.1699 +            for (int i = 0; i < n;) {
170.1700 +                char c = s.charAt(i);
170.1701 +                char d = t.charAt(i);
170.1702 +                if (c != '%') {
170.1703 +                    if (c != d)
170.1704 +                        return false;
170.1705 +                    i++;
170.1706 +                    continue;
170.1707 +                }
170.1708 +                i++;
170.1709 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
170.1710 +                    return false;
170.1711 +                i++;
170.1712 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
170.1713 +                    return false;
170.1714 +                i++;
170.1715 +            }
170.1716 +            return true;
170.1717 +        }
170.1718 +        return false;
170.1719 +    }
170.1720 +
170.1721 +    // US-ASCII only
170.1722 +    private static boolean equalIgnoringCase(String s, String t) {
170.1723 +        if (s == t) return true;
170.1724 +        if ((s != null) && (t != null)) {
170.1725 +            int n = s.length();
170.1726 +            if (t.length() != n)
170.1727 +                return false;
170.1728 +            for (int i = 0; i < n; i++) {
170.1729 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
170.1730 +                    return false;
170.1731 +            }
170.1732 +            return true;
170.1733 +        }
170.1734 +        return false;
170.1735 +    }
170.1736 +
170.1737 +    private static int hash(int hash, String s) {
170.1738 +        if (s == null) return hash;
170.1739 +        return hash * 127 + s.hashCode();
170.1740 +    }
170.1741 +
170.1742 +    // US-ASCII only
170.1743 +    private static int hashIgnoringCase(int hash, String s) {
170.1744 +        if (s == null) return hash;
170.1745 +        int h = hash;
170.1746 +        int n = s.length();
170.1747 +        for (int i = 0; i < n; i++)
170.1748 +            h = 31 * h + toLower(s.charAt(i));
170.1749 +        return h;
170.1750 +    }
170.1751 +
170.1752 +    private static int compare(String s, String t) {
170.1753 +        if (s == t) return 0;
170.1754 +        if (s != null) {
170.1755 +            if (t != null)
170.1756 +                return s.compareTo(t);
170.1757 +            else
170.1758 +                return +1;
170.1759 +        } else {
170.1760 +            return -1;
170.1761 +        }
170.1762 +    }
170.1763 +
170.1764 +    // US-ASCII only
170.1765 +    private static int compareIgnoringCase(String s, String t) {
170.1766 +        if (s == t) return 0;
170.1767 +        if (s != null) {
170.1768 +            if (t != null) {
170.1769 +                int sn = s.length();
170.1770 +                int tn = t.length();
170.1771 +                int n = sn < tn ? sn : tn;
170.1772 +                for (int i = 0; i < n; i++) {
170.1773 +                    int c = toLower(s.charAt(i)) - toLower(t.charAt(i));
170.1774 +                    if (c != 0)
170.1775 +                        return c;
170.1776 +                }
170.1777 +                return sn - tn;
170.1778 +            }
170.1779 +            return +1;
170.1780 +        } else {
170.1781 +            return -1;
170.1782 +        }
170.1783 +    }
170.1784 +
170.1785 +
170.1786 +    // -- String construction --
170.1787 +
170.1788 +    // If a scheme is given then the path, if given, must be absolute
170.1789 +    //
170.1790 +    private static void checkPath(String s, String scheme, String path)
170.1791 +        throws URISyntaxException
170.1792 +    {
170.1793 +        if (scheme != null) {
170.1794 +            if ((path != null)
170.1795 +                && ((path.length() > 0) && (path.charAt(0) != '/')))
170.1796 +                throw new URISyntaxException(s,
170.1797 +                                             "Relative path in absolute URI");
170.1798 +        }
170.1799 +    }
170.1800 +
170.1801 +    private void appendAuthority(StringBuffer sb,
170.1802 +                                 String authority,
170.1803 +                                 String userInfo,
170.1804 +                                 String host,
170.1805 +                                 int port)
170.1806 +    {
170.1807 +        if (host != null) {
170.1808 +            sb.append("//");
170.1809 +            if (userInfo != null) {
170.1810 +                sb.append(quote(userInfo, L_USERINFO, H_USERINFO));
170.1811 +                sb.append('@');
170.1812 +            }
170.1813 +            boolean needBrackets = ((host.indexOf(':') >= 0)
170.1814 +                                    && !host.startsWith("[")
170.1815 +                                    && !host.endsWith("]"));
170.1816 +            if (needBrackets) sb.append('[');
170.1817 +            sb.append(host);
170.1818 +            if (needBrackets) sb.append(']');
170.1819 +            if (port != -1) {
170.1820 +                sb.append(':');
170.1821 +                sb.append(port);
170.1822 +            }
170.1823 +        } else if (authority != null) {
170.1824 +            sb.append("//");
170.1825 +            if (authority.startsWith("[")) {
170.1826 +                // authority should (but may not) contain an embedded IPv6 address
170.1827 +                int end = authority.indexOf("]");
170.1828 +                String doquote = authority, dontquote = "";
170.1829 +                if (end != -1 && authority.indexOf(":") != -1) {
170.1830 +                    // the authority contains an IPv6 address
170.1831 +                    if (end == authority.length()) {
170.1832 +                        dontquote = authority;
170.1833 +                        doquote = "";
170.1834 +                    } else {
170.1835 +                        dontquote = authority.substring(0 , end + 1);
170.1836 +                        doquote = authority.substring(end + 1);
170.1837 +                    }
170.1838 +                }
170.1839 +                sb.append(dontquote);
170.1840 +                sb.append(quote(doquote,
170.1841 +                            L_REG_NAME | L_SERVER,
170.1842 +                            H_REG_NAME | H_SERVER));
170.1843 +            } else {
170.1844 +                sb.append(quote(authority,
170.1845 +                            L_REG_NAME | L_SERVER,
170.1846 +                            H_REG_NAME | H_SERVER));
170.1847 +            }
170.1848 +        }
170.1849 +    }
170.1850 +
170.1851 +    private void appendSchemeSpecificPart(StringBuffer sb,
170.1852 +                                          String opaquePart,
170.1853 +                                          String authority,
170.1854 +                                          String userInfo,
170.1855 +                                          String host,
170.1856 +                                          int port,
170.1857 +                                          String path,
170.1858 +                                          String query)
170.1859 +    {
170.1860 +        if (opaquePart != null) {
170.1861 +            /* check if SSP begins with an IPv6 address
170.1862 +             * because we must not quote a literal IPv6 address
170.1863 +             */
170.1864 +            if (opaquePart.startsWith("//[")) {
170.1865 +                int end =  opaquePart.indexOf("]");
170.1866 +                if (end != -1 && opaquePart.indexOf(":")!=-1) {
170.1867 +                    String doquote, dontquote;
170.1868 +                    if (end == opaquePart.length()) {
170.1869 +                        dontquote = opaquePart;
170.1870 +                        doquote = "";
170.1871 +                    } else {
170.1872 +                        dontquote = opaquePart.substring(0,end+1);
170.1873 +                        doquote = opaquePart.substring(end+1);
170.1874 +                    }
170.1875 +                    sb.append (dontquote);
170.1876 +                    sb.append(quote(doquote, L_URIC, H_URIC));
170.1877 +                }
170.1878 +            } else {
170.1879 +                sb.append(quote(opaquePart, L_URIC, H_URIC));
170.1880 +            }
170.1881 +        } else {
170.1882 +            appendAuthority(sb, authority, userInfo, host, port);
170.1883 +            if (path != null)
170.1884 +                sb.append(quote(path, L_PATH, H_PATH));
170.1885 +            if (query != null) {
170.1886 +                sb.append('?');
170.1887 +                sb.append(quote(query, L_URIC, H_URIC));
170.1888 +            }
170.1889 +        }
170.1890 +    }
170.1891 +
170.1892 +    private void appendFragment(StringBuffer sb, String fragment) {
170.1893 +        if (fragment != null) {
170.1894 +            sb.append('#');
170.1895 +            sb.append(quote(fragment, L_URIC, H_URIC));
170.1896 +        }
170.1897 +    }
170.1898 +
170.1899 +    private String toString(String scheme,
170.1900 +                            String opaquePart,
170.1901 +                            String authority,
170.1902 +                            String userInfo,
170.1903 +                            String host,
170.1904 +                            int port,
170.1905 +                            String path,
170.1906 +                            String query,
170.1907 +                            String fragment)
170.1908 +    {
170.1909 +        StringBuffer sb = new StringBuffer();
170.1910 +        if (scheme != null) {
170.1911 +            sb.append(scheme);
170.1912 +            sb.append(':');
170.1913 +        }
170.1914 +        appendSchemeSpecificPart(sb, opaquePart,
170.1915 +                                 authority, userInfo, host, port,
170.1916 +                                 path, query);
170.1917 +        appendFragment(sb, fragment);
170.1918 +        return sb.toString();
170.1919 +    }
170.1920 +
170.1921 +    private void defineSchemeSpecificPart() {
170.1922 +        if (schemeSpecificPart != null) return;
170.1923 +        StringBuffer sb = new StringBuffer();
170.1924 +        appendSchemeSpecificPart(sb, null, getAuthority(), getUserInfo(),
170.1925 +                                 host, port, getPath(), getQuery());
170.1926 +        if (sb.length() == 0) return;
170.1927 +        schemeSpecificPart = sb.toString();
170.1928 +    }
170.1929 +
170.1930 +    private void defineString() {
170.1931 +        if (string != null) return;
170.1932 +
170.1933 +        StringBuffer sb = new StringBuffer();
170.1934 +        if (scheme != null) {
170.1935 +            sb.append(scheme);
170.1936 +            sb.append(':');
170.1937 +        }
170.1938 +        if (isOpaque()) {
170.1939 +            sb.append(schemeSpecificPart);
170.1940 +        } else {
170.1941 +            if (host != null) {
170.1942 +                sb.append("//");
170.1943 +                if (userInfo != null) {
170.1944 +                    sb.append(userInfo);
170.1945 +                    sb.append('@');
170.1946 +                }
170.1947 +                boolean needBrackets = ((host.indexOf(':') >= 0)
170.1948 +                                    && !host.startsWith("[")
170.1949 +                                    && !host.endsWith("]"));
170.1950 +                if (needBrackets) sb.append('[');
170.1951 +                sb.append(host);
170.1952 +                if (needBrackets) sb.append(']');
170.1953 +                if (port != -1) {
170.1954 +                    sb.append(':');
170.1955 +                    sb.append(port);
170.1956 +                }
170.1957 +            } else if (authority != null) {
170.1958 +                sb.append("//");
170.1959 +                sb.append(authority);
170.1960 +            }
170.1961 +            if (path != null)
170.1962 +                sb.append(path);
170.1963 +            if (query != null) {
170.1964 +                sb.append('?');
170.1965 +                sb.append(query);
170.1966 +            }
170.1967 +        }
170.1968 +        if (fragment != null) {
170.1969 +            sb.append('#');
170.1970 +            sb.append(fragment);
170.1971 +        }
170.1972 +        string = sb.toString();
170.1973 +    }
170.1974 +
170.1975 +
170.1976 +    // -- Normalization, resolution, and relativization --
170.1977 +
170.1978 +    // RFC2396 5.2 (6)
170.1979 +    private static String resolvePath(String base, String child,
170.1980 +                                      boolean absolute)
170.1981 +    {
170.1982 +        int i = base.lastIndexOf('/');
170.1983 +        int cn = child.length();
170.1984 +        String path = "";
170.1985 +
170.1986 +        if (cn == 0) {
170.1987 +            // 5.2 (6a)
170.1988 +            if (i >= 0)
170.1989 +                path = base.substring(0, i + 1);
170.1990 +        } else {
170.1991 +            StringBuffer sb = new StringBuffer(base.length() + cn);
170.1992 +            // 5.2 (6a)
170.1993 +            if (i >= 0)
170.1994 +                sb.append(base.substring(0, i + 1));
170.1995 +            // 5.2 (6b)
170.1996 +            sb.append(child);
170.1997 +            path = sb.toString();
170.1998 +        }
170.1999 +
170.2000 +        // 5.2 (6c-f)
170.2001 +        String np = normalize(path);
170.2002 +
170.2003 +        // 5.2 (6g): If the result is absolute but the path begins with "../",
170.2004 +        // then we simply leave the path as-is
170.2005 +
170.2006 +        return np;
170.2007 +    }
170.2008 +
170.2009 +    // RFC2396 5.2
170.2010 +    private static URI resolve(URI base, URI child) {
170.2011 +        // check if child if opaque first so that NPE is thrown
170.2012 +        // if child is null.
170.2013 +        if (child.isOpaque() || base.isOpaque())
170.2014 +            return child;
170.2015 +
170.2016 +        // 5.2 (2): Reference to current document (lone fragment)
170.2017 +        if ((child.scheme == null) && (child.authority == null)
170.2018 +            && child.path.equals("") && (child.fragment != null)
170.2019 +            && (child.query == null)) {
170.2020 +            if ((base.fragment != null)
170.2021 +                && child.fragment.equals(base.fragment)) {
170.2022 +                return base;
170.2023 +            }
170.2024 +            URI ru = new URI();
170.2025 +            ru.scheme = base.scheme;
170.2026 +            ru.authority = base.authority;
170.2027 +            ru.userInfo = base.userInfo;
170.2028 +            ru.host = base.host;
170.2029 +            ru.port = base.port;
170.2030 +            ru.path = base.path;
170.2031 +            ru.fragment = child.fragment;
170.2032 +            ru.query = base.query;
170.2033 +            return ru;
170.2034 +        }
170.2035 +
170.2036 +        // 5.2 (3): Child is absolute
170.2037 +        if (child.scheme != null)
170.2038 +            return child;
170.2039 +
170.2040 +        URI ru = new URI();             // Resolved URI
170.2041 +        ru.scheme = base.scheme;
170.2042 +        ru.query = child.query;
170.2043 +        ru.fragment = child.fragment;
170.2044 +
170.2045 +        // 5.2 (4): Authority
170.2046 +        if (child.authority == null) {
170.2047 +            ru.authority = base.authority;
170.2048 +            ru.host = base.host;
170.2049 +            ru.userInfo = base.userInfo;
170.2050 +            ru.port = base.port;
170.2051 +
170.2052 +            String cp = (child.path == null) ? "" : child.path;
170.2053 +            if ((cp.length() > 0) && (cp.charAt(0) == '/')) {
170.2054 +                // 5.2 (5): Child path is absolute
170.2055 +                ru.path = child.path;
170.2056 +            } else {
170.2057 +                // 5.2 (6): Resolve relative path
170.2058 +                ru.path = resolvePath(base.path, cp, base.isAbsolute());
170.2059 +            }
170.2060 +        } else {
170.2061 +            ru.authority = child.authority;
170.2062 +            ru.host = child.host;
170.2063 +            ru.userInfo = child.userInfo;
170.2064 +            ru.host = child.host;
170.2065 +            ru.port = child.port;
170.2066 +            ru.path = child.path;
170.2067 +        }
170.2068 +
170.2069 +        // 5.2 (7): Recombine (nothing to do here)
170.2070 +        return ru;
170.2071 +    }
170.2072 +
170.2073 +    // If the given URI's path is normal then return the URI;
170.2074 +    // o.w., return a new URI containing the normalized path.
170.2075 +    //
170.2076 +    private static URI normalize(URI u) {
170.2077 +        if (u.isOpaque() || (u.path == null) || (u.path.length() == 0))
170.2078 +            return u;
170.2079 +
170.2080 +        String np = normalize(u.path);
170.2081 +        if (np == u.path)
170.2082 +            return u;
170.2083 +
170.2084 +        URI v = new URI();
170.2085 +        v.scheme = u.scheme;
170.2086 +        v.fragment = u.fragment;
170.2087 +        v.authority = u.authority;
170.2088 +        v.userInfo = u.userInfo;
170.2089 +        v.host = u.host;
170.2090 +        v.port = u.port;
170.2091 +        v.path = np;
170.2092 +        v.query = u.query;
170.2093 +        return v;
170.2094 +    }
170.2095 +
170.2096 +    // If both URIs are hierarchical, their scheme and authority components are
170.2097 +    // identical, and the base path is a prefix of the child's path, then
170.2098 +    // return a relative URI that, when resolved against the base, yields the
170.2099 +    // child; otherwise, return the child.
170.2100 +    //
170.2101 +    private static URI relativize(URI base, URI child) {
170.2102 +        // check if child if opaque first so that NPE is thrown
170.2103 +        // if child is null.
170.2104 +        if (child.isOpaque() || base.isOpaque())
170.2105 +            return child;
170.2106 +        if (!equalIgnoringCase(base.scheme, child.scheme)
170.2107 +            || !equal(base.authority, child.authority))
170.2108 +            return child;
170.2109 +
170.2110 +        String bp = normalize(base.path);
170.2111 +        String cp = normalize(child.path);
170.2112 +        if (!bp.equals(cp)) {
170.2113 +            if (!bp.endsWith("/"))
170.2114 +                bp = bp + "/";
170.2115 +            if (!cp.startsWith(bp))
170.2116 +                return child;
170.2117 +        }
170.2118 +
170.2119 +        URI v = new URI();
170.2120 +        v.path = cp.substring(bp.length());
170.2121 +        v.query = child.query;
170.2122 +        v.fragment = child.fragment;
170.2123 +        return v;
170.2124 +    }
170.2125 +
170.2126 +
170.2127 +
170.2128 +    // -- Path normalization --
170.2129 +
170.2130 +    // The following algorithm for path normalization avoids the creation of a
170.2131 +    // string object for each segment, as well as the use of a string buffer to
170.2132 +    // compute the final result, by using a single char array and editing it in
170.2133 +    // place.  The array is first split into segments, replacing each slash
170.2134 +    // with '\0' and creating a segment-index array, each element of which is
170.2135 +    // the index of the first char in the corresponding segment.  We then walk
170.2136 +    // through both arrays, removing ".", "..", and other segments as necessary
170.2137 +    // by setting their entries in the index array to -1.  Finally, the two
170.2138 +    // arrays are used to rejoin the segments and compute the final result.
170.2139 +    //
170.2140 +    // This code is based upon src/solaris/native/java/io/canonicalize_md.c
170.2141 +
170.2142 +
170.2143 +    // Check the given path to see if it might need normalization.  A path
170.2144 +    // might need normalization if it contains duplicate slashes, a "."
170.2145 +    // segment, or a ".." segment.  Return -1 if no further normalization is
170.2146 +    // possible, otherwise return the number of segments found.
170.2147 +    //
170.2148 +    // This method takes a string argument rather than a char array so that
170.2149 +    // this test can be performed without invoking path.toCharArray().
170.2150 +    //
170.2151 +    static private int needsNormalization(String path) {
170.2152 +        boolean normal = true;
170.2153 +        int ns = 0;                     // Number of segments
170.2154 +        int end = path.length() - 1;    // Index of last char in path
170.2155 +        int p = 0;                      // Index of next char in path
170.2156 +
170.2157 +        // Skip initial slashes
170.2158 +        while (p <= end) {
170.2159 +            if (path.charAt(p) != '/') break;
170.2160 +            p++;
170.2161 +        }
170.2162 +        if (p > 1) normal = false;
170.2163 +
170.2164 +        // Scan segments
170.2165 +        while (p <= end) {
170.2166 +
170.2167 +            // Looking at "." or ".." ?
170.2168 +            if ((path.charAt(p) == '.')
170.2169 +                && ((p == end)
170.2170 +                    || ((path.charAt(p + 1) == '/')
170.2171 +                        || ((path.charAt(p + 1) == '.')
170.2172 +                            && ((p + 1 == end)
170.2173 +                                || (path.charAt(p + 2) == '/')))))) {
170.2174 +                normal = false;
170.2175 +            }
170.2176 +            ns++;
170.2177 +
170.2178 +            // Find beginning of next segment
170.2179 +            while (p <= end) {
170.2180 +                if (path.charAt(p++) != '/')
170.2181 +                    continue;
170.2182 +
170.2183 +                // Skip redundant slashes
170.2184 +                while (p <= end) {
170.2185 +                    if (path.charAt(p) != '/') break;
170.2186 +                    normal = false;
170.2187 +                    p++;
170.2188 +                }
170.2189 +
170.2190 +                break;
170.2191 +            }
170.2192 +        }
170.2193 +
170.2194 +        return normal ? -1 : ns;
170.2195 +    }
170.2196 +
170.2197 +
170.2198 +    // Split the given path into segments, replacing slashes with nulls and
170.2199 +    // filling in the given segment-index array.
170.2200 +    //
170.2201 +    // Preconditions:
170.2202 +    //   segs.length == Number of segments in path
170.2203 +    //
170.2204 +    // Postconditions:
170.2205 +    //   All slashes in path replaced by '\0'
170.2206 +    //   segs[i] == Index of first char in segment i (0 <= i < segs.length)
170.2207 +    //
170.2208 +    static private void split(char[] path, int[] segs) {
170.2209 +        int end = path.length - 1;      // Index of last char in path
170.2210 +        int p = 0;                      // Index of next char in path
170.2211 +        int i = 0;                      // Index of current segment
170.2212 +
170.2213 +        // Skip initial slashes
170.2214 +        while (p <= end) {
170.2215 +            if (path[p] != '/') break;
170.2216 +            path[p] = '\0';
170.2217 +            p++;
170.2218 +        }
170.2219 +
170.2220 +        while (p <= end) {
170.2221 +
170.2222 +            // Note start of segment
170.2223 +            segs[i++] = p++;
170.2224 +
170.2225 +            // Find beginning of next segment
170.2226 +            while (p <= end) {
170.2227 +                if (path[p++] != '/')
170.2228 +                    continue;
170.2229 +                path[p - 1] = '\0';
170.2230 +
170.2231 +                // Skip redundant slashes
170.2232 +                while (p <= end) {
170.2233 +                    if (path[p] != '/') break;
170.2234 +                    path[p++] = '\0';
170.2235 +                }
170.2236 +                break;
170.2237 +            }
170.2238 +        }
170.2239 +
170.2240 +        if (i != segs.length)
170.2241 +            throw new InternalError();  // ASSERT
170.2242 +    }
170.2243 +
170.2244 +
170.2245 +    // Join the segments in the given path according to the given segment-index
170.2246 +    // array, ignoring those segments whose index entries have been set to -1,
170.2247 +    // and inserting slashes as needed.  Return the length of the resulting
170.2248 +    // path.
170.2249 +    //
170.2250 +    // Preconditions:
170.2251 +    //   segs[i] == -1 implies segment i is to be ignored
170.2252 +    //   path computed by split, as above, with '\0' having replaced '/'
170.2253 +    //
170.2254 +    // Postconditions:
170.2255 +    //   path[0] .. path[return value] == Resulting path
170.2256 +    //
170.2257 +    static private int join(char[] path, int[] segs) {
170.2258 +        int ns = segs.length;           // Number of segments
170.2259 +        int end = path.length - 1;      // Index of last char in path
170.2260 +        int p = 0;                      // Index of next path char to write
170.2261 +
170.2262 +        if (path[p] == '\0') {
170.2263 +            // Restore initial slash for absolute paths
170.2264 +            path[p++] = '/';
170.2265 +        }
170.2266 +
170.2267 +        for (int i = 0; i < ns; i++) {
170.2268 +            int q = segs[i];            // Current segment
170.2269 +            if (q == -1)
170.2270 +                // Ignore this segment
170.2271 +                continue;
170.2272 +
170.2273 +            if (p == q) {
170.2274 +                // We're already at this segment, so just skip to its end
170.2275 +                while ((p <= end) && (path[p] != '\0'))
170.2276 +                    p++;
170.2277 +                if (p <= end) {
170.2278 +                    // Preserve trailing slash
170.2279 +                    path[p++] = '/';
170.2280 +                }
170.2281 +            } else if (p < q) {
170.2282 +                // Copy q down to p
170.2283 +                while ((q <= end) && (path[q] != '\0'))
170.2284 +                    path[p++] = path[q++];
170.2285 +                if (q <= end) {
170.2286 +                    // Preserve trailing slash
170.2287 +                    path[p++] = '/';
170.2288 +                }
170.2289 +            } else
170.2290 +                throw new InternalError(); // ASSERT false
170.2291 +        }
170.2292 +
170.2293 +        return p;
170.2294 +    }
170.2295 +
170.2296 +
170.2297 +    // Remove "." segments from the given path, and remove segment pairs
170.2298 +    // consisting of a non-".." segment followed by a ".." segment.
170.2299 +    //
170.2300 +    private static void removeDots(char[] path, int[] segs) {
170.2301 +        int ns = segs.length;
170.2302 +        int end = path.length - 1;
170.2303 +
170.2304 +        for (int i = 0; i < ns; i++) {
170.2305 +            int dots = 0;               // Number of dots found (0, 1, or 2)
170.2306 +
170.2307 +            // Find next occurrence of "." or ".."
170.2308 +            do {
170.2309 +                int p = segs[i];
170.2310 +                if (path[p] == '.') {
170.2311 +                    if (p == end) {
170.2312 +                        dots = 1;
170.2313 +                        break;
170.2314 +                    } else if (path[p + 1] == '\0') {
170.2315 +                        dots = 1;
170.2316 +                        break;
170.2317 +                    } else if ((path[p + 1] == '.')
170.2318 +                               && ((p + 1 == end)
170.2319 +                                   || (path[p + 2] == '\0'))) {
170.2320 +                        dots = 2;
170.2321 +                        break;
170.2322 +                    }
170.2323 +                }
170.2324 +                i++;
170.2325 +            } while (i < ns);
170.2326 +            if ((i > ns) || (dots == 0))
170.2327 +                break;
170.2328 +
170.2329 +            if (dots == 1) {
170.2330 +                // Remove this occurrence of "."
170.2331 +                segs[i] = -1;
170.2332 +            } else {
170.2333 +                // If there is a preceding non-".." segment, remove both that
170.2334 +                // segment and this occurrence of ".."; otherwise, leave this
170.2335 +                // ".." segment as-is.
170.2336 +                int j;
170.2337 +                for (j = i - 1; j >= 0; j--) {
170.2338 +                    if (segs[j] != -1) break;
170.2339 +                }
170.2340 +                if (j >= 0) {
170.2341 +                    int q = segs[j];
170.2342 +                    if (!((path[q] == '.')
170.2343 +                          && (path[q + 1] == '.')
170.2344 +                          && (path[q + 2] == '\0'))) {
170.2345 +                        segs[i] = -1;
170.2346 +                        segs[j] = -1;
170.2347 +                    }
170.2348 +                }
170.2349 +            }
170.2350 +        }
170.2351 +    }
170.2352 +
170.2353 +
170.2354 +    // DEVIATION: If the normalized path is relative, and if the first
170.2355 +    // segment could be parsed as a scheme name, then prepend a "." segment
170.2356 +    //
170.2357 +    private static void maybeAddLeadingDot(char[] path, int[] segs) {
170.2358 +
170.2359 +        if (path[0] == '\0')
170.2360 +            // The path is absolute
170.2361 +            return;
170.2362 +
170.2363 +        int ns = segs.length;
170.2364 +        int f = 0;                      // Index of first segment
170.2365 +        while (f < ns) {
170.2366 +            if (segs[f] >= 0)
170.2367 +                break;
170.2368 +            f++;
170.2369 +        }
170.2370 +        if ((f >= ns) || (f == 0))
170.2371 +            // The path is empty, or else the original first segment survived,
170.2372 +            // in which case we already know that no leading "." is needed
170.2373 +            return;
170.2374 +
170.2375 +        int p = segs[f];
170.2376 +        while ((p < path.length) && (path[p] != ':') && (path[p] != '\0')) p++;
170.2377 +        if (p >= path.length || path[p] == '\0')
170.2378 +            // No colon in first segment, so no "." needed
170.2379 +            return;
170.2380 +
170.2381 +        // At this point we know that the first segment is unused,
170.2382 +        // hence we can insert a "." segment at that position
170.2383 +        path[0] = '.';
170.2384 +        path[1] = '\0';
170.2385 +        segs[0] = 0;
170.2386 +    }
170.2387 +
170.2388 +
170.2389 +    // Normalize the given path string.  A normal path string has no empty
170.2390 +    // segments (i.e., occurrences of "//"), no segments equal to ".", and no
170.2391 +    // segments equal to ".." that are preceded by a segment not equal to "..".
170.2392 +    // In contrast to Unix-style pathname normalization, for URI paths we
170.2393 +    // always retain trailing slashes.
170.2394 +    //
170.2395 +    private static String normalize(String ps) {
170.2396 +
170.2397 +        // Does this path need normalization?
170.2398 +        int ns = needsNormalization(ps);        // Number of segments
170.2399 +        if (ns < 0)
170.2400 +            // Nope -- just return it
170.2401 +            return ps;
170.2402 +
170.2403 +        char[] path = ps.toCharArray();         // Path in char-array form
170.2404 +
170.2405 +        // Split path into segments
170.2406 +        int[] segs = new int[ns];               // Segment-index array
170.2407 +        split(path, segs);
170.2408 +
170.2409 +        // Remove dots
170.2410 +        removeDots(path, segs);
170.2411 +
170.2412 +        // Prevent scheme-name confusion
170.2413 +        maybeAddLeadingDot(path, segs);
170.2414 +
170.2415 +        // Join the remaining segments and return the result
170.2416 +        String s = new String(path, 0, join(path, segs));
170.2417 +        if (s.equals(ps)) {
170.2418 +            // string was already normalized
170.2419 +            return ps;
170.2420 +        }
170.2421 +        return s;
170.2422 +    }
170.2423 +
170.2424 +
170.2425 +
170.2426 +    // -- Character classes for parsing --
170.2427 +
170.2428 +    // RFC2396 precisely specifies which characters in the US-ASCII charset are
170.2429 +    // permissible in the various components of a URI reference.  We here
170.2430 +    // define a set of mask pairs to aid in enforcing these restrictions.  Each
170.2431 +    // mask pair consists of two longs, a low mask and a high mask.  Taken
170.2432 +    // together they represent a 128-bit mask, where bit i is set iff the
170.2433 +    // character with value i is permitted.
170.2434 +    //
170.2435 +    // This approach is more efficient than sequentially searching arrays of
170.2436 +    // permitted characters.  It could be made still more efficient by
170.2437 +    // precompiling the mask information so that a character's presence in a
170.2438 +    // given mask could be determined by a single table lookup.
170.2439 +
170.2440 +    // Compute the low-order mask for the characters in the given string
170.2441 +    private static long lowMask(String chars) {
170.2442 +        int n = chars.length();
170.2443 +        long m = 0;
170.2444 +        for (int i = 0; i < n; i++) {
170.2445 +            char c = chars.charAt(i);
170.2446 +            if (c < 64)
170.2447 +                m |= (1L << c);
170.2448 +        }
170.2449 +        return m;
170.2450 +    }
170.2451 +
170.2452 +    // Compute the high-order mask for the characters in the given string
170.2453 +    private static long highMask(String chars) {
170.2454 +        int n = chars.length();
170.2455 +        long m = 0;
170.2456 +        for (int i = 0; i < n; i++) {
170.2457 +            char c = chars.charAt(i);
170.2458 +            if ((c >= 64) && (c < 128))
170.2459 +                m |= (1L << (c - 64));
170.2460 +        }
170.2461 +        return m;
170.2462 +    }
170.2463 +
170.2464 +    // Compute a low-order mask for the characters
170.2465 +    // between first and last, inclusive
170.2466 +    private static long lowMask(char first, char last) {
170.2467 +        long m = 0;
170.2468 +        int f = Math.max(Math.min(first, 63), 0);
170.2469 +        int l = Math.max(Math.min(last, 63), 0);
170.2470 +        for (int i = f; i <= l; i++)
170.2471 +            m |= 1L << i;
170.2472 +        return m;
170.2473 +    }
170.2474 +
170.2475 +    // Compute a high-order mask for the characters
170.2476 +    // between first and last, inclusive
170.2477 +    private static long highMask(char first, char last) {
170.2478 +        long m = 0;
170.2479 +        int f = Math.max(Math.min(first, 127), 64) - 64;
170.2480 +        int l = Math.max(Math.min(last, 127), 64) - 64;
170.2481 +        for (int i = f; i <= l; i++)
170.2482 +            m |= 1L << i;
170.2483 +        return m;
170.2484 +    }
170.2485 +
170.2486 +    // Tell whether the given character is permitted by the given mask pair
170.2487 +    private static boolean match(char c, long lowMask, long highMask) {
170.2488 +        if (c == 0) // 0 doesn't have a slot in the mask. So, it never matches.
170.2489 +            return false;
170.2490 +        if (c < 64)
170.2491 +            return ((1L << c) & lowMask) != 0;
170.2492 +        if (c < 128)
170.2493 +            return ((1L << (c - 64)) & highMask) != 0;
170.2494 +        return false;
170.2495 +    }
170.2496 +
170.2497 +    // Character-class masks, in reverse order from RFC2396 because
170.2498 +    // initializers for static fields cannot make forward references.
170.2499 +
170.2500 +    // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
170.2501 +    //            "8" | "9"
170.2502 +    private static final long L_DIGIT = lowMask('0', '9');
170.2503 +    private static final long H_DIGIT = 0L;
170.2504 +
170.2505 +    // upalpha  = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
170.2506 +    //            "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
170.2507 +    //            "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
170.2508 +    private static final long L_UPALPHA = 0L;
170.2509 +    private static final long H_UPALPHA = highMask('A', 'Z');
170.2510 +
170.2511 +    // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
170.2512 +    //            "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
170.2513 +    //            "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
170.2514 +    private static final long L_LOWALPHA = 0L;
170.2515 +    private static final long H_LOWALPHA = highMask('a', 'z');
170.2516 +
170.2517 +    // alpha         = lowalpha | upalpha
170.2518 +    private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA;
170.2519 +    private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA;
170.2520 +
170.2521 +    // alphanum      = alpha | digit
170.2522 +    private static final long L_ALPHANUM = L_DIGIT | L_ALPHA;
170.2523 +    private static final long H_ALPHANUM = H_DIGIT | H_ALPHA;
170.2524 +
170.2525 +    // hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
170.2526 +    //                         "a" | "b" | "c" | "d" | "e" | "f"
170.2527 +    private static final long L_HEX = L_DIGIT;
170.2528 +    private static final long H_HEX = highMask('A', 'F') | highMask('a', 'f');
170.2529 +
170.2530 +    // mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
170.2531 +    //                 "(" | ")"
170.2532 +    private static final long L_MARK = lowMask("-_.!~*'()");
170.2533 +    private static final long H_MARK = highMask("-_.!~*'()");
170.2534 +
170.2535 +    // unreserved    = alphanum | mark
170.2536 +    private static final long L_UNRESERVED = L_ALPHANUM | L_MARK;
170.2537 +    private static final long H_UNRESERVED = H_ALPHANUM | H_MARK;
170.2538 +
170.2539 +    // reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
170.2540 +    //                 "$" | "," | "[" | "]"
170.2541 +    // Added per RFC2732: "[", "]"
170.2542 +    private static final long L_RESERVED = lowMask(";/?:@&=+$,[]");
170.2543 +    private static final long H_RESERVED = highMask(";/?:@&=+$,[]");
170.2544 +
170.2545 +    // The zero'th bit is used to indicate that escape pairs and non-US-ASCII
170.2546 +    // characters are allowed; this is handled by the scanEscape method below.
170.2547 +    private static final long L_ESCAPED = 1L;
170.2548 +    private static final long H_ESCAPED = 0L;
170.2549 +
170.2550 +    // uric          = reserved | unreserved | escaped
170.2551 +    private static final long L_URIC = L_RESERVED | L_UNRESERVED | L_ESCAPED;
170.2552 +    private static final long H_URIC = H_RESERVED | H_UNRESERVED | H_ESCAPED;
170.2553 +
170.2554 +    // pchar         = unreserved | escaped |
170.2555 +    //                 ":" | "@" | "&" | "=" | "+" | "$" | ","
170.2556 +    private static final long L_PCHAR
170.2557 +        = L_UNRESERVED | L_ESCAPED | lowMask(":@&=+$,");
170.2558 +    private static final long H_PCHAR
170.2559 +        = H_UNRESERVED | H_ESCAPED | highMask(":@&=+$,");
170.2560 +
170.2561 +    // All valid path characters
170.2562 +    private static final long L_PATH = L_PCHAR | lowMask(";/");
170.2563 +    private static final long H_PATH = H_PCHAR | highMask(";/");
170.2564 +
170.2565 +    // Dash, for use in domainlabel and toplabel
170.2566 +    private static final long L_DASH = lowMask("-");
170.2567 +    private static final long H_DASH = highMask("-");
170.2568 +
170.2569 +    // Dot, for use in hostnames
170.2570 +    private static final long L_DOT = lowMask(".");
170.2571 +    private static final long H_DOT = highMask(".");
170.2572 +
170.2573 +    // userinfo      = *( unreserved | escaped |
170.2574 +    //                    ";" | ":" | "&" | "=" | "+" | "$" | "," )
170.2575 +    private static final long L_USERINFO
170.2576 +        = L_UNRESERVED | L_ESCAPED | lowMask(";:&=+$,");
170.2577 +    private static final long H_USERINFO
170.2578 +        = H_UNRESERVED | H_ESCAPED | highMask(";:&=+$,");
170.2579 +
170.2580 +    // reg_name      = 1*( unreserved | escaped | "$" | "," |
170.2581 +    //                     ";" | ":" | "@" | "&" | "=" | "+" )
170.2582 +    private static final long L_REG_NAME
170.2583 +        = L_UNRESERVED | L_ESCAPED | lowMask("$,;:@&=+");
170.2584 +    private static final long H_REG_NAME
170.2585 +        = H_UNRESERVED | H_ESCAPED | highMask("$,;:@&=+");
170.2586 +
170.2587 +    // All valid characters for server-based authorities
170.2588 +    private static final long L_SERVER
170.2589 +        = L_USERINFO | L_ALPHANUM | L_DASH | lowMask(".:@[]");
170.2590 +    private static final long H_SERVER
170.2591 +        = H_USERINFO | H_ALPHANUM | H_DASH | highMask(".:@[]");
170.2592 +
170.2593 +    // Special case of server authority that represents an IPv6 address
170.2594 +    // In this case, a % does not signify an escape sequence
170.2595 +    private static final long L_SERVER_PERCENT
170.2596 +        = L_SERVER | lowMask("%");
170.2597 +    private static final long H_SERVER_PERCENT
170.2598 +        = H_SERVER | highMask("%");
170.2599 +    private static final long L_LEFT_BRACKET = lowMask("[");
170.2600 +    private static final long H_LEFT_BRACKET = highMask("[");
170.2601 +
170.2602 +    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
170.2603 +    private static final long L_SCHEME = L_ALPHA | L_DIGIT | lowMask("+-.");
170.2604 +    private static final long H_SCHEME = H_ALPHA | H_DIGIT | highMask("+-.");
170.2605 +
170.2606 +    // uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
170.2607 +    //                 "&" | "=" | "+" | "$" | ","
170.2608 +    private static final long L_URIC_NO_SLASH
170.2609 +        = L_UNRESERVED | L_ESCAPED | lowMask(";?:@&=+$,");
170.2610 +    private static final long H_URIC_NO_SLASH
170.2611 +        = H_UNRESERVED | H_ESCAPED | highMask(";?:@&=+$,");
170.2612 +
170.2613 +
170.2614 +    // -- Escaping and encoding --
170.2615 +
170.2616 +    private final static char[] hexDigits = {
170.2617 +        '0', '1', '2', '3', '4', '5', '6', '7',
170.2618 +        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
170.2619 +    };
170.2620 +
170.2621 +    private static void appendEscape(StringBuffer sb, byte b) {
170.2622 +        sb.append('%');
170.2623 +        sb.append(hexDigits[(b >> 4) & 0x0f]);
170.2624 +        sb.append(hexDigits[(b >> 0) & 0x0f]);
170.2625 +    }
170.2626 +
170.2627 +    private static void appendEncoded(StringBuffer sb, char c) {
170.2628 +        /*
170.2629 +        ByteBuffer bb = null;
170.2630 +        try {
170.2631 +            bb = ThreadLocalCoders.encoderFor("UTF-8")
170.2632 +                .encode(CharBuffer.wrap("" + c));
170.2633 +        } catch (CharacterCodingException x) {
170.2634 +            assert false;
170.2635 +        }
170.2636 +        while (bb.hasRemaining()) {
170.2637 +            int b = bb.get() & 0xff;
170.2638 +            if (b >= 0x80)
170.2639 +                appendEscape(sb, (byte)b);
170.2640 +            else
170.2641 +                sb.append((char)b);
170.2642 +        }
170.2643 +        */
170.2644 +    }
170.2645 +
170.2646 +    // Quote any characters in s that are not permitted
170.2647 +    // by the given mask pair
170.2648 +    //
170.2649 +    private static String quote(String s, long lowMask, long highMask) {
170.2650 +        int n = s.length();
170.2651 +        StringBuffer sb = null;
170.2652 +        boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0);
170.2653 +        for (int i = 0; i < s.length(); i++) {
170.2654 +            char c = s.charAt(i);
170.2655 +            if (c < '\u0080') {
170.2656 +                if (!match(c, lowMask, highMask)) {
170.2657 +                    if (sb == null) {
170.2658 +                        sb = new StringBuffer();
170.2659 +                        sb.append(s.substring(0, i));
170.2660 +                    }
170.2661 +                    appendEscape(sb, (byte)c);
170.2662 +                } else {
170.2663 +                    if (sb != null)
170.2664 +                        sb.append(c);
170.2665 +                }
170.2666 +            } else if (allowNonASCII
170.2667 +                       && (Character.isSpaceChar(c)
170.2668 +                           || Character.isISOControl(c))) {
170.2669 +                if (sb == null) {
170.2670 +                    sb = new StringBuffer();
170.2671 +                    sb.append(s.substring(0, i));
170.2672 +                }
170.2673 +                appendEncoded(sb, c);
170.2674 +            } else {
170.2675 +                if (sb != null)
170.2676 +                    sb.append(c);
170.2677 +            }
170.2678 +        }
170.2679 +        return (sb == null) ? s : sb.toString();
170.2680 +    }
170.2681 +
170.2682 +    // Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets,
170.2683 +    // assuming that s is otherwise legal
170.2684 +    //
170.2685 +    private static String encode(String s) {
170.2686 +        int n = s.length();
170.2687 +        if (n == 0)
170.2688 +            return s;
170.2689 +
170.2690 +        // First check whether we actually need to encode
170.2691 +        for (int i = 0;;) {
170.2692 +            if (s.charAt(i) >= '\u0080')
170.2693 +                break;
170.2694 +            if (++i >= n)
170.2695 +                return s;
170.2696 +        }
170.2697 +/*
170.2698 +        String ns = Normalizer.normalize(s, Normalizer.Form.NFC);
170.2699 +        ByteBuffer bb = null;
170.2700 +        try {
170.2701 +            bb = ThreadLocalCoders.encoderFor("UTF-8")
170.2702 +                .encode(CharBuffer.wrap(ns));
170.2703 +        } catch (CharacterCodingException x) {
170.2704 +            assert false;
170.2705 +        }
170.2706 +*/
170.2707 +        StringBuffer sb = new StringBuffer();
170.2708 +        /*
170.2709 +        while (bb.hasRemaining()) {
170.2710 +            int b = bb.get() & 0xff;
170.2711 +            if (b >= 0x80)
170.2712 +                appendEscape(sb, (byte)b);
170.2713 +            else
170.2714 +                sb.append((char)b);
170.2715 +        }
170.2716 +        */
170.2717 +        return sb.toString();
170.2718 +    }
170.2719 +
170.2720 +    private static int decode(char c) {
170.2721 +        if ((c >= '0') && (c <= '9'))
170.2722 +            return c - '0';
170.2723 +        if ((c >= 'a') && (c <= 'f'))
170.2724 +            return c - 'a' + 10;
170.2725 +        if ((c >= 'A') && (c <= 'F'))
170.2726 +            return c - 'A' + 10;
170.2727 +        assert false;
170.2728 +        return -1;
170.2729 +    }
170.2730 +
170.2731 +    private static byte decode(char c1, char c2) {
170.2732 +        return (byte)(  ((decode(c1) & 0xf) << 4)
170.2733 +                      | ((decode(c2) & 0xf) << 0));
170.2734 +    }
170.2735 +
170.2736 +    // Evaluates all escapes in s, applying UTF-8 decoding if needed.  Assumes
170.2737 +    // that escapes are well-formed syntactically, i.e., of the form %XX.  If a
170.2738 +    // sequence of escaped octets is not valid UTF-8 then the erroneous octets
170.2739 +    // are replaced with '\uFFFD'.
170.2740 +    // Exception: any "%" found between "[]" is left alone. It is an IPv6 literal
170.2741 +    //            with a scope_id
170.2742 +    //
170.2743 +    private static String decode(String s) {
170.2744 +        if (s == null)
170.2745 +            return s;
170.2746 +        int n = s.length();
170.2747 +        if (n == 0)
170.2748 +            return s;
170.2749 +        if (s.indexOf('%') < 0)
170.2750 +            return s;
170.2751 +
170.2752 +        StringBuffer sb = new StringBuffer(n);
170.2753 +        /*
170.2754 +        ByteBuffer bb = ByteBuffer.allocate(n);
170.2755 +        CharBuffer cb = CharBuffer.allocate(n);
170.2756 +        CharsetDecoder dec = ThreadLocalCoders.decoderFor("UTF-8")
170.2757 +            .onMalformedInput(CodingErrorAction.REPLACE)
170.2758 +            .onUnmappableCharacter(CodingErrorAction.REPLACE);
170.2759 +
170.2760 +        // This is not horribly efficient, but it will do for now
170.2761 +        char c = s.charAt(0);
170.2762 +        boolean betweenBrackets = false;
170.2763 +
170.2764 +        for (int i = 0; i < n;) {
170.2765 +            assert c == s.charAt(i);    // Loop invariant
170.2766 +            if (c == '[') {
170.2767 +                betweenBrackets = true;
170.2768 +            } else if (betweenBrackets && c == ']') {
170.2769 +                betweenBrackets = false;
170.2770 +            }
170.2771 +            if (c != '%' || betweenBrackets) {
170.2772 +                sb.append(c);
170.2773 +                if (++i >= n)
170.2774 +                    break;
170.2775 +                c = s.charAt(i);
170.2776 +                continue;
170.2777 +            }
170.2778 +            bb.clear();
170.2779 +            int ui = i;
170.2780 +            for (;;) {
170.2781 +                assert (n - i >= 2);
170.2782 +                bb.put(decode(s.charAt(++i), s.charAt(++i)));
170.2783 +                if (++i >= n)
170.2784 +                    break;
170.2785 +                c = s.charAt(i);
170.2786 +                if (c != '%')
170.2787 +                    break;
170.2788 +            }
170.2789 +            bb.flip();
170.2790 +            cb.clear();
170.2791 +            dec.reset();
170.2792 +            CoderResult cr = dec.decode(bb, cb, true);
170.2793 +            assert cr.isUnderflow();
170.2794 +            cr = dec.flush(cb);
170.2795 +            assert cr.isUnderflow();
170.2796 +            sb.append(cb.flip().toString());
170.2797 +        }
170.2798 +*/
170.2799 +        return sb.toString();
170.2800 +    }
170.2801 +
170.2802 +
170.2803 +    // -- Parsing --
170.2804 +
170.2805 +    // For convenience we wrap the input URI string in a new instance of the
170.2806 +    // following internal class.  This saves always having to pass the input
170.2807 +    // string as an argument to each internal scan/parse method.
170.2808 +
170.2809 +    private class Parser {
170.2810 +
170.2811 +        private String input;           // URI input string
170.2812 +        private boolean requireServerAuthority = false;
170.2813 +
170.2814 +        Parser(String s) {
170.2815 +            input = s;
170.2816 +            string = s;
170.2817 +        }
170.2818 +
170.2819 +        // -- Methods for throwing URISyntaxException in various ways --
170.2820 +
170.2821 +        private void fail(String reason) throws URISyntaxException {
170.2822 +            throw new URISyntaxException(input, reason);
170.2823 +        }
170.2824 +
170.2825 +        private void fail(String reason, int p) throws URISyntaxException {
170.2826 +            throw new URISyntaxException(input, reason, p);
170.2827 +        }
170.2828 +
170.2829 +        private void failExpecting(String expected, int p)
170.2830 +            throws URISyntaxException
170.2831 +        {
170.2832 +            fail("Expected " + expected, p);
170.2833 +        }
170.2834 +
170.2835 +        private void failExpecting(String expected, String prior, int p)
170.2836 +            throws URISyntaxException
170.2837 +        {
170.2838 +            fail("Expected " + expected + " following " + prior, p);
170.2839 +        }
170.2840 +
170.2841 +
170.2842 +        // -- Simple access to the input string --
170.2843 +
170.2844 +        // Return a substring of the input string
170.2845 +        //
170.2846 +        private String substring(int start, int end) {
170.2847 +            return input.substring(start, end);
170.2848 +        }
170.2849 +
170.2850 +        // Return the char at position p,
170.2851 +        // assuming that p < input.length()
170.2852 +        //
170.2853 +        private char charAt(int p) {
170.2854 +            return input.charAt(p);
170.2855 +        }
170.2856 +
170.2857 +        // Tells whether start < end and, if so, whether charAt(start) == c
170.2858 +        //
170.2859 +        private boolean at(int start, int end, char c) {
170.2860 +            return (start < end) && (charAt(start) == c);
170.2861 +        }
170.2862 +
170.2863 +        // Tells whether start + s.length() < end and, if so,
170.2864 +        // whether the chars at the start position match s exactly
170.2865 +        //
170.2866 +        private boolean at(int start, int end, String s) {
170.2867 +            int p = start;
170.2868 +            int sn = s.length();
170.2869 +            if (sn > end - p)
170.2870 +                return false;
170.2871 +            int i = 0;
170.2872 +            while (i < sn) {
170.2873 +                if (charAt(p++) != s.charAt(i)) {
170.2874 +                    break;
170.2875 +                }
170.2876 +                i++;
170.2877 +            }
170.2878 +            return (i == sn);
170.2879 +        }
170.2880 +
170.2881 +
170.2882 +        // -- Scanning --
170.2883 +
170.2884 +        // The various scan and parse methods that follow use a uniform
170.2885 +        // convention of taking the current start position and end index as
170.2886 +        // their first two arguments.  The start is inclusive while the end is
170.2887 +        // exclusive, just as in the String class, i.e., a start/end pair
170.2888 +        // denotes the left-open interval [start, end) of the input string.
170.2889 +        //
170.2890 +        // These methods never proceed past the end position.  They may return
170.2891 +        // -1 to indicate outright failure, but more often they simply return
170.2892 +        // the position of the first char after the last char scanned.  Thus
170.2893 +        // a typical idiom is
170.2894 +        //
170.2895 +        //     int p = start;
170.2896 +        //     int q = scan(p, end, ...);
170.2897 +        //     if (q > p)
170.2898 +        //         // We scanned something
170.2899 +        //         ...;
170.2900 +        //     else if (q == p)
170.2901 +        //         // We scanned nothing
170.2902 +        //         ...;
170.2903 +        //     else if (q == -1)
170.2904 +        //         // Something went wrong
170.2905 +        //         ...;
170.2906 +
170.2907 +
170.2908 +        // Scan a specific char: If the char at the given start position is
170.2909 +        // equal to c, return the index of the next char; otherwise, return the
170.2910 +        // start position.
170.2911 +        //
170.2912 +        private int scan(int start, int end, char c) {
170.2913 +            if ((start < end) && (charAt(start) == c))
170.2914 +                return start + 1;
170.2915 +            return start;
170.2916 +        }
170.2917 +
170.2918 +        // Scan forward from the given start position.  Stop at the first char
170.2919 +        // in the err string (in which case -1 is returned), or the first char
170.2920 +        // in the stop string (in which case the index of the preceding char is
170.2921 +        // returned), or the end of the input string (in which case the length
170.2922 +        // of the input string is returned).  May return the start position if
170.2923 +        // nothing matches.
170.2924 +        //
170.2925 +        private int scan(int start, int end, String err, String stop) {
170.2926 +            int p = start;
170.2927 +            while (p < end) {
170.2928 +                char c = charAt(p);
170.2929 +                if (err.indexOf(c) >= 0)
170.2930 +                    return -1;
170.2931 +                if (stop.indexOf(c) >= 0)
170.2932 +                    break;
170.2933 +                p++;
170.2934 +            }
170.2935 +            return p;
170.2936 +        }
170.2937 +
170.2938 +        // Scan a potential escape sequence, starting at the given position,
170.2939 +        // with the given first char (i.e., charAt(start) == c).
170.2940 +        //
170.2941 +        // This method assumes that if escapes are allowed then visible
170.2942 +        // non-US-ASCII chars are also allowed.
170.2943 +        //
170.2944 +        private int scanEscape(int start, int n, char first)
170.2945 +            throws URISyntaxException
170.2946 +        {
170.2947 +            int p = start;
170.2948 +            char c = first;
170.2949 +            if (c == '%') {
170.2950 +                // Process escape pair
170.2951 +                if ((p + 3 <= n)
170.2952 +                    && match(charAt(p + 1), L_HEX, H_HEX)
170.2953 +                    && match(charAt(p + 2), L_HEX, H_HEX)) {
170.2954 +                    return p + 3;
170.2955 +                }
170.2956 +                fail("Malformed escape pair", p);
170.2957 +            } else if ((c > 128)
170.2958 +                       && !Character.isSpaceChar(c)
170.2959 +                       && !Character.isISOControl(c)) {
170.2960 +                // Allow unescaped but visible non-US-ASCII chars
170.2961 +                return p + 1;
170.2962 +            }
170.2963 +            return p;
170.2964 +        }
170.2965 +
170.2966 +        // Scan chars that match the given mask pair
170.2967 +        //
170.2968 +        private int scan(int start, int n, long lowMask, long highMask)
170.2969 +            throws URISyntaxException
170.2970 +        {
170.2971 +            int p = start;
170.2972 +            while (p < n) {
170.2973 +                char c = charAt(p);
170.2974 +                if (match(c, lowMask, highMask)) {
170.2975 +                    p++;
170.2976 +                    continue;
170.2977 +                }
170.2978 +                if ((lowMask & L_ESCAPED) != 0) {
170.2979 +                    int q = scanEscape(p, n, c);
170.2980 +                    if (q > p) {
170.2981 +                        p = q;
170.2982 +                        continue;
170.2983 +                    }
170.2984 +                }
170.2985 +                break;
170.2986 +            }
170.2987 +            return p;
170.2988 +        }
170.2989 +
170.2990 +        // Check that each of the chars in [start, end) matches the given mask
170.2991 +        //
170.2992 +        private void checkChars(int start, int end,
170.2993 +                                long lowMask, long highMask,
170.2994 +                                String what)
170.2995 +            throws URISyntaxException
170.2996 +        {
170.2997 +            int p = scan(start, end, lowMask, highMask);
170.2998 +            if (p < end)
170.2999 +                fail("Illegal character in " + what, p);
170.3000 +        }
170.3001 +
170.3002 +        // Check that the char at position p matches the given mask
170.3003 +        //
170.3004 +        private void checkChar(int p,
170.3005 +                               long lowMask, long highMask,
170.3006 +                               String what)
170.3007 +            throws URISyntaxException
170.3008 +        {
170.3009 +            checkChars(p, p + 1, lowMask, highMask, what);
170.3010 +        }
170.3011 +
170.3012 +
170.3013 +        // -- Parsing --
170.3014 +
170.3015 +        // [<scheme>:]<scheme-specific-part>[#<fragment>]
170.3016 +        //
170.3017 +        void parse(boolean rsa) throws URISyntaxException {
170.3018 +            requireServerAuthority = rsa;
170.3019 +            int ssp;                    // Start of scheme-specific part
170.3020 +            int n = input.length();
170.3021 +            int p = scan(0, n, "/?#", ":");
170.3022 +            if ((p >= 0) && at(p, n, ':')) {
170.3023 +                if (p == 0)
170.3024 +                    failExpecting("scheme name", 0);
170.3025 +                checkChar(0, L_ALPHA, H_ALPHA, "scheme name");
170.3026 +                checkChars(1, p, L_SCHEME, H_SCHEME, "scheme name");
170.3027 +                scheme = substring(0, p);
170.3028 +                p++;                    // Skip ':'
170.3029 +                ssp = p;
170.3030 +                if (at(p, n, '/')) {
170.3031 +                    p = parseHierarchical(p, n);
170.3032 +                } else {
170.3033 +                    int q = scan(p, n, "", "#");
170.3034 +                    if (q <= p)
170.3035 +                        failExpecting("scheme-specific part", p);
170.3036 +                    checkChars(p, q, L_URIC, H_URIC, "opaque part");
170.3037 +                    p = q;
170.3038 +                }
170.3039 +            } else {
170.3040 +                ssp = 0;
170.3041 +                p = parseHierarchical(0, n);
170.3042 +            }
170.3043 +            schemeSpecificPart = substring(ssp, p);
170.3044 +            if (at(p, n, '#')) {
170.3045 +                checkChars(p + 1, n, L_URIC, H_URIC, "fragment");
170.3046 +                fragment = substring(p + 1, n);
170.3047 +                p = n;
170.3048 +            }
170.3049 +            if (p < n)
170.3050 +                fail("end of URI", p);
170.3051 +        }
170.3052 +
170.3053 +        // [//authority]<path>[?<query>]
170.3054 +        //
170.3055 +        // DEVIATION from RFC2396: We allow an empty authority component as
170.3056 +        // long as it's followed by a non-empty path, query component, or
170.3057 +        // fragment component.  This is so that URIs such as "file:///foo/bar"
170.3058 +        // will parse.  This seems to be the intent of RFC2396, though the
170.3059 +        // grammar does not permit it.  If the authority is empty then the
170.3060 +        // userInfo, host, and port components are undefined.
170.3061 +        //
170.3062 +        // DEVIATION from RFC2396: We allow empty relative paths.  This seems
170.3063 +        // to be the intent of RFC2396, but the grammar does not permit it.
170.3064 +        // The primary consequence of this deviation is that "#f" parses as a
170.3065 +        // relative URI with an empty path.
170.3066 +        //
170.3067 +        private int parseHierarchical(int start, int n)
170.3068 +            throws URISyntaxException
170.3069 +        {
170.3070 +            int p = start;
170.3071 +            if (at(p, n, '/') && at(p + 1, n, '/')) {
170.3072 +                p += 2;
170.3073 +                int q = scan(p, n, "", "/?#");
170.3074 +                if (q > p) {
170.3075 +                    p = parseAuthority(p, q);
170.3076 +                } else if (q < n) {
170.3077 +                    // DEVIATION: Allow empty authority prior to non-empty
170.3078 +                    // path, query component or fragment identifier
170.3079 +                } else
170.3080 +                    failExpecting("authority", p);
170.3081 +            }
170.3082 +            int q = scan(p, n, "", "?#"); // DEVIATION: May be empty
170.3083 +            checkChars(p, q, L_PATH, H_PATH, "path");
170.3084 +            path = substring(p, q);
170.3085 +            p = q;
170.3086 +            if (at(p, n, '?')) {
170.3087 +                p++;
170.3088 +                q = scan(p, n, "", "#");
170.3089 +                checkChars(p, q, L_URIC, H_URIC, "query");
170.3090 +                query = substring(p, q);
170.3091 +                p = q;
170.3092 +            }
170.3093 +            return p;
170.3094 +        }
170.3095 +
170.3096 +        // authority     = server | reg_name
170.3097 +        //
170.3098 +        // Ambiguity: An authority that is a registry name rather than a server
170.3099 +        // might have a prefix that parses as a server.  We use the fact that
170.3100 +        // the authority component is always followed by '/' or the end of the
170.3101 +        // input string to resolve this: If the complete authority did not
170.3102 +        // parse as a server then we try to parse it as a registry name.
170.3103 +        //
170.3104 +        private int parseAuthority(int start, int n)
170.3105 +            throws URISyntaxException
170.3106 +        {
170.3107 +            int p = start;
170.3108 +            int q = p;
170.3109 +            URISyntaxException ex = null;
170.3110 +
170.3111 +            boolean serverChars;
170.3112 +            boolean regChars;
170.3113 +
170.3114 +            if (scan(p, n, "", "]") > p) {
170.3115 +                // contains a literal IPv6 address, therefore % is allowed
170.3116 +                serverChars = (scan(p, n, L_SERVER_PERCENT, H_SERVER_PERCENT) == n);
170.3117 +            } else {
170.3118 +                serverChars = (scan(p, n, L_SERVER, H_SERVER) == n);
170.3119 +            }
170.3120 +            regChars = (scan(p, n, L_REG_NAME, H_REG_NAME) == n);
170.3121 +
170.3122 +            if (regChars && !serverChars) {
170.3123 +                // Must be a registry-based authority
170.3124 +                authority = substring(p, n);
170.3125 +                return n;
170.3126 +            }
170.3127 +
170.3128 +            if (serverChars) {
170.3129 +                // Might be (probably is) a server-based authority, so attempt
170.3130 +                // to parse it as such.  If the attempt fails, try to treat it
170.3131 +                // as a registry-based authority.
170.3132 +                try {
170.3133 +                    q = parseServer(p, n);
170.3134 +                    if (q < n)
170.3135 +                        failExpecting("end of authority", q);
170.3136 +                    authority = substring(p, n);
170.3137 +                } catch (URISyntaxException x) {
170.3138 +                    // Undo results of failed parse
170.3139 +                    userInfo = null;
170.3140 +                    host = null;
170.3141 +                    port = -1;
170.3142 +                    if (requireServerAuthority) {
170.3143 +                        // If we're insisting upon a server-based authority,
170.3144 +                        // then just re-throw the exception
170.3145 +                        throw x;
170.3146 +                    } else {
170.3147 +                        // Save the exception in case it doesn't parse as a
170.3148 +                        // registry either
170.3149 +                        ex = x;
170.3150 +                        q = p;
170.3151 +                    }
170.3152 +                }
170.3153 +            }
170.3154 +
170.3155 +            if (q < n) {
170.3156 +                if (regChars) {
170.3157 +                    // Registry-based authority
170.3158 +                    authority = substring(p, n);
170.3159 +                } else if (ex != null) {
170.3160 +                    // Re-throw exception; it was probably due to
170.3161 +                    // a malformed IPv6 address
170.3162 +                    throw ex;
170.3163 +                } else {
170.3164 +                    fail("Illegal character in authority", q);
170.3165 +                }
170.3166 +            }
170.3167 +
170.3168 +            return n;
170.3169 +        }
170.3170 +
170.3171 +
170.3172 +        // [<userinfo>@]<host>[:<port>]
170.3173 +        //
170.3174 +        private int parseServer(int start, int n)
170.3175 +            throws URISyntaxException
170.3176 +        {
170.3177 +            int p = start;
170.3178 +            int q;
170.3179 +
170.3180 +            // userinfo
170.3181 +            q = scan(p, n, "/?#", "@");
170.3182 +            if ((q >= p) && at(q, n, '@')) {
170.3183 +                checkChars(p, q, L_USERINFO, H_USERINFO, "user info");
170.3184 +                userInfo = substring(p, q);
170.3185 +                p = q + 1;              // Skip '@'
170.3186 +            }
170.3187 +
170.3188 +            // hostname, IPv4 address, or IPv6 address
170.3189 +            if (at(p, n, '[')) {
170.3190 +                // DEVIATION from RFC2396: Support IPv6 addresses, per RFC2732
170.3191 +                p++;
170.3192 +                q = scan(p, n, "/?#", "]");
170.3193 +                if ((q > p) && at(q, n, ']')) {
170.3194 +                    // look for a "%" scope id
170.3195 +                    int r = scan (p, q, "", "%");
170.3196 +                    if (r > p) {
170.3197 +                        parseIPv6Reference(p, r);
170.3198 +                        if (r+1 == q) {
170.3199 +                            fail ("scope id expected");
170.3200 +                        }
170.3201 +                        checkChars (r+1, q, L_ALPHANUM, H_ALPHANUM,
170.3202 +                                                "scope id");
170.3203 +                    } else {
170.3204 +                        parseIPv6Reference(p, q);
170.3205 +                    }
170.3206 +                    host = substring(p-1, q+1);
170.3207 +                    p = q + 1;
170.3208 +                } else {
170.3209 +                    failExpecting("closing bracket for IPv6 address", q);
170.3210 +                }
170.3211 +            } else {
170.3212 +                q = parseIPv4Address(p, n);
170.3213 +                if (q <= p)
170.3214 +                    q = parseHostname(p, n);
170.3215 +                p = q;
170.3216 +            }
170.3217 +
170.3218 +            // port
170.3219 +            if (at(p, n, ':')) {
170.3220 +                p++;
170.3221 +                q = scan(p, n, "", "/");
170.3222 +                if (q > p) {
170.3223 +                    checkChars(p, q, L_DIGIT, H_DIGIT, "port number");
170.3224 +                    try {
170.3225 +                        port = Integer.parseInt(substring(p, q));
170.3226 +                    } catch (NumberFormatException x) {
170.3227 +                        fail("Malformed port number", p);
170.3228 +                    }
170.3229 +                    p = q;
170.3230 +                }
170.3231 +            }
170.3232 +            if (p < n)
170.3233 +                failExpecting("port number", p);
170.3234 +
170.3235 +            return p;
170.3236 +        }
170.3237 +
170.3238 +        // Scan a string of decimal digits whose value fits in a byte
170.3239 +        //
170.3240 +        private int scanByte(int start, int n)
170.3241 +            throws URISyntaxException
170.3242 +        {
170.3243 +            int p = start;
170.3244 +            int q = scan(p, n, L_DIGIT, H_DIGIT);
170.3245 +            if (q <= p) return q;
170.3246 +            if (Integer.parseInt(substring(p, q)) > 255) return p;
170.3247 +            return q;
170.3248 +        }
170.3249 +
170.3250 +        // Scan an IPv4 address.
170.3251 +        //
170.3252 +        // If the strict argument is true then we require that the given
170.3253 +        // interval contain nothing besides an IPv4 address; if it is false
170.3254 +        // then we only require that it start with an IPv4 address.
170.3255 +        //
170.3256 +        // If the interval does not contain or start with (depending upon the
170.3257 +        // strict argument) a legal IPv4 address characters then we return -1
170.3258 +        // immediately; otherwise we insist that these characters parse as a
170.3259 +        // legal IPv4 address and throw an exception on failure.
170.3260 +        //
170.3261 +        // We assume that any string of decimal digits and dots must be an IPv4
170.3262 +        // address.  It won't parse as a hostname anyway, so making that
170.3263 +        // assumption here allows more meaningful exceptions to be thrown.
170.3264 +        //
170.3265 +        private int scanIPv4Address(int start, int n, boolean strict)
170.3266 +            throws URISyntaxException
170.3267 +        {
170.3268 +            int p = start;
170.3269 +            int q;
170.3270 +            int m = scan(p, n, L_DIGIT | L_DOT, H_DIGIT | H_DOT);
170.3271 +            if ((m <= p) || (strict && (m != n)))
170.3272 +                return -1;
170.3273 +            for (;;) {
170.3274 +                // Per RFC2732: At most three digits per byte
170.3275 +                // Further constraint: Each element fits in a byte
170.3276 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
170.3277 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
170.3278 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
170.3279 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
170.3280 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
170.3281 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
170.3282 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
170.3283 +                if (q < m) break;
170.3284 +                return q;
170.3285 +            }
170.3286 +            fail("Malformed IPv4 address", q);
170.3287 +            return -1;
170.3288 +        }
170.3289 +
170.3290 +        // Take an IPv4 address: Throw an exception if the given interval
170.3291 +        // contains anything except an IPv4 address
170.3292 +        //
170.3293 +        private int takeIPv4Address(int start, int n, String expected)
170.3294 +            throws URISyntaxException
170.3295 +        {
170.3296 +            int p = scanIPv4Address(start, n, true);
170.3297 +            if (p <= start)
170.3298 +                failExpecting(expected, start);
170.3299 +            return p;
170.3300 +        }
170.3301 +
170.3302 +        // Attempt to parse an IPv4 address, returning -1 on failure but
170.3303 +        // allowing the given interval to contain [:<characters>] after
170.3304 +        // the IPv4 address.
170.3305 +        //
170.3306 +        private int parseIPv4Address(int start, int n) {
170.3307 +            int p;
170.3308 +
170.3309 +            try {
170.3310 +                p = scanIPv4Address(start, n, false);
170.3311 +            } catch (URISyntaxException x) {
170.3312 +                return -1;
170.3313 +            } catch (NumberFormatException nfe) {
170.3314 +                return -1;
170.3315 +            }
170.3316 +
170.3317 +            if (p > start && p < n) {
170.3318 +                // IPv4 address is followed by something - check that
170.3319 +                // it's a ":" as this is the only valid character to
170.3320 +                // follow an address.
170.3321 +                if (charAt(p) != ':') {
170.3322 +                    p = -1;
170.3323 +                }
170.3324 +            }
170.3325 +
170.3326 +            if (p > start)
170.3327 +                host = substring(start, p);
170.3328 +
170.3329 +            return p;
170.3330 +        }
170.3331 +
170.3332 +        // hostname      = domainlabel [ "." ] | 1*( domainlabel "." ) toplabel [ "." ]
170.3333 +        // domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
170.3334 +        // toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
170.3335 +        //
170.3336 +        private int parseHostname(int start, int n)
170.3337 +            throws URISyntaxException
170.3338 +        {
170.3339 +            int p = start;
170.3340 +            int q;
170.3341 +            int l = -1;                 // Start of last parsed label
170.3342 +
170.3343 +            do {
170.3344 +                // domainlabel = alphanum [ *( alphanum | "-" ) alphanum ]
170.3345 +                q = scan(p, n, L_ALPHANUM, H_ALPHANUM);
170.3346 +                if (q <= p)
170.3347 +                    break;
170.3348 +                l = p;
170.3349 +                if (q > p) {
170.3350 +                    p = q;
170.3351 +                    q = scan(p, n, L_ALPHANUM | L_DASH, H_ALPHANUM | H_DASH);
170.3352 +                    if (q > p) {
170.3353 +                        if (charAt(q - 1) == '-')
170.3354 +                            fail("Illegal character in hostname", q - 1);
170.3355 +                        p = q;
170.3356 +                    }
170.3357 +                }
170.3358 +                q = scan(p, n, '.');
170.3359 +                if (q <= p)
170.3360 +                    break;
170.3361 +                p = q;
170.3362 +            } while (p < n);
170.3363 +
170.3364 +            if ((p < n) && !at(p, n, ':'))
170.3365 +                fail("Illegal character in hostname", p);
170.3366 +
170.3367 +            if (l < 0)
170.3368 +                failExpecting("hostname", start);
170.3369 +
170.3370 +            // for a fully qualified hostname check that the rightmost
170.3371 +            // label starts with an alpha character.
170.3372 +            if (l > start && !match(charAt(l), L_ALPHA, H_ALPHA)) {
170.3373 +                fail("Illegal character in hostname", l);
170.3374 +            }
170.3375 +
170.3376 +            host = substring(start, p);
170.3377 +            return p;
170.3378 +        }
170.3379 +
170.3380 +
170.3381 +        // IPv6 address parsing, from RFC2373: IPv6 Addressing Architecture
170.3382 +        //
170.3383 +        // Bug: The grammar in RFC2373 Appendix B does not allow addresses of
170.3384 +        // the form ::12.34.56.78, which are clearly shown in the examples
170.3385 +        // earlier in the document.  Here is the original grammar:
170.3386 +        //
170.3387 +        //   IPv6address = hexpart [ ":" IPv4address ]
170.3388 +        //   hexpart     = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
170.3389 +        //   hexseq      = hex4 *( ":" hex4)
170.3390 +        //   hex4        = 1*4HEXDIG
170.3391 +        //
170.3392 +        // We therefore use the following revised grammar:
170.3393 +        //
170.3394 +        //   IPv6address = hexseq [ ":" IPv4address ]
170.3395 +        //                 | hexseq [ "::" [ hexpost ] ]
170.3396 +        //                 | "::" [ hexpost ]
170.3397 +        //   hexpost     = hexseq | hexseq ":" IPv4address | IPv4address
170.3398 +        //   hexseq      = hex4 *( ":" hex4)
170.3399 +        //   hex4        = 1*4HEXDIG
170.3400 +        //
170.3401 +        // This covers all and only the following cases:
170.3402 +        //
170.3403 +        //   hexseq
170.3404 +        //   hexseq : IPv4address
170.3405 +        //   hexseq ::
170.3406 +        //   hexseq :: hexseq
170.3407 +        //   hexseq :: hexseq : IPv4address
170.3408 +        //   hexseq :: IPv4address
170.3409 +        //   :: hexseq
170.3410 +        //   :: hexseq : IPv4address
170.3411 +        //   :: IPv4address
170.3412 +        //   ::
170.3413 +        //
170.3414 +        // Additionally we constrain the IPv6 address as follows :-
170.3415 +        //
170.3416 +        //  i.  IPv6 addresses without compressed zeros should contain
170.3417 +        //      exactly 16 bytes.
170.3418 +        //
170.3419 +        //  ii. IPv6 addresses with compressed zeros should contain
170.3420 +        //      less than 16 bytes.
170.3421 +
170.3422 +        private int ipv6byteCount = 0;
170.3423 +
170.3424 +        private int parseIPv6Reference(int start, int n)
170.3425 +            throws URISyntaxException
170.3426 +        {
170.3427 +            int p = start;
170.3428 +            int q;
170.3429 +            boolean compressedZeros = false;
170.3430 +
170.3431 +            q = scanHexSeq(p, n);
170.3432 +
170.3433 +            if (q > p) {
170.3434 +                p = q;
170.3435 +                if (at(p, n, "::")) {
170.3436 +                    compressedZeros = true;
170.3437 +                    p = scanHexPost(p + 2, n);
170.3438 +                } else if (at(p, n, ':')) {
170.3439 +                    p = takeIPv4Address(p + 1,  n, "IPv4 address");
170.3440 +                    ipv6byteCount += 4;
170.3441 +                }
170.3442 +            } else if (at(p, n, "::")) {
170.3443 +                compressedZeros = true;
170.3444 +                p = scanHexPost(p + 2, n);
170.3445 +            }
170.3446 +            if (p < n)
170.3447 +                fail("Malformed IPv6 address", start);
170.3448 +            if (ipv6byteCount > 16)
170.3449 +                fail("IPv6 address too long", start);
170.3450 +            if (!compressedZeros && ipv6byteCount < 16)
170.3451 +                fail("IPv6 address too short", start);
170.3452 +            if (compressedZeros && ipv6byteCount == 16)
170.3453 +                fail("Malformed IPv6 address", start);
170.3454 +
170.3455 +            return p;
170.3456 +        }
170.3457 +
170.3458 +        private int scanHexPost(int start, int n)
170.3459 +            throws URISyntaxException
170.3460 +        {
170.3461 +            int p = start;
170.3462 +            int q;
170.3463 +
170.3464 +            if (p == n)
170.3465 +                return p;
170.3466 +
170.3467 +            q = scanHexSeq(p, n);
170.3468 +            if (q > p) {
170.3469 +                p = q;
170.3470 +                if (at(p, n, ':')) {
170.3471 +                    p++;
170.3472 +                    p = takeIPv4Address(p, n, "hex digits or IPv4 address");
170.3473 +                    ipv6byteCount += 4;
170.3474 +                }
170.3475 +            } else {
170.3476 +                p = takeIPv4Address(p, n, "hex digits or IPv4 address");
170.3477 +                ipv6byteCount += 4;
170.3478 +            }
170.3479 +            return p;
170.3480 +        }
170.3481 +
170.3482 +        // Scan a hex sequence; return -1 if one could not be scanned
170.3483 +        //
170.3484 +        private int scanHexSeq(int start, int n)
170.3485 +            throws URISyntaxException
170.3486 +        {
170.3487 +            int p = start;
170.3488 +            int q;
170.3489 +
170.3490 +            q = scan(p, n, L_HEX, H_HEX);
170.3491 +            if (q <= p)
170.3492 +                return -1;
170.3493 +            if (at(q, n, '.'))          // Beginning of IPv4 address
170.3494 +                return -1;
170.3495 +            if (q > p + 4)
170.3496 +                fail("IPv6 hexadecimal digit sequence too long", p);
170.3497 +            ipv6byteCount += 2;
170.3498 +            p = q;
170.3499 +            while (p < n) {
170.3500 +                if (!at(p, n, ':'))
170.3501 +                    break;
170.3502 +                if (at(p + 1, n, ':'))
170.3503 +                    break;              // "::"
170.3504 +                p++;
170.3505 +                q = scan(p, n, L_HEX, H_HEX);
170.3506 +                if (q <= p)
170.3507 +                    failExpecting("digits for an IPv6 address", p);
170.3508 +                if (at(q, n, '.')) {    // Beginning of IPv4 address
170.3509 +                    p--;
170.3510 +                    break;
170.3511 +                }
170.3512 +                if (q > p + 4)
170.3513 +                    fail("IPv6 hexadecimal digit sequence too long", p);
170.3514 +                ipv6byteCount += 2;
170.3515 +                p = q;
170.3516 +            }
170.3517 +
170.3518 +            return p;
170.3519 +        }
170.3520 +
170.3521 +    }
170.3522 +
170.3523 +}
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/rt/emul/compact/src/main/java/java/net/URISyntaxException.java	Wed Apr 30 15:04:10 2014 +0200
   171.3 @@ -0,0 +1,135 @@
   171.4 +/*
   171.5 + * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
   171.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   171.7 + *
   171.8 + * This code is free software; you can redistribute it and/or modify it
   171.9 + * under the terms of the GNU General Public License version 2 only, as
  171.10 + * published by the Free Software Foundation.  Oracle designates this
  171.11 + * particular file as subject to the "Classpath" exception as provided
  171.12 + * by Oracle in the LICENSE file that accompanied this code.
  171.13 + *
  171.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  171.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  171.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  171.17 + * version 2 for more details (a copy is included in the LICENSE file that
  171.18 + * accompanied this code).
  171.19 + *
  171.20 + * You should have received a copy of the GNU General Public License version
  171.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  171.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  171.23 + *
  171.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  171.25 + * or visit www.oracle.com if you need additional information or have any
  171.26 + * questions.
  171.27 + */
  171.28 +
  171.29 +package java.net;
  171.30 +
  171.31 +
  171.32 +/**
  171.33 + * Checked exception thrown to indicate that a string could not be parsed as a
  171.34 + * URI reference.
  171.35 + *
  171.36 + * @author Mark Reinhold
  171.37 + * @see URI
  171.38 + * @since 1.4
  171.39 + */
  171.40 +
  171.41 +public class URISyntaxException
  171.42 +    extends Exception
  171.43 +{
  171.44 +    private static final long serialVersionUID = 2137979680897488891L;
  171.45 +
  171.46 +    private String input;
  171.47 +    private int index;
  171.48 +
  171.49 +    /**
  171.50 +     * Constructs an instance from the given input string, reason, and error
  171.51 +     * index.
  171.52 +     *
  171.53 +     * @param  input   The input string
  171.54 +     * @param  reason  A string explaining why the input could not be parsed
  171.55 +     * @param  index   The index at which the parse error occurred,
  171.56 +     *                 or <tt>-1</tt> if the index is not known
  171.57 +     *
  171.58 +     * @throws  NullPointerException
  171.59 +     *          If either the input or reason strings are <tt>null</tt>
  171.60 +     *
  171.61 +     * @throws  IllegalArgumentException
  171.62 +     *          If the error index is less than <tt>-1</tt>
  171.63 +     */
  171.64 +    public URISyntaxException(String input, String reason, int index) {
  171.65 +        super(reason);
  171.66 +        if ((input == null) || (reason == null))
  171.67 +            throw new NullPointerException();
  171.68 +        if (index < -1)
  171.69 +            throw new IllegalArgumentException();
  171.70 +        this.input = input;
  171.71 +        this.index = index;
  171.72 +    }
  171.73 +
  171.74 +    /**
  171.75 +     * Constructs an instance from the given input string and reason.  The
  171.76 +     * resulting object will have an error index of <tt>-1</tt>.
  171.77 +     *
  171.78 +     * @param  input   The input string
  171.79 +     * @param  reason  A string explaining why the input could not be parsed
  171.80 +     *
  171.81 +     * @throws  NullPointerException
  171.82 +     *          If either the input or reason strings are <tt>null</tt>
  171.83 +     */
  171.84 +    public URISyntaxException(String input, String reason) {
  171.85 +        this(input, reason, -1);
  171.86 +    }
  171.87 +
  171.88 +    /**
  171.89 +     * Returns the input string.
  171.90 +     *
  171.91 +     * @return  The input string
  171.92 +     */
  171.93 +    public String getInput() {
  171.94 +        return input;
  171.95 +    }
  171.96 +
  171.97 +    /**
  171.98 +     * Returns a string explaining why the input string could not be parsed.
  171.99 +     *
 171.100 +     * @return  The reason string
 171.101 +     */
 171.102 +    public String getReason() {
 171.103 +        return super.getMessage();
 171.104 +    }
 171.105 +
 171.106 +    /**
 171.107 +     * Returns an index into the input string of the position at which the
 171.108 +     * parse error occurred, or <tt>-1</tt> if this position is not known.
 171.109 +     *
 171.110 +     * @return  The error index
 171.111 +     */
 171.112 +    public int getIndex() {
 171.113 +        return index;
 171.114 +    }
 171.115 +
 171.116 +    /**
 171.117 +     * Returns a string describing the parse error.  The resulting string
 171.118 +     * consists of the reason string followed by a colon character
 171.119 +     * (<tt>':'</tt>), a space, and the input string.  If the error index is
 171.120 +     * defined then the string <tt>" at index "</tt> followed by the index, in
 171.121 +     * decimal, is inserted after the reason string and before the colon
 171.122 +     * character.
 171.123 +     *
 171.124 +     * @return  A string describing the parse error
 171.125 +     */
 171.126 +    public String getMessage() {
 171.127 +        StringBuffer sb = new StringBuffer();
 171.128 +        sb.append(getReason());
 171.129 +        if (index > -1) {
 171.130 +            sb.append(" at index ");
 171.131 +            sb.append(index);
 171.132 +        }
 171.133 +        sb.append(": ");
 171.134 +        sb.append(input);
 171.135 +        return sb.toString();
 171.136 +    }
 171.137 +
 171.138 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/rt/emul/compact/src/main/java/java/net/URLConnection.java	Wed Apr 30 15:04:10 2014 +0200
   172.3 @@ -0,0 +1,2314 @@
   172.4 +/*
   172.5 + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
   172.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   172.7 + *
   172.8 + * This code is free software; you can redistribute it and/or modify it
   172.9 + * under the terms of the GNU General Public License version 2 only, as
  172.10 + * published by the Free Software Foundation.  Oracle designates this
  172.11 + * particular file as subject to the "Classpath" exception as provided
  172.12 + * by Oracle in the LICENSE file that accompanied this code.
  172.13 + *
  172.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  172.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  172.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  172.17 + * version 2 for more details (a copy is included in the LICENSE file that
  172.18 + * accompanied this code).
  172.19 + *
  172.20 + * You should have received a copy of the GNU General Public License version
  172.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  172.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  172.23 + *
  172.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  172.25 + * or visit www.oracle.com if you need additional information or have any
  172.26 + * questions.
  172.27 + */
  172.28 +
  172.29 +package java.net;
  172.30 +
  172.31 +import java.io.IOException;
  172.32 +import java.io.InputStream;
  172.33 +import java.io.OutputStream;
  172.34 +import java.io.PrintStream;
  172.35 +import java.util.ArrayList;
  172.36 +import java.util.Date;
  172.37 +import java.util.StringTokenizer;
  172.38 +import java.util.Collections;
  172.39 +import java.util.HashMap;
  172.40 +import java.util.Hashtable;
  172.41 +import java.util.Iterator;
  172.42 +import java.util.Map;
  172.43 +import java.util.List;
  172.44 +import java.util.NoSuchElementException;
  172.45 +
  172.46 +/**
  172.47 + * The abstract class <code>URLConnection</code> is the superclass
  172.48 + * of all classes that represent a communications link between the
  172.49 + * application and a URL. Instances of this class can be used both to
  172.50 + * read from and to write to the resource referenced by the URL. In
  172.51 + * general, creating a connection to a URL is a multistep process:
  172.52 + * <p>
  172.53 + * <center><table border=2 summary="Describes the process of creating a connection to a URL: openConnection() and connect() over time.">
  172.54 + * <tr><th><code>openConnection()</code></th>
  172.55 + *     <th><code>connect()</code></th></tr>
  172.56 + * <tr><td>Manipulate parameters that affect the connection to the remote
  172.57 + *         resource.</td>
  172.58 + *     <td>Interact with the resource; query header fields and
  172.59 + *         contents.</td></tr>
  172.60 + * </table>
  172.61 + * ----------------------------&gt;
  172.62 + * <br>time</center>
  172.63 + *
  172.64 + * <ol>
  172.65 + * <li>The connection object is created by invoking the
  172.66 + *     <code>openConnection</code> method on a URL.
  172.67 + * <li>The setup parameters and general request properties are manipulated.
  172.68 + * <li>The actual connection to the remote object is made, using the
  172.69 + *    <code>connect</code> method.
  172.70 + * <li>The remote object becomes available. The header fields and the contents
  172.71 + *     of the remote object can be accessed.
  172.72 + * </ol>
  172.73 + * <p>
  172.74 + * The setup parameters are modified using the following methods:
  172.75 + * <ul>
  172.76 + *   <li><code>setAllowUserInteraction</code>
  172.77 + *   <li><code>setDoInput</code>
  172.78 + *   <li><code>setDoOutput</code>
  172.79 + *   <li><code>setIfModifiedSince</code>
  172.80 + *   <li><code>setUseCaches</code>
  172.81 + * </ul>
  172.82 + * <p>
  172.83 + * and the general request properties are modified using the method:
  172.84 + * <ul>
  172.85 + *   <li><code>setRequestProperty</code>
  172.86 + * </ul>
  172.87 + * <p>
  172.88 + * Default values for the <code>AllowUserInteraction</code> and
  172.89 + * <code>UseCaches</code> parameters can be set using the methods
  172.90 + * <code>setDefaultAllowUserInteraction</code> and
  172.91 + * <code>setDefaultUseCaches</code>.
  172.92 + * <p>
  172.93 + * Each of the above <code>set</code> methods has a corresponding
  172.94 + * <code>get</code> method to retrieve the value of the parameter or
  172.95 + * general request property. The specific parameters and general
  172.96 + * request properties that are applicable are protocol specific.
  172.97 + * <p>
  172.98 + * The following methods are used to access the header fields and
  172.99 + * the contents after the connection is made to the remote object:
 172.100 + * <ul>
 172.101 + *   <li><code>getContent</code>
 172.102 + *   <li><code>getHeaderField</code>
 172.103 + *   <li><code>getInputStream</code>
 172.104 + *   <li><code>getOutputStream</code>
 172.105 + * </ul>
 172.106 + * <p>
 172.107 + * Certain header fields are accessed frequently. The methods:
 172.108 + * <ul>
 172.109 + *   <li><code>getContentEncoding</code>
 172.110 + *   <li><code>getContentLength</code>
 172.111 + *   <li><code>getContentType</code>
 172.112 + *   <li><code>getDate</code>
 172.113 + *   <li><code>getExpiration</code>
 172.114 + *   <li><code>getLastModifed</code>
 172.115 + * </ul>
 172.116 + * <p>
 172.117 + * provide convenient access to these fields. The
 172.118 + * <code>getContentType</code> method is used by the
 172.119 + * <code>getContent</code> method to determine the type of the remote
 172.120 + * object; subclasses may find it convenient to override the
 172.121 + * <code>getContentType</code> method.
 172.122 + * <p>
 172.123 + * In the common case, all of the pre-connection parameters and
 172.124 + * general request properties can be ignored: the pre-connection
 172.125 + * parameters and request properties default to sensible values. For
 172.126 + * most clients of this interface, there are only two interesting
 172.127 + * methods: <code>getInputStream</code> and <code>getContent</code>,
 172.128 + * which are mirrored in the <code>URL</code> class by convenience methods.
 172.129 + * <p>
 172.130 + * More information on the request properties and header fields of
 172.131 + * an <code>http</code> connection can be found at:
 172.132 + * <blockquote><pre>
 172.133 + * <a href="http://www.ietf.org/rfc/rfc2616.txt">http://www.ietf.org/rfc/rfc2616.txt</a>
 172.134 + * </pre></blockquote>
 172.135 + *
 172.136 + * Note about <code>fileNameMap</code>: In versions prior to JDK 1.1.6,
 172.137 + * field <code>fileNameMap</code> of <code>URLConnection</code> was public.
 172.138 + * In JDK 1.1.6 and later, <code>fileNameMap</code> is private; accessor
 172.139 + * and mutator methods {@link #getFileNameMap() getFileNameMap} and
 172.140 + * {@link #setFileNameMap(java.net.FileNameMap) setFileNameMap} are added
 172.141 + * to access it.  This change is also described on the <a href=
 172.142 + * "http://java.sun.com/products/jdk/1.2/compatibility.html">
 172.143 + * Compatibility</a> page.
 172.144 + *
 172.145 + * Invoking the <tt>close()</tt> methods on the <tt>InputStream</tt> or <tt>OutputStream</tt> of an
 172.146 + * <tt>URLConnection</tt> after a request may free network resources associated with this
 172.147 + * instance, unless particular protocol specifications specify different behaviours
 172.148 + * for it.
 172.149 + *
 172.150 + * @author  James Gosling
 172.151 + * @see     java.net.URL#openConnection()
 172.152 + * @see     java.net.URLConnection#connect()
 172.153 + * @see     java.net.URLConnection#getContent()
 172.154 + * @see     java.net.URLConnection#getContentEncoding()
 172.155 + * @see     java.net.URLConnection#getContentLength()
 172.156 + * @see     java.net.URLConnection#getContentType()
 172.157 + * @see     java.net.URLConnection#getDate()
 172.158 + * @see     java.net.URLConnection#getExpiration()
 172.159 + * @see     java.net.URLConnection#getHeaderField(int)
 172.160 + * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.161 + * @see     java.net.URLConnection#getInputStream()
 172.162 + * @see     java.net.URLConnection#getLastModified()
 172.163 + * @see     java.net.URLConnection#getOutputStream()
 172.164 + * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
 172.165 + * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
 172.166 + * @see     java.net.URLConnection#setDoInput(boolean)
 172.167 + * @see     java.net.URLConnection#setDoOutput(boolean)
 172.168 + * @see     java.net.URLConnection#setIfModifiedSince(long)
 172.169 + * @see     java.net.URLConnection#setRequestProperty(java.lang.String, java.lang.String)
 172.170 + * @see     java.net.URLConnection#setUseCaches(boolean)
 172.171 + * @since   JDK1.0
 172.172 + */
 172.173 +public abstract class URLConnection {
 172.174 +
 172.175 +   /**
 172.176 +     * The URL represents the remote object on the World Wide Web to
 172.177 +     * which this connection is opened.
 172.178 +     * <p>
 172.179 +     * The value of this field can be accessed by the
 172.180 +     * <code>getURL</code> method.
 172.181 +     * <p>
 172.182 +     * The default value of this variable is the value of the URL
 172.183 +     * argument in the <code>URLConnection</code> constructor.
 172.184 +     *
 172.185 +     * @see     java.net.URLConnection#getURL()
 172.186 +     * @see     java.net.URLConnection#url
 172.187 +     */
 172.188 +    protected URL url;
 172.189 +
 172.190 +   /**
 172.191 +     * This variable is set by the <code>setDoInput</code> method. Its
 172.192 +     * value is returned by the <code>getDoInput</code> method.
 172.193 +     * <p>
 172.194 +     * A URL connection can be used for input and/or output. Setting the
 172.195 +     * <code>doInput</code> flag to <code>true</code> indicates that
 172.196 +     * the application intends to read data from the URL connection.
 172.197 +     * <p>
 172.198 +     * The default value of this field is <code>true</code>.
 172.199 +     *
 172.200 +     * @see     java.net.URLConnection#getDoInput()
 172.201 +     * @see     java.net.URLConnection#setDoInput(boolean)
 172.202 +     */
 172.203 +    protected boolean doInput = true;
 172.204 +
 172.205 +   /**
 172.206 +     * This variable is set by the <code>setDoOutput</code> method. Its
 172.207 +     * value is returned by the <code>getDoOutput</code> method.
 172.208 +     * <p>
 172.209 +     * A URL connection can be used for input and/or output. Setting the
 172.210 +     * <code>doOutput</code> flag to <code>true</code> indicates
 172.211 +     * that the application intends to write data to the URL connection.
 172.212 +     * <p>
 172.213 +     * The default value of this field is <code>false</code>.
 172.214 +     *
 172.215 +     * @see     java.net.URLConnection#getDoOutput()
 172.216 +     * @see     java.net.URLConnection#setDoOutput(boolean)
 172.217 +     */
 172.218 +    protected boolean doOutput = false;
 172.219 +
 172.220 +    private static boolean defaultAllowUserInteraction = false;
 172.221 +
 172.222 +   /**
 172.223 +     * If <code>true</code>, this <code>URL</code> is being examined in
 172.224 +     * a context in which it makes sense to allow user interactions such
 172.225 +     * as popping up an authentication dialog. If <code>false</code>,
 172.226 +     * then no user interaction is allowed.
 172.227 +     * <p>
 172.228 +     * The value of this field can be set by the
 172.229 +     * <code>setAllowUserInteraction</code> method.
 172.230 +     * Its value is returned by the
 172.231 +     * <code>getAllowUserInteraction</code> method.
 172.232 +     * Its default value is the value of the argument in the last invocation
 172.233 +     * of the <code>setDefaultAllowUserInteraction</code> method.
 172.234 +     *
 172.235 +     * @see     java.net.URLConnection#getAllowUserInteraction()
 172.236 +     * @see     java.net.URLConnection#setAllowUserInteraction(boolean)
 172.237 +     * @see     java.net.URLConnection#setDefaultAllowUserInteraction(boolean)
 172.238 +     */
 172.239 +    protected boolean allowUserInteraction = defaultAllowUserInteraction;
 172.240 +
 172.241 +    private static boolean defaultUseCaches = true;
 172.242 +
 172.243 +   /**
 172.244 +     * If <code>true</code>, the protocol is allowed to use caching
 172.245 +     * whenever it can. If <code>false</code>, the protocol must always
 172.246 +     * try to get a fresh copy of the object.
 172.247 +     * <p>
 172.248 +     * This field is set by the <code>setUseCaches</code> method. Its
 172.249 +     * value is returned by the <code>getUseCaches</code> method.
 172.250 +     * <p>
 172.251 +     * Its default value is the value given in the last invocation of the
 172.252 +     * <code>setDefaultUseCaches</code> method.
 172.253 +     *
 172.254 +     * @see     java.net.URLConnection#setUseCaches(boolean)
 172.255 +     * @see     java.net.URLConnection#getUseCaches()
 172.256 +     * @see     java.net.URLConnection#setDefaultUseCaches(boolean)
 172.257 +     */
 172.258 +    protected boolean useCaches = defaultUseCaches;
 172.259 +
 172.260 +   /**
 172.261 +     * Some protocols support skipping the fetching of the object unless
 172.262 +     * the object has been modified more recently than a certain time.
 172.263 +     * <p>
 172.264 +     * A nonzero value gives a time as the number of milliseconds since
 172.265 +     * January 1, 1970, GMT. The object is fetched only if it has been
 172.266 +     * modified more recently than that time.
 172.267 +     * <p>
 172.268 +     * This variable is set by the <code>setIfModifiedSince</code>
 172.269 +     * method. Its value is returned by the
 172.270 +     * <code>getIfModifiedSince</code> method.
 172.271 +     * <p>
 172.272 +     * The default value of this field is <code>0</code>, indicating
 172.273 +     * that the fetching must always occur.
 172.274 +     *
 172.275 +     * @see     java.net.URLConnection#getIfModifiedSince()
 172.276 +     * @see     java.net.URLConnection#setIfModifiedSince(long)
 172.277 +     */
 172.278 +    protected long ifModifiedSince = 0;
 172.279 +
 172.280 +   /**
 172.281 +     * If <code>false</code>, this connection object has not created a
 172.282 +     * communications link to the specified URL. If <code>true</code>,
 172.283 +     * the communications link has been established.
 172.284 +     */
 172.285 +    protected boolean connected = false;
 172.286 +
 172.287 +    /**
 172.288 +     * @since 1.5
 172.289 +     */
 172.290 +    private int connectTimeout;
 172.291 +    private int readTimeout;
 172.292 +
 172.293 +    /**
 172.294 +     * @since 1.6
 172.295 +     */
 172.296 +    private MessageHeader requests;
 172.297 +
 172.298 +   /**
 172.299 +    * @since   JDK1.1
 172.300 +    */
 172.301 +    private static FileNameMap fileNameMap;
 172.302 +
 172.303 +    /**
 172.304 +     * @since 1.2.2
 172.305 +     */
 172.306 +    private static boolean fileNameMapLoaded = false;
 172.307 +
 172.308 +    /**
 172.309 +     * Loads filename map (a mimetable) from a data file. It will
 172.310 +     * first try to load the user-specific table, defined
 172.311 +     * by &quot;content.types.user.table&quot; property. If that fails,
 172.312 +     * it tries to load the default built-in table at
 172.313 +     * lib/content-types.properties under java home.
 172.314 +     *
 172.315 +     * @return the FileNameMap
 172.316 +     * @since 1.2
 172.317 +     * @see #setFileNameMap(java.net.FileNameMap)
 172.318 +     */
 172.319 +    public static synchronized FileNameMap getFileNameMap() {
 172.320 +        if ((fileNameMap == null) && !fileNameMapLoaded) {
 172.321 +            fileNameMap = new FileNameMap() {
 172.322 +                @Override
 172.323 +                public String getContentTypeFor(String fileName) {
 172.324 +                    return "text/plain";
 172.325 +                }
 172.326 +            };
 172.327 +            fileNameMapLoaded = true;
 172.328 +        }
 172.329 +
 172.330 +        return new FileNameMap() {
 172.331 +            private FileNameMap map = fileNameMap;
 172.332 +            public String getContentTypeFor(String fileName) {
 172.333 +                return map.getContentTypeFor(fileName);
 172.334 +            }
 172.335 +        };
 172.336 +    }
 172.337 +
 172.338 +    /**
 172.339 +     * Sets the FileNameMap.
 172.340 +     * <p>
 172.341 +     * If there is a security manager, this method first calls
 172.342 +     * the security manager's <code>checkSetFactory</code> method
 172.343 +     * to ensure the operation is allowed.
 172.344 +     * This could result in a SecurityException.
 172.345 +     *
 172.346 +     * @param map the FileNameMap to be set
 172.347 +     * @exception  SecurityException  if a security manager exists and its
 172.348 +     *             <code>checkSetFactory</code> method doesn't allow the operation.
 172.349 +     * @see        SecurityManager#checkSetFactory
 172.350 +     * @see #getFileNameMap()
 172.351 +     * @since 1.2
 172.352 +     */
 172.353 +    public static void setFileNameMap(FileNameMap map) {
 172.354 +        throw new SecurityException();
 172.355 +    }
 172.356 +
 172.357 +    /**
 172.358 +     * Opens a communications link to the resource referenced by this
 172.359 +     * URL, if such a connection has not already been established.
 172.360 +     * <p>
 172.361 +     * If the <code>connect</code> method is called when the connection
 172.362 +     * has already been opened (indicated by the <code>connected</code>
 172.363 +     * field having the value <code>true</code>), the call is ignored.
 172.364 +     * <p>
 172.365 +     * URLConnection objects go through two phases: first they are
 172.366 +     * created, then they are connected.  After being created, and
 172.367 +     * before being connected, various options can be specified
 172.368 +     * (e.g., doInput and UseCaches).  After connecting, it is an
 172.369 +     * error to try to set them.  Operations that depend on being
 172.370 +     * connected, like getContentLength, will implicitly perform the
 172.371 +     * connection, if necessary.
 172.372 +     *
 172.373 +     * @throws SocketTimeoutException if the timeout expires before
 172.374 +     *               the connection can be established
 172.375 +     * @exception  IOException  if an I/O error occurs while opening the
 172.376 +     *               connection.
 172.377 +     * @see java.net.URLConnection#connected
 172.378 +     * @see #getConnectTimeout()
 172.379 +     * @see #setConnectTimeout(int)
 172.380 +     */
 172.381 +    abstract public void connect() throws IOException;
 172.382 +
 172.383 +    /**
 172.384 +     * Sets a specified timeout value, in milliseconds, to be used
 172.385 +     * when opening a communications link to the resource referenced
 172.386 +     * by this URLConnection.  If the timeout expires before the
 172.387 +     * connection can be established, a
 172.388 +     * java.net.SocketTimeoutException is raised. A timeout of zero is
 172.389 +     * interpreted as an infinite timeout.
 172.390 +
 172.391 +     * <p> Some non-standard implmentation of this method may ignore
 172.392 +     * the specified timeout. To see the connect timeout set, please
 172.393 +     * call getConnectTimeout().
 172.394 +     *
 172.395 +     * @param timeout an <code>int</code> that specifies the connect
 172.396 +     *               timeout value in milliseconds
 172.397 +     * @throws IllegalArgumentException if the timeout parameter is negative
 172.398 +     *
 172.399 +     * @see #getConnectTimeout()
 172.400 +     * @see #connect()
 172.401 +     * @since 1.5
 172.402 +     */
 172.403 +    public void setConnectTimeout(int timeout) {
 172.404 +        if (timeout < 0) {
 172.405 +            throw new IllegalArgumentException("timeout can not be negative");
 172.406 +        }
 172.407 +        connectTimeout = timeout;
 172.408 +    }
 172.409 +
 172.410 +    /**
 172.411 +     * Returns setting for connect timeout.
 172.412 +     * <p>
 172.413 +     * 0 return implies that the option is disabled
 172.414 +     * (i.e., timeout of infinity).
 172.415 +     *
 172.416 +     * @return an <code>int</code> that indicates the connect timeout
 172.417 +     *         value in milliseconds
 172.418 +     * @see #setConnectTimeout(int)
 172.419 +     * @see #connect()
 172.420 +     * @since 1.5
 172.421 +     */
 172.422 +    public int getConnectTimeout() {
 172.423 +        return connectTimeout;
 172.424 +    }
 172.425 +
 172.426 +    /**
 172.427 +     * Sets the read timeout to a specified timeout, in
 172.428 +     * milliseconds. A non-zero value specifies the timeout when
 172.429 +     * reading from Input stream when a connection is established to a
 172.430 +     * resource. If the timeout expires before there is data available
 172.431 +     * for read, a java.net.SocketTimeoutException is raised. A
 172.432 +     * timeout of zero is interpreted as an infinite timeout.
 172.433 +     *
 172.434 +     *<p> Some non-standard implementation of this method ignores the
 172.435 +     * specified timeout. To see the read timeout set, please call
 172.436 +     * getReadTimeout().
 172.437 +     *
 172.438 +     * @param timeout an <code>int</code> that specifies the timeout
 172.439 +     * value to be used in milliseconds
 172.440 +     * @throws IllegalArgumentException if the timeout parameter is negative
 172.441 +     *
 172.442 +     * @see #getReadTimeout()
 172.443 +     * @see InputStream#read()
 172.444 +     * @since 1.5
 172.445 +     */
 172.446 +    public void setReadTimeout(int timeout) {
 172.447 +        if (timeout < 0) {
 172.448 +            throw new IllegalArgumentException("timeout can not be negative");
 172.449 +        }
 172.450 +        readTimeout = timeout;
 172.451 +    }
 172.452 +
 172.453 +    /**
 172.454 +     * Returns setting for read timeout. 0 return implies that the
 172.455 +     * option is disabled (i.e., timeout of infinity).
 172.456 +     *
 172.457 +     * @return an <code>int</code> that indicates the read timeout
 172.458 +     *         value in milliseconds
 172.459 +     *
 172.460 +     * @see #setReadTimeout(int)
 172.461 +     * @see InputStream#read()
 172.462 +     * @since 1.5
 172.463 +     */
 172.464 +    public int getReadTimeout() {
 172.465 +        return readTimeout;
 172.466 +    }
 172.467 +
 172.468 +    /**
 172.469 +     * Constructs a URL connection to the specified URL. A connection to
 172.470 +     * the object referenced by the URL is not created.
 172.471 +     *
 172.472 +     * @param   url   the specified URL.
 172.473 +     */
 172.474 +    protected URLConnection(URL url) {
 172.475 +        this.url = url;
 172.476 +    }
 172.477 +
 172.478 +    /**
 172.479 +     * Returns the value of this <code>URLConnection</code>'s <code>URL</code>
 172.480 +     * field.
 172.481 +     *
 172.482 +     * @return  the value of this <code>URLConnection</code>'s <code>URL</code>
 172.483 +     *          field.
 172.484 +     * @see     java.net.URLConnection#url
 172.485 +     */
 172.486 +    public URL getURL() {
 172.487 +        return url;
 172.488 +    }
 172.489 +
 172.490 +    /**
 172.491 +     * Returns the value of the <code>content-length</code> header field.
 172.492 +     * <P>
 172.493 +     * <B>Note</B>: {@link #getContentLengthLong() getContentLengthLong()}
 172.494 +     * should be preferred over this method, since it returns a {@code long}
 172.495 +     * instead and is therefore more portable.</P>
 172.496 +     *
 172.497 +     * @return  the content length of the resource that this connection's URL
 172.498 +     *          references, {@code -1} if the content length is not known,
 172.499 +     *          or if the content length is greater than Integer.MAX_VALUE.
 172.500 +     */
 172.501 +    public int getContentLength() {
 172.502 +        long l = getContentLengthLong();
 172.503 +        if (l > Integer.MAX_VALUE)
 172.504 +            return -1;
 172.505 +        return (int) l;
 172.506 +    }
 172.507 +
 172.508 +    /**
 172.509 +     * Returns the value of the <code>content-length</code> header field as a
 172.510 +     * long.
 172.511 +     *
 172.512 +     * @return  the content length of the resource that this connection's URL
 172.513 +     *          references, or <code>-1</code> if the content length is
 172.514 +     *          not known.
 172.515 +     * @since 7.0
 172.516 +     */
 172.517 +    public long getContentLengthLong() {
 172.518 +        return getHeaderFieldLong("content-length", -1);
 172.519 +    }
 172.520 +
 172.521 +    /**
 172.522 +     * Returns the value of the <code>content-type</code> header field.
 172.523 +     *
 172.524 +     * @return  the content type of the resource that the URL references,
 172.525 +     *          or <code>null</code> if not known.
 172.526 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.527 +     */
 172.528 +    public String getContentType() {
 172.529 +        return getHeaderField("content-type");
 172.530 +    }
 172.531 +
 172.532 +    /**
 172.533 +     * Returns the value of the <code>content-encoding</code> header field.
 172.534 +     *
 172.535 +     * @return  the content encoding of the resource that the URL references,
 172.536 +     *          or <code>null</code> if not known.
 172.537 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.538 +     */
 172.539 +    public String getContentEncoding() {
 172.540 +        return getHeaderField("content-encoding");
 172.541 +    }
 172.542 +
 172.543 +    /**
 172.544 +     * Returns the value of the <code>expires</code> header field.
 172.545 +     *
 172.546 +     * @return  the expiration date of the resource that this URL references,
 172.547 +     *          or 0 if not known. The value is the number of milliseconds since
 172.548 +     *          January 1, 1970 GMT.
 172.549 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.550 +     */
 172.551 +    public long getExpiration() {
 172.552 +        return getHeaderFieldDate("expires", 0);
 172.553 +    }
 172.554 +
 172.555 +    /**
 172.556 +     * Returns the value of the <code>date</code> header field.
 172.557 +     *
 172.558 +     * @return  the sending date of the resource that the URL references,
 172.559 +     *          or <code>0</code> if not known. The value returned is the
 172.560 +     *          number of milliseconds since January 1, 1970 GMT.
 172.561 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.562 +     */
 172.563 +    public long getDate() {
 172.564 +        return getHeaderFieldDate("date", 0);
 172.565 +    }
 172.566 +
 172.567 +    /**
 172.568 +     * Returns the value of the <code>last-modified</code> header field.
 172.569 +     * The result is the number of milliseconds since January 1, 1970 GMT.
 172.570 +     *
 172.571 +     * @return  the date the resource referenced by this
 172.572 +     *          <code>URLConnection</code> was last modified, or 0 if not known.
 172.573 +     * @see     java.net.URLConnection#getHeaderField(java.lang.String)
 172.574 +     */
 172.575 +    public long getLastModified() {
 172.576 +        return getHeaderFieldDate("last-modified", 0);
 172.577 +    }
 172.578 +
 172.579 +    /**
 172.580 +     * Returns the value of the named header field.
 172.581 +     * <p>
 172.582 +     * If called on a connection that sets the same header multiple times
 172.583 +     * with possibly different values, only the last value is returned.
 172.584 +     *
 172.585 +     *
 172.586 +     * @param   name   the name of a header field.
 172.587 +     * @return  the value of the named header field, or <code>null</code>
 172.588 +     *          if there is no such field in the header.
 172.589 +     */
 172.590 +    public String getHeaderField(String name) {
 172.591 +        return null;
 172.592 +    }
 172.593 +
 172.594 +    /**
 172.595 +     * Returns an unmodifiable Map of the header fields.
 172.596 +     * The Map keys are Strings that represent the
 172.597 +     * response-header field names. Each Map value is an
 172.598 +     * unmodifiable List of Strings that represents
 172.599 +     * the corresponding field values.
 172.600 +     *
 172.601 +     * @return a Map of header fields
 172.602 +     * @since 1.4
 172.603 +     */
 172.604 +    public Map<String,List<String>> getHeaderFields() {
 172.605 +        return Collections.EMPTY_MAP;
 172.606 +    }
 172.607 +
 172.608 +    /**
 172.609 +     * Returns the value of the named field parsed as a number.
 172.610 +     * <p>
 172.611 +     * This form of <code>getHeaderField</code> exists because some
 172.612 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
 172.613 +     * headers. Classes for that connection type can override this method
 172.614 +     * and short-circuit the parsing.
 172.615 +     *
 172.616 +     * @param   name      the name of the header field.
 172.617 +     * @param   Default   the default value.
 172.618 +     * @return  the value of the named field, parsed as an integer. The
 172.619 +     *          <code>Default</code> value is returned if the field is
 172.620 +     *          missing or malformed.
 172.621 +     */
 172.622 +    public int getHeaderFieldInt(String name, int Default) {
 172.623 +        String value = getHeaderField(name);
 172.624 +        try {
 172.625 +            return Integer.parseInt(value);
 172.626 +        } catch (Exception e) { }
 172.627 +        return Default;
 172.628 +    }
 172.629 +
 172.630 +    /**
 172.631 +     * Returns the value of the named field parsed as a number.
 172.632 +     * <p>
 172.633 +     * This form of <code>getHeaderField</code> exists because some
 172.634 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
 172.635 +     * headers. Classes for that connection type can override this method
 172.636 +     * and short-circuit the parsing.
 172.637 +     *
 172.638 +     * @param   name      the name of the header field.
 172.639 +     * @param   Default   the default value.
 172.640 +     * @return  the value of the named field, parsed as a long. The
 172.641 +     *          <code>Default</code> value is returned if the field is
 172.642 +     *          missing or malformed.
 172.643 +     * @since 7.0
 172.644 +     */
 172.645 +    public long getHeaderFieldLong(String name, long Default) {
 172.646 +        String value = getHeaderField(name);
 172.647 +        try {
 172.648 +            return Long.parseLong(value);
 172.649 +        } catch (Exception e) { }
 172.650 +        return Default;
 172.651 +    }
 172.652 +
 172.653 +    /**
 172.654 +     * Returns the value of the named field parsed as date.
 172.655 +     * The result is the number of milliseconds since January 1, 1970 GMT
 172.656 +     * represented by the named field.
 172.657 +     * <p>
 172.658 +     * This form of <code>getHeaderField</code> exists because some
 172.659 +     * connection types (e.g., <code>http-ng</code>) have pre-parsed
 172.660 +     * headers. Classes for that connection type can override this method
 172.661 +     * and short-circuit the parsing.
 172.662 +     *
 172.663 +     * @param   name     the name of the header field.
 172.664 +     * @param   Default   a default value.
 172.665 +     * @return  the value of the field, parsed as a date. The value of the
 172.666 +     *          <code>Default</code> argument is returned if the field is
 172.667 +     *          missing or malformed.
 172.668 +     */
 172.669 +    public long getHeaderFieldDate(String name, long Default) {
 172.670 +        String value = getHeaderField(name);
 172.671 +        try {
 172.672 +            return Date.parse(value);
 172.673 +        } catch (Exception e) { }
 172.674 +        return Default;
 172.675 +    }
 172.676 +
 172.677 +    /**
 172.678 +     * Returns the key for the <code>n</code><sup>th</sup> header field.
 172.679 +     * It returns <code>null</code> if there are fewer than <code>n+1</code> fields.
 172.680 +     *
 172.681 +     * @param   n   an index, where n>=0
 172.682 +     * @return  the key for the <code>n</code><sup>th</sup> header field,
 172.683 +     *          or <code>null</code> if there are fewer than <code>n+1</code>
 172.684 +     *          fields.
 172.685 +     */
 172.686 +    public String getHeaderFieldKey(int n) {
 172.687 +        return null;
 172.688 +    }
 172.689 +
 172.690 +    /**
 172.691 +     * Returns the value for the <code>n</code><sup>th</sup> header field.
 172.692 +     * It returns <code>null</code> if there are fewer than
 172.693 +     * <code>n+1</code>fields.
 172.694 +     * <p>
 172.695 +     * This method can be used in conjunction with the
 172.696 +     * {@link #getHeaderFieldKey(int) getHeaderFieldKey} method to iterate through all
 172.697 +     * the headers in the message.
 172.698 +     *
 172.699 +     * @param   n   an index, where n>=0
 172.700 +     * @return  the value of the <code>n</code><sup>th</sup> header field
 172.701 +     *          or <code>null</code> if there are fewer than <code>n+1</code> fields
 172.702 +     * @see     java.net.URLConnection#getHeaderFieldKey(int)
 172.703 +     */
 172.704 +    public String getHeaderField(int n) {
 172.705 +        return null;
 172.706 +    }
 172.707 +
 172.708 +    /**
 172.709 +     * Retrieves the contents of this URL connection.
 172.710 +     * <p>
 172.711 +     * This method first determines the content type of the object by
 172.712 +     * calling the <code>getContentType</code> method. If this is
 172.713 +     * the first time that the application has seen that specific content
 172.714 +     * type, a content handler for that content type is created:
 172.715 +     * <ol>
 172.716 +     * <li>If the application has set up a content handler factory instance
 172.717 +     *     using the <code>setContentHandlerFactory</code> method, the
 172.718 +     *     <code>createContentHandler</code> method of that instance is called
 172.719 +     *     with the content type as an argument; the result is a content
 172.720 +     *     handler for that content type.
 172.721 +     * <li>If no content handler factory has yet been set up, or if the
 172.722 +     *     factory's <code>createContentHandler</code> method returns
 172.723 +     *     <code>null</code>, then the application loads the class named:
 172.724 +     *     <blockquote><pre>
 172.725 +     *         sun.net.www.content.&lt;<i>contentType</i>&gt;
 172.726 +     *     </pre></blockquote>
 172.727 +     *     where &lt;<i>contentType</i>&gt; is formed by taking the
 172.728 +     *     content-type string, replacing all slash characters with a
 172.729 +     *     <code>period</code> ('.'), and all other non-alphanumeric characters
 172.730 +     *     with the underscore character '<code>_</code>'. The alphanumeric
 172.731 +     *     characters are specifically the 26 uppercase ASCII letters
 172.732 +     *     '<code>A</code>' through '<code>Z</code>', the 26 lowercase ASCII
 172.733 +     *     letters '<code>a</code>' through '<code>z</code>', and the 10 ASCII
 172.734 +     *     digits '<code>0</code>' through '<code>9</code>'. If the specified
 172.735 +     *     class does not exist, or is not a subclass of
 172.736 +     *     <code>ContentHandler</code>, then an
 172.737 +     *     <code>UnknownServiceException</code> is thrown.
 172.738 +     * </ol>
 172.739 +     *
 172.740 +     * @return     the object fetched. The <code>instanceof</code> operator
 172.741 +     *               should be used to determine the specific kind of object
 172.742 +     *               returned.
 172.743 +     * @exception  IOException              if an I/O error occurs while
 172.744 +     *               getting the content.
 172.745 +     * @exception  UnknownServiceException  if the protocol does not support
 172.746 +     *               the content type.
 172.747 +     * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
 172.748 +     * @see        java.net.URLConnection#getContentType()
 172.749 +     * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
 172.750 +     */
 172.751 +    public Object getContent() throws IOException {
 172.752 +        // Must call getInputStream before GetHeaderField gets called
 172.753 +        // so that FileNotFoundException has a chance to be thrown up
 172.754 +        // from here without being caught.
 172.755 +        getInputStream();
 172.756 +        return getContentHandler().getContent(this);
 172.757 +    }
 172.758 +
 172.759 +    /**
 172.760 +     * Retrieves the contents of this URL connection.
 172.761 +     *
 172.762 +     * @param classes the <code>Class</code> array
 172.763 +     * indicating the requested types
 172.764 +     * @return     the object fetched that is the first match of the type
 172.765 +     *               specified in the classes array. null if none of
 172.766 +     *               the requested types are supported.
 172.767 +     *               The <code>instanceof</code> operator should be used to
 172.768 +     *               determine the specific kind of object returned.
 172.769 +     * @exception  IOException              if an I/O error occurs while
 172.770 +     *               getting the content.
 172.771 +     * @exception  UnknownServiceException  if the protocol does not support
 172.772 +     *               the content type.
 172.773 +     * @see        java.net.URLConnection#getContent()
 172.774 +     * @see        java.net.ContentHandlerFactory#createContentHandler(java.lang.String)
 172.775 +     * @see        java.net.URLConnection#getContent(java.lang.Class[])
 172.776 +     * @see        java.net.URLConnection#setContentHandlerFactory(java.net.ContentHandlerFactory)
 172.777 +     * @since 1.3
 172.778 +     */
 172.779 +    public Object getContent(Class[] classes) throws IOException {
 172.780 +        // Must call getInputStream before GetHeaderField gets called
 172.781 +        // so that FileNotFoundException has a chance to be thrown up
 172.782 +        // from here without being caught.
 172.783 +        getInputStream();
 172.784 +        return getContentHandler().getContent(this, classes);
 172.785 +    }
 172.786 +
 172.787 +    /**
 172.788 +     * Returns a permission object representing the permission
 172.789 +     * necessary to make the connection represented by this
 172.790 +     * object. This method returns null if no permission is
 172.791 +     * required to make the connection. By default, this method
 172.792 +     * returns <code>java.security.AllPermission</code>. Subclasses
 172.793 +     * should override this method and return the permission
 172.794 +     * that best represents the permission required to make a
 172.795 +     * a connection to the URL. For example, a <code>URLConnection</code>
 172.796 +     * representing a <code>file:</code> URL would return a
 172.797 +     * <code>java.io.FilePermission</code> object.
 172.798 +     *
 172.799 +     * <p>The permission returned may dependent upon the state of the
 172.800 +     * connection. For example, the permission before connecting may be
 172.801 +     * different from that after connecting. For example, an HTTP
 172.802 +     * sever, say foo.com, may redirect the connection to a different
 172.803 +     * host, say bar.com. Before connecting the permission returned by
 172.804 +     * the connection will represent the permission needed to connect
 172.805 +     * to foo.com, while the permission returned after connecting will
 172.806 +     * be to bar.com.
 172.807 +     *
 172.808 +     * <p>Permissions are generally used for two purposes: to protect
 172.809 +     * caches of objects obtained through URLConnections, and to check
 172.810 +     * the right of a recipient to learn about a particular URL. In
 172.811 +     * the first case, the permission should be obtained
 172.812 +     * <em>after</em> the object has been obtained. For example, in an
 172.813 +     * HTTP connection, this will represent the permission to connect
 172.814 +     * to the host from which the data was ultimately fetched. In the
 172.815 +     * second case, the permission should be obtained and tested
 172.816 +     * <em>before</em> connecting.
 172.817 +     *
 172.818 +     * @return the permission object representing the permission
 172.819 +     * necessary to make the connection represented by this
 172.820 +     * URLConnection.
 172.821 +     *
 172.822 +     * @exception IOException if the computation of the permission
 172.823 +     * requires network or file I/O and an exception occurs while
 172.824 +     * computing it.
 172.825 +     */
 172.826 +//    public Permission getPermission() throws IOException {
 172.827 +//        return SecurityConstants.ALL_PERMISSION;
 172.828 +//    }
 172.829 +
 172.830 +    /**
 172.831 +     * Returns an input stream that reads from this open connection.
 172.832 +     *
 172.833 +     * A SocketTimeoutException can be thrown when reading from the
 172.834 +     * returned input stream if the read timeout expires before data
 172.835 +     * is available for read.
 172.836 +     *
 172.837 +     * @return     an input stream that reads from this open connection.
 172.838 +     * @exception  IOException              if an I/O error occurs while
 172.839 +     *               creating the input stream.
 172.840 +     * @exception  UnknownServiceException  if the protocol does not support
 172.841 +     *               input.
 172.842 +     * @see #setReadTimeout(int)
 172.843 +     * @see #getReadTimeout()
 172.844 +     */
 172.845 +    public InputStream getInputStream() throws IOException {
 172.846 +        throw new UnknownServiceException("protocol doesn't support input");
 172.847 +    }
 172.848 +
 172.849 +    /**
 172.850 +     * Returns an output stream that writes to this connection.
 172.851 +     *
 172.852 +     * @return     an output stream that writes to this connection.
 172.853 +     * @exception  IOException              if an I/O error occurs while
 172.854 +     *               creating the output stream.
 172.855 +     * @exception  UnknownServiceException  if the protocol does not support
 172.856 +     *               output.
 172.857 +     */
 172.858 +    public OutputStream getOutputStream() throws IOException {
 172.859 +        throw new UnknownServiceException("protocol doesn't support output");
 172.860 +    }
 172.861 +
 172.862 +    /**
 172.863 +     * Returns a <code>String</code> representation of this URL connection.
 172.864 +     *
 172.865 +     * @return  a string representation of this <code>URLConnection</code>.
 172.866 +     */
 172.867 +    public String toString() {
 172.868 +        return this.getClass().getName() + ":" + url;
 172.869 +    }
 172.870 +
 172.871 +    /**
 172.872 +     * Sets the value of the <code>doInput</code> field for this
 172.873 +     * <code>URLConnection</code> to the specified value.
 172.874 +     * <p>
 172.875 +     * A URL connection can be used for input and/or output.  Set the DoInput
 172.876 +     * flag to true if you intend to use the URL connection for input,
 172.877 +     * false if not.  The default is true.
 172.878 +     *
 172.879 +     * @param   doinput   the new value.
 172.880 +     * @throws IllegalStateException if already connected
 172.881 +     * @see     java.net.URLConnection#doInput
 172.882 +     * @see #getDoInput()
 172.883 +     */
 172.884 +    public void setDoInput(boolean doinput) {
 172.885 +        if (connected)
 172.886 +            throw new IllegalStateException("Already connected");
 172.887 +        doInput = doinput;
 172.888 +    }
 172.889 +
 172.890 +    /**
 172.891 +     * Returns the value of this <code>URLConnection</code>'s
 172.892 +     * <code>doInput</code> flag.
 172.893 +     *
 172.894 +     * @return  the value of this <code>URLConnection</code>'s
 172.895 +     *          <code>doInput</code> flag.
 172.896 +     * @see     #setDoInput(boolean)
 172.897 +     */
 172.898 +    public boolean getDoInput() {
 172.899 +        return doInput;
 172.900 +    }
 172.901 +
 172.902 +    /**
 172.903 +     * Sets the value of the <code>doOutput</code> field for this
 172.904 +     * <code>URLConnection</code> to the specified value.
 172.905 +     * <p>
 172.906 +     * A URL connection can be used for input and/or output.  Set the DoOutput
 172.907 +     * flag to true if you intend to use the URL connection for output,
 172.908 +     * false if not.  The default is false.
 172.909 +     *
 172.910 +     * @param   dooutput   the new value.
 172.911 +     * @throws IllegalStateException if already connected
 172.912 +     * @see #getDoOutput()
 172.913 +     */
 172.914 +    public void setDoOutput(boolean dooutput) {
 172.915 +        if (connected)
 172.916 +            throw new IllegalStateException("Already connected");
 172.917 +        doOutput = dooutput;
 172.918 +    }
 172.919 +
 172.920 +    /**
 172.921 +     * Returns the value of this <code>URLConnection</code>'s
 172.922 +     * <code>doOutput</code> flag.
 172.923 +     *
 172.924 +     * @return  the value of this <code>URLConnection</code>'s
 172.925 +     *          <code>doOutput</code> flag.
 172.926 +     * @see     #setDoOutput(boolean)
 172.927 +     */
 172.928 +    public boolean getDoOutput() {
 172.929 +        return doOutput;
 172.930 +    }
 172.931 +
 172.932 +    /**
 172.933 +     * Set the value of the <code>allowUserInteraction</code> field of
 172.934 +     * this <code>URLConnection</code>.
 172.935 +     *
 172.936 +     * @param   allowuserinteraction   the new value.
 172.937 +     * @throws IllegalStateException if already connected
 172.938 +     * @see     #getAllowUserInteraction()
 172.939 +     */
 172.940 +    public void setAllowUserInteraction(boolean allowuserinteraction) {
 172.941 +        if (connected)
 172.942 +            throw new IllegalStateException("Already connected");
 172.943 +        allowUserInteraction = allowuserinteraction;
 172.944 +    }
 172.945 +
 172.946 +    /**
 172.947 +     * Returns the value of the <code>allowUserInteraction</code> field for
 172.948 +     * this object.
 172.949 +     *
 172.950 +     * @return  the value of the <code>allowUserInteraction</code> field for
 172.951 +     *          this object.
 172.952 +     * @see     #setAllowUserInteraction(boolean)
 172.953 +     */
 172.954 +    public boolean getAllowUserInteraction() {
 172.955 +        return allowUserInteraction;
 172.956 +    }
 172.957 +
 172.958 +    /**
 172.959 +     * Sets the default value of the
 172.960 +     * <code>allowUserInteraction</code> field for all future
 172.961 +     * <code>URLConnection</code> objects to the specified value.
 172.962 +     *
 172.963 +     * @param   defaultallowuserinteraction   the new value.
 172.964 +     * @see     #getDefaultAllowUserInteraction()
 172.965 +     */
 172.966 +    public static void setDefaultAllowUserInteraction(boolean defaultallowuserinteraction) {
 172.967 +        defaultAllowUserInteraction = defaultallowuserinteraction;
 172.968 +    }
 172.969 +
 172.970 +    /**
 172.971 +     * Returns the default value of the <code>allowUserInteraction</code>
 172.972 +     * field.
 172.973 +     * <p>
 172.974 +     * Ths default is "sticky", being a part of the static state of all
 172.975 +     * URLConnections.  This flag applies to the next, and all following
 172.976 +     * URLConnections that are created.
 172.977 +     *
 172.978 +     * @return  the default value of the <code>allowUserInteraction</code>
 172.979 +     *          field.
 172.980 +     * @see     #setDefaultAllowUserInteraction(boolean)
 172.981 +     */
 172.982 +    public static boolean getDefaultAllowUserInteraction() {
 172.983 +        return defaultAllowUserInteraction;
 172.984 +    }
 172.985 +
 172.986 +    /**
 172.987 +     * Sets the value of the <code>useCaches</code> field of this
 172.988 +     * <code>URLConnection</code> to the specified value.
 172.989 +     * <p>
 172.990 +     * Some protocols do caching of documents.  Occasionally, it is important
 172.991 +     * to be able to "tunnel through" and ignore the caches (e.g., the
 172.992 +     * "reload" button in a browser).  If the UseCaches flag on a connection
 172.993 +     * is true, the connection is allowed to use whatever caches it can.
 172.994 +     *  If false, caches are to be ignored.
 172.995 +     *  The default value comes from DefaultUseCaches, which defaults to
 172.996 +     * true.
 172.997 +     *
 172.998 +     * @param usecaches a <code>boolean</code> indicating whether
 172.999 +     * or not to allow caching
172.1000 +     * @throws IllegalStateException if already connected
172.1001 +     * @see #getUseCaches()
172.1002 +     */
172.1003 +    public void setUseCaches(boolean usecaches) {
172.1004 +        if (connected)
172.1005 +            throw new IllegalStateException("Already connected");
172.1006 +        useCaches = usecaches;
172.1007 +    }
172.1008 +
172.1009 +    /**
172.1010 +     * Returns the value of this <code>URLConnection</code>'s
172.1011 +     * <code>useCaches</code> field.
172.1012 +     *
172.1013 +     * @return  the value of this <code>URLConnection</code>'s
172.1014 +     *          <code>useCaches</code> field.
172.1015 +     * @see #setUseCaches(boolean)
172.1016 +     */
172.1017 +    public boolean getUseCaches() {
172.1018 +        return useCaches;
172.1019 +    }
172.1020 +
172.1021 +    /**
172.1022 +     * Sets the value of the <code>ifModifiedSince</code> field of
172.1023 +     * this <code>URLConnection</code> to the specified value.
172.1024 +     *
172.1025 +     * @param   ifmodifiedsince   the new value.
172.1026 +     * @throws IllegalStateException if already connected
172.1027 +     * @see     #getIfModifiedSince()
172.1028 +     */
172.1029 +    public void setIfModifiedSince(long ifmodifiedsince) {
172.1030 +        if (connected)
172.1031 +            throw new IllegalStateException("Already connected");
172.1032 +        ifModifiedSince = ifmodifiedsince;
172.1033 +    }
172.1034 +
172.1035 +    /**
172.1036 +     * Returns the value of this object's <code>ifModifiedSince</code> field.
172.1037 +     *
172.1038 +     * @return  the value of this object's <code>ifModifiedSince</code> field.
172.1039 +     * @see #setIfModifiedSince(long)
172.1040 +     */
172.1041 +    public long getIfModifiedSince() {
172.1042 +        return ifModifiedSince;
172.1043 +    }
172.1044 +
172.1045 +   /**
172.1046 +     * Returns the default value of a <code>URLConnection</code>'s
172.1047 +     * <code>useCaches</code> flag.
172.1048 +     * <p>
172.1049 +     * Ths default is "sticky", being a part of the static state of all
172.1050 +     * URLConnections.  This flag applies to the next, and all following
172.1051 +     * URLConnections that are created.
172.1052 +     *
172.1053 +     * @return  the default value of a <code>URLConnection</code>'s
172.1054 +     *          <code>useCaches</code> flag.
172.1055 +     * @see     #setDefaultUseCaches(boolean)
172.1056 +     */
172.1057 +    public boolean getDefaultUseCaches() {
172.1058 +        return defaultUseCaches;
172.1059 +    }
172.1060 +
172.1061 +   /**
172.1062 +     * Sets the default value of the <code>useCaches</code> field to the
172.1063 +     * specified value.
172.1064 +     *
172.1065 +     * @param   defaultusecaches   the new value.
172.1066 +     * @see     #getDefaultUseCaches()
172.1067 +     */
172.1068 +    public void setDefaultUseCaches(boolean defaultusecaches) {
172.1069 +        defaultUseCaches = defaultusecaches;
172.1070 +    }
172.1071 +
172.1072 +    /**
172.1073 +     * Sets the general request property. If a property with the key already
172.1074 +     * exists, overwrite its value with the new value.
172.1075 +     *
172.1076 +     * <p> NOTE: HTTP requires all request properties which can
172.1077 +     * legally have multiple instances with the same key
172.1078 +     * to use a comma-seperated list syntax which enables multiple
172.1079 +     * properties to be appended into a single property.
172.1080 +     *
172.1081 +     * @param   key     the keyword by which the request is known
172.1082 +     *                  (e.g., "<code>Accept</code>").
172.1083 +     * @param   value   the value associated with it.
172.1084 +     * @throws IllegalStateException if already connected
172.1085 +     * @throws NullPointerException if key is <CODE>null</CODE>
172.1086 +     * @see #getRequestProperty(java.lang.String)
172.1087 +     */
172.1088 +    public void setRequestProperty(String key, String value) {
172.1089 +        if (connected)
172.1090 +            throw new IllegalStateException("Already connected");
172.1091 +        if (key == null)
172.1092 +            throw new NullPointerException ("key is null");
172.1093 +
172.1094 +        if (requests == null)
172.1095 +            requests = new MessageHeader();
172.1096 +
172.1097 +        requests.set(key, value);
172.1098 +    }
172.1099 +
172.1100 +    /**
172.1101 +     * Adds a general request property specified by a
172.1102 +     * key-value pair.  This method will not overwrite
172.1103 +     * existing values associated with the same key.
172.1104 +     *
172.1105 +     * @param   key     the keyword by which the request is known
172.1106 +     *                  (e.g., "<code>Accept</code>").
172.1107 +     * @param   value  the value associated with it.
172.1108 +     * @throws IllegalStateException if already connected
172.1109 +     * @throws NullPointerException if key is null
172.1110 +     * @see #getRequestProperties()
172.1111 +     * @since 1.4
172.1112 +     */
172.1113 +    public void addRequestProperty(String key, String value) {
172.1114 +        if (connected)
172.1115 +            throw new IllegalStateException("Already connected");
172.1116 +        if (key == null)
172.1117 +            throw new NullPointerException ("key is null");
172.1118 +
172.1119 +        if (requests == null)
172.1120 +            requests = new MessageHeader();
172.1121 +
172.1122 +        requests.add(key, value);
172.1123 +    }
172.1124 +
172.1125 +
172.1126 +    /**
172.1127 +     * Returns the value of the named general request property for this
172.1128 +     * connection.
172.1129 +     *
172.1130 +     * @param key the keyword by which the request is known (e.g., "Accept").
172.1131 +     * @return  the value of the named general request property for this
172.1132 +     *           connection. If key is null, then null is returned.
172.1133 +     * @throws IllegalStateException if already connected
172.1134 +     * @see #setRequestProperty(java.lang.String, java.lang.String)
172.1135 +     */
172.1136 +    public String getRequestProperty(String key) {
172.1137 +        if (connected)
172.1138 +            throw new IllegalStateException("Already connected");
172.1139 +
172.1140 +        if (requests == null)
172.1141 +            return null;
172.1142 +
172.1143 +        return requests.findValue(key);
172.1144 +    }
172.1145 +
172.1146 +    /**
172.1147 +     * Returns an unmodifiable Map of general request
172.1148 +     * properties for this connection. The Map keys
172.1149 +     * are Strings that represent the request-header
172.1150 +     * field names. Each Map value is a unmodifiable List
172.1151 +     * of Strings that represents the corresponding
172.1152 +     * field values.
172.1153 +     *
172.1154 +     * @return  a Map of the general request properties for this connection.
172.1155 +     * @throws IllegalStateException if already connected
172.1156 +     * @since 1.4
172.1157 +     */
172.1158 +    public Map<String,List<String>> getRequestProperties() {
172.1159 +        if (connected)
172.1160 +            throw new IllegalStateException("Already connected");
172.1161 +
172.1162 +        if (requests == null)
172.1163 +            return Collections.EMPTY_MAP;
172.1164 +
172.1165 +        return requests.getHeaders(null);
172.1166 +    }
172.1167 +
172.1168 +    /**
172.1169 +     * Sets the default value of a general request property. When a
172.1170 +     * <code>URLConnection</code> is created, it is initialized with
172.1171 +     * these properties.
172.1172 +     *
172.1173 +     * @param   key     the keyword by which the request is known
172.1174 +     *                  (e.g., "<code>Accept</code>").
172.1175 +     * @param   value   the value associated with the key.
172.1176 +     *
172.1177 +     * @see java.net.URLConnection#setRequestProperty(java.lang.String,java.lang.String)
172.1178 +     *
172.1179 +     * @deprecated The instance specific setRequestProperty method
172.1180 +     * should be used after an appropriate instance of URLConnection
172.1181 +     * is obtained. Invoking this method will have no effect.
172.1182 +     *
172.1183 +     * @see #getDefaultRequestProperty(java.lang.String)
172.1184 +     */
172.1185 +    @Deprecated
172.1186 +    public static void setDefaultRequestProperty(String key, String value) {
172.1187 +    }
172.1188 +
172.1189 +    /**
172.1190 +     * Returns the value of the default request property. Default request
172.1191 +     * properties are set for every connection.
172.1192 +     *
172.1193 +     * @param key the keyword by which the request is known (e.g., "Accept").
172.1194 +     * @return  the value of the default request property
172.1195 +     * for the specified key.
172.1196 +     *
172.1197 +     * @see java.net.URLConnection#getRequestProperty(java.lang.String)
172.1198 +     *
172.1199 +     * @deprecated The instance specific getRequestProperty method
172.1200 +     * should be used after an appropriate instance of URLConnection
172.1201 +     * is obtained.
172.1202 +     *
172.1203 +     * @see #setDefaultRequestProperty(java.lang.String, java.lang.String)
172.1204 +     */
172.1205 +    @Deprecated
172.1206 +    public static String getDefaultRequestProperty(String key) {
172.1207 +        return null;
172.1208 +    }
172.1209 +
172.1210 +    /**
172.1211 +     * The ContentHandler factory.
172.1212 +     */
172.1213 +    static ContentHandlerFactory factory;
172.1214 +
172.1215 +    /**
172.1216 +     * Sets the <code>ContentHandlerFactory</code> of an
172.1217 +     * application. It can be called at most once by an application.
172.1218 +     * <p>
172.1219 +     * The <code>ContentHandlerFactory</code> instance is used to
172.1220 +     * construct a content handler from a content type
172.1221 +     * <p>
172.1222 +     * If there is a security manager, this method first calls
172.1223 +     * the security manager's <code>checkSetFactory</code> method
172.1224 +     * to ensure the operation is allowed.
172.1225 +     * This could result in a SecurityException.
172.1226 +     *
172.1227 +     * @param      fac   the desired factory.
172.1228 +     * @exception  Error  if the factory has already been defined.
172.1229 +     * @exception  SecurityException  if a security manager exists and its
172.1230 +     *             <code>checkSetFactory</code> method doesn't allow the operation.
172.1231 +     * @see        java.net.ContentHandlerFactory
172.1232 +     * @see        java.net.URLConnection#getContent()
172.1233 +     * @see        SecurityManager#checkSetFactory
172.1234 +     */
172.1235 +    public static synchronized void setContentHandlerFactory(ContentHandlerFactory fac) {
172.1236 +        throw new SecurityException();
172.1237 +    }
172.1238 +
172.1239 +    private static Hashtable handlers = new Hashtable();
172.1240 +
172.1241 +    /**
172.1242 +     * Gets the Content Handler appropriate for this connection.
172.1243 +     * @param connection the connection to use.
172.1244 +     */
172.1245 +    synchronized ContentHandler getContentHandler()
172.1246 +    throws UnknownServiceException
172.1247 +    {
172.1248 +        String contentType = stripOffParameters(getContentType());
172.1249 +        ContentHandler handler = null;
172.1250 +        if (contentType == null)
172.1251 +            throw new UnknownServiceException("no content-type");
172.1252 +        try {
172.1253 +            handler = (ContentHandler) handlers.get(contentType);
172.1254 +            if (handler != null)
172.1255 +                return handler;
172.1256 +        } catch(Exception e) {
172.1257 +        }
172.1258 +
172.1259 +        if (factory != null)
172.1260 +            handler = factory.createContentHandler(contentType);
172.1261 +        if (handler == null) {
172.1262 +            try {
172.1263 +                handler = lookupContentHandlerClassFor(contentType);
172.1264 +            } catch(Exception e) {
172.1265 +                e.printStackTrace();
172.1266 +                handler = UnknownContentHandler.INSTANCE;
172.1267 +            }
172.1268 +            handlers.put(contentType, handler);
172.1269 +        }
172.1270 +        return handler;
172.1271 +    }
172.1272 +
172.1273 +    /*
172.1274 +     * Media types are in the format: type/subtype*(; parameter).
172.1275 +     * For looking up the content handler, we should ignore those
172.1276 +     * parameters.
172.1277 +     */
172.1278 +    private String stripOffParameters(String contentType)
172.1279 +    {
172.1280 +        if (contentType == null)
172.1281 +            return null;
172.1282 +        int index = contentType.indexOf(';');
172.1283 +
172.1284 +        if (index > 0)
172.1285 +            return contentType.substring(0, index);
172.1286 +        else
172.1287 +            return contentType;
172.1288 +    }
172.1289 +
172.1290 +    private static final String contentClassPrefix = "sun.net.www.content";
172.1291 +    private static final String contentPathProp = "java.content.handler.pkgs";
172.1292 +
172.1293 +    /**
172.1294 +     * Looks for a content handler in a user-defineable set of places.
172.1295 +     * By default it looks in sun.net.www.content, but users can define a
172.1296 +     * vertical-bar delimited set of class prefixes to search through in
172.1297 +     * addition by defining the java.content.handler.pkgs property.
172.1298 +     * The class name must be of the form:
172.1299 +     * <pre>
172.1300 +     *     {package-prefix}.{major}.{minor}
172.1301 +     * e.g.
172.1302 +     *     YoyoDyne.experimental.text.plain
172.1303 +     * </pre>
172.1304 +     */
172.1305 +    private ContentHandler lookupContentHandlerClassFor(String contentType)
172.1306 +        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
172.1307 +        String contentHandlerClassName = typeToPackageName(contentType);
172.1308 +
172.1309 +        String contentHandlerPkgPrefixes =getContentHandlerPkgPrefixes();
172.1310 +
172.1311 +        StringTokenizer packagePrefixIter =
172.1312 +            new StringTokenizer(contentHandlerPkgPrefixes, "|");
172.1313 +
172.1314 +        while (packagePrefixIter.hasMoreTokens()) {
172.1315 +            String packagePrefix = packagePrefixIter.nextToken().trim();
172.1316 +
172.1317 +            try {
172.1318 +                String clsName = packagePrefix + "." + contentHandlerClassName;
172.1319 +                Class cls = null;
172.1320 +                try {
172.1321 +                    cls = Class.forName(clsName);
172.1322 +                } catch (ClassNotFoundException e) {
172.1323 +                    ClassLoader cl = ClassLoader.getSystemClassLoader();
172.1324 +                    if (cl != null) {
172.1325 +                        cls = cl.loadClass(clsName);
172.1326 +                    }
172.1327 +                }
172.1328 +                if (cls != null) {
172.1329 +                    ContentHandler handler =
172.1330 +                        (ContentHandler)cls.newInstance();
172.1331 +                    return handler;
172.1332 +                }
172.1333 +            } catch(Exception e) {
172.1334 +            }
172.1335 +        }
172.1336 +
172.1337 +        return UnknownContentHandler.INSTANCE;
172.1338 +    }
172.1339 +
172.1340 +    /**
172.1341 +     * Utility function to map a MIME content type into an equivalent
172.1342 +     * pair of class name components.  For example: "text/html" would
172.1343 +     * be returned as "text.html"
172.1344 +     */
172.1345 +    private String typeToPackageName(String contentType) {
172.1346 +        // make sure we canonicalize the class name: all lower case
172.1347 +        contentType = contentType.toLowerCase();
172.1348 +        int len = contentType.length();
172.1349 +        char nm[] = new char[len];
172.1350 +        contentType.getChars(0, len, nm, 0);
172.1351 +        for (int i = 0; i < len; i++) {
172.1352 +            char c = nm[i];
172.1353 +            if (c == '/') {
172.1354 +                nm[i] = '.';
172.1355 +            } else if (!('A' <= c && c <= 'Z' ||
172.1356 +                       'a' <= c && c <= 'z' ||
172.1357 +                       '0' <= c && c <= '9')) {
172.1358 +                nm[i] = '_';
172.1359 +            }
172.1360 +        }
172.1361 +        return new String(nm);
172.1362 +    }
172.1363 +
172.1364 +
172.1365 +    /**
172.1366 +     * Returns a vertical bar separated list of package prefixes for potential
172.1367 +     * content handlers.  Tries to get the java.content.handler.pkgs property
172.1368 +     * to use as a set of package prefixes to search.  Whether or not
172.1369 +     * that property has been defined, the sun.net.www.content is always
172.1370 +     * the last one on the returned package list.
172.1371 +     */
172.1372 +    private String getContentHandlerPkgPrefixes() {
172.1373 +        String packagePrefixList = "";
172.1374 +        
172.1375 +        if (packagePrefixList != "") {
172.1376 +            packagePrefixList += "|";
172.1377 +        }
172.1378 +
172.1379 +        return packagePrefixList + contentClassPrefix;
172.1380 +    }
172.1381 +
172.1382 +    /**
172.1383 +     * Tries to determine the content type of an object, based
172.1384 +     * on the specified "file" component of a URL.
172.1385 +     * This is a convenience method that can be used by
172.1386 +     * subclasses that override the <code>getContentType</code> method.
172.1387 +     *
172.1388 +     * @param   fname   a filename.
172.1389 +     * @return  a guess as to what the content type of the object is,
172.1390 +     *          based upon its file name.
172.1391 +     * @see     java.net.URLConnection#getContentType()
172.1392 +     */
172.1393 +    public static String guessContentTypeFromName(String fname) {
172.1394 +        return getFileNameMap().getContentTypeFor(fname);
172.1395 +    }
172.1396 +
172.1397 +    /**
172.1398 +     * Tries to determine the type of an input stream based on the
172.1399 +     * characters at the beginning of the input stream. This method can
172.1400 +     * be used by subclasses that override the
172.1401 +     * <code>getContentType</code> method.
172.1402 +     * <p>
172.1403 +     * Ideally, this routine would not be needed. But many
172.1404 +     * <code>http</code> servers return the incorrect content type; in
172.1405 +     * addition, there are many nonstandard extensions. Direct inspection
172.1406 +     * of the bytes to determine the content type is often more accurate
172.1407 +     * than believing the content type claimed by the <code>http</code> server.
172.1408 +     *
172.1409 +     * @param      is   an input stream that supports marks.
172.1410 +     * @return     a guess at the content type, or <code>null</code> if none
172.1411 +     *             can be determined.
172.1412 +     * @exception  IOException  if an I/O error occurs while reading the
172.1413 +     *               input stream.
172.1414 +     * @see        java.io.InputStream#mark(int)
172.1415 +     * @see        java.io.InputStream#markSupported()
172.1416 +     * @see        java.net.URLConnection#getContentType()
172.1417 +     */
172.1418 +    static public String guessContentTypeFromStream(InputStream is)
172.1419 +                        throws IOException {
172.1420 +        // If we can't read ahead safely, just give up on guessing
172.1421 +        if (!is.markSupported())
172.1422 +            return null;
172.1423 +
172.1424 +        is.mark(16);
172.1425 +        int c1 = is.read();
172.1426 +        int c2 = is.read();
172.1427 +        int c3 = is.read();
172.1428 +        int c4 = is.read();
172.1429 +        int c5 = is.read();
172.1430 +        int c6 = is.read();
172.1431 +        int c7 = is.read();
172.1432 +        int c8 = is.read();
172.1433 +        int c9 = is.read();
172.1434 +        int c10 = is.read();
172.1435 +        int c11 = is.read();
172.1436 +        int c12 = is.read();
172.1437 +        int c13 = is.read();
172.1438 +        int c14 = is.read();
172.1439 +        int c15 = is.read();
172.1440 +        int c16 = is.read();
172.1441 +        is.reset();
172.1442 +
172.1443 +        if (c1 == 0xCA && c2 == 0xFE && c3 == 0xBA && c4 == 0xBE) {
172.1444 +            return "application/java-vm";
172.1445 +        }
172.1446 +
172.1447 +        if (c1 == 0xAC && c2 == 0xED) {
172.1448 +            // next two bytes are version number, currently 0x00 0x05
172.1449 +            return "application/x-java-serialized-object";
172.1450 +        }
172.1451 +
172.1452 +        if (c1 == '<') {
172.1453 +            if (c2 == '!'
172.1454 +                || ((c2 == 'h' && (c3 == 't' && c4 == 'm' && c5 == 'l' ||
172.1455 +                                   c3 == 'e' && c4 == 'a' && c5 == 'd') ||
172.1456 +                (c2 == 'b' && c3 == 'o' && c4 == 'd' && c5 == 'y'))) ||
172.1457 +                ((c2 == 'H' && (c3 == 'T' && c4 == 'M' && c5 == 'L' ||
172.1458 +                                c3 == 'E' && c4 == 'A' && c5 == 'D') ||
172.1459 +                (c2 == 'B' && c3 == 'O' && c4 == 'D' && c5 == 'Y')))) {
172.1460 +                return "text/html";
172.1461 +            }
172.1462 +
172.1463 +            if (c2 == '?' && c3 == 'x' && c4 == 'm' && c5 == 'l' && c6 == ' ') {
172.1464 +                return "application/xml";
172.1465 +            }
172.1466 +        }
172.1467 +
172.1468 +        // big and little (identical) endian UTF-8 encodings, with BOM
172.1469 +        if (c1 == 0xef &&  c2 == 0xbb &&  c3 == 0xbf) {
172.1470 +            if (c4 == '<' &&  c5 == '?' &&  c6 == 'x') {
172.1471 +                return "application/xml";
172.1472 +            }
172.1473 +        }
172.1474 +
172.1475 +        // big and little endian UTF-16 encodings, with byte order mark
172.1476 +        if (c1 == 0xfe && c2 == 0xff) {
172.1477 +            if (c3 == 0 && c4 == '<' && c5 == 0 && c6 == '?' &&
172.1478 +                c7 == 0 && c8 == 'x') {
172.1479 +                return "application/xml";
172.1480 +            }
172.1481 +        }
172.1482 +
172.1483 +        if (c1 == 0xff && c2 == 0xfe) {
172.1484 +            if (c3 == '<' && c4 == 0 && c5 == '?' && c6 == 0 &&
172.1485 +                c7 == 'x' && c8 == 0) {
172.1486 +                return "application/xml";
172.1487 +            }
172.1488 +        }
172.1489 +
172.1490 +        // big and little endian UTF-32 encodings, with BOM
172.1491 +        if (c1 == 0x00 &&  c2 == 0x00 &&  c3 == 0xfe &&  c4 == 0xff) {
172.1492 +            if (c5  == 0 && c6  == 0 && c7  == 0 && c8  == '<' &&
172.1493 +                c9  == 0 && c10 == 0 && c11 == 0 && c12 == '?' &&
172.1494 +                c13 == 0 && c14 == 0 && c15 == 0 && c16 == 'x') {
172.1495 +                return "application/xml";
172.1496 +            }
172.1497 +        }
172.1498 +
172.1499 +        if (c1 == 0xff &&  c2 == 0xfe &&  c3 == 0x00 &&  c4 == 0x00) {
172.1500 +            if (c5  == '<' && c6  == 0 && c7  == 0 && c8  == 0 &&
172.1501 +                c9  == '?' && c10 == 0 && c11 == 0 && c12 == 0 &&
172.1502 +                c13 == 'x' && c14 == 0 && c15 == 0 && c16 == 0) {
172.1503 +                return "application/xml";
172.1504 +            }
172.1505 +        }
172.1506 +
172.1507 +        if (c1 == 'G' && c2 == 'I' && c3 == 'F' && c4 == '8') {
172.1508 +            return "image/gif";
172.1509 +        }
172.1510 +
172.1511 +        if (c1 == '#' && c2 == 'd' && c3 == 'e' && c4 == 'f') {
172.1512 +            return "image/x-bitmap";
172.1513 +        }
172.1514 +
172.1515 +        if (c1 == '!' && c2 == ' ' && c3 == 'X' && c4 == 'P' &&
172.1516 +                        c5 == 'M' && c6 == '2') {
172.1517 +            return "image/x-pixmap";
172.1518 +        }
172.1519 +
172.1520 +        if (c1 == 137 && c2 == 80 && c3 == 78 &&
172.1521 +                c4 == 71 && c5 == 13 && c6 == 10 &&
172.1522 +                c7 == 26 && c8 == 10) {
172.1523 +            return "image/png";
172.1524 +        }
172.1525 +
172.1526 +        if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF) {
172.1527 +            if (c4 == 0xE0) {
172.1528 +                return "image/jpeg";
172.1529 +            }
172.1530 +
172.1531 +            /**
172.1532 +             * File format used by digital cameras to store images.
172.1533 +             * Exif Format can be read by any application supporting
172.1534 +             * JPEG. Exif Spec can be found at:
172.1535 +             * http://www.pima.net/standards/it10/PIMA15740/Exif_2-1.PDF
172.1536 +             */
172.1537 +            if ((c4 == 0xE1) &&
172.1538 +                (c7 == 'E' && c8 == 'x' && c9 == 'i' && c10 =='f' &&
172.1539 +                 c11 == 0)) {
172.1540 +                return "image/jpeg";
172.1541 +            }
172.1542 +
172.1543 +            if (c4 == 0xEE) {
172.1544 +                return "image/jpg";
172.1545 +            }
172.1546 +        }
172.1547 +
172.1548 +        if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
172.1549 +            c5 == 0xA1 && c6 == 0xB1 && c7 == 0x1A && c8 == 0xE1) {
172.1550 +
172.1551 +            /* Above is signature of Microsoft Structured Storage.
172.1552 +             * Below this, could have tests for various SS entities.
172.1553 +             * For now, just test for FlashPix.
172.1554 +             */
172.1555 +            if (checkfpx(is)) {
172.1556 +                return "image/vnd.fpx";
172.1557 +            }
172.1558 +        }
172.1559 +
172.1560 +        if (c1 == 0x2E && c2 == 0x73 && c3 == 0x6E && c4 == 0x64) {
172.1561 +            return "audio/basic";  // .au format, big endian
172.1562 +        }
172.1563 +
172.1564 +        if (c1 == 0x64 && c2 == 0x6E && c3 == 0x73 && c4 == 0x2E) {
172.1565 +            return "audio/basic";  // .au format, little endian
172.1566 +        }
172.1567 +
172.1568 +        if (c1 == 'R' && c2 == 'I' && c3 == 'F' && c4 == 'F') {
172.1569 +            /* I don't know if this is official but evidence
172.1570 +             * suggests that .wav files start with "RIFF" - brown
172.1571 +             */
172.1572 +            return "audio/x-wav";
172.1573 +        }
172.1574 +        return null;
172.1575 +    }
172.1576 +
172.1577 +    /**
172.1578 +     * Check for FlashPix image data in InputStream is.  Return true if
172.1579 +     * the stream has FlashPix data, false otherwise.  Before calling this
172.1580 +     * method, the stream should have already been checked to be sure it
172.1581 +     * contains Microsoft Structured Storage data.
172.1582 +     */
172.1583 +    static private boolean checkfpx(InputStream is) throws IOException {
172.1584 +
172.1585 +        /* Test for FlashPix image data in Microsoft Structured Storage format.
172.1586 +         * In general, should do this with calls to an SS implementation.
172.1587 +         * Lacking that, need to dig via offsets to get to the FlashPix
172.1588 +         * ClassID.  Details:
172.1589 +         *
172.1590 +         * Offset to Fpx ClsID from beginning of stream should be:
172.1591 +         *
172.1592 +         * FpxClsidOffset = rootEntryOffset + clsidOffset
172.1593 +         *
172.1594 +         * where: clsidOffset = 0x50.
172.1595 +         *        rootEntryOffset = headerSize + sectorSize*sectDirStart
172.1596 +         *                          + 128*rootEntryDirectory
172.1597 +         *
172.1598 +         *        where:  headerSize = 0x200 (always)
172.1599 +         *                sectorSize = 2 raised to power of uSectorShift,
172.1600 +         *                             which is found in the header at
172.1601 +         *                             offset 0x1E.
172.1602 +         *                sectDirStart = found in the header at offset 0x30.
172.1603 +         *                rootEntryDirectory = in general, should search for
172.1604 +         *                                     directory labelled as root.
172.1605 +         *                                     We will assume value of 0 (i.e.,
172.1606 +         *                                     rootEntry is in first directory)
172.1607 +         */
172.1608 +
172.1609 +        // Mark the stream so we can reset it. 0x100 is enough for the first
172.1610 +        // few reads, but the mark will have to be reset and set again once
172.1611 +        // the offset to the root directory entry is computed. That offset
172.1612 +        // can be very large and isn't know until the stream has been read from
172.1613 +        is.mark(0x100);
172.1614 +
172.1615 +        // Get the byte ordering located at 0x1E. 0xFE is Intel,
172.1616 +        // 0xFF is other
172.1617 +        long toSkip = (long)0x1C;
172.1618 +        long posn;
172.1619 +
172.1620 +        if ((posn = skipForward(is, toSkip)) < toSkip) {
172.1621 +          is.reset();
172.1622 +          return false;
172.1623 +        }
172.1624 +
172.1625 +        int c[] = new int[16];
172.1626 +        if (readBytes(c, 2, is) < 0) {
172.1627 +            is.reset();
172.1628 +            return false;
172.1629 +        }
172.1630 +
172.1631 +        int byteOrder = c[0];
172.1632 +
172.1633 +        posn+=2;
172.1634 +        int uSectorShift;
172.1635 +        if (readBytes(c, 2, is) < 0) {
172.1636 +            is.reset();
172.1637 +            return false;
172.1638 +        }
172.1639 +
172.1640 +        if(byteOrder == 0xFE) {
172.1641 +            uSectorShift = c[0];
172.1642 +            uSectorShift += c[1] << 8;
172.1643 +        }
172.1644 +        else {
172.1645 +            uSectorShift = c[0] << 8;
172.1646 +            uSectorShift += c[1];
172.1647 +        }
172.1648 +
172.1649 +        posn += 2;
172.1650 +        toSkip = (long)0x30 - posn;
172.1651 +        long skipped = 0;
172.1652 +        if ((skipped = skipForward(is, toSkip)) < toSkip) {
172.1653 +          is.reset();
172.1654 +          return false;
172.1655 +        }
172.1656 +        posn += skipped;
172.1657 +
172.1658 +        if (readBytes(c, 4, is) < 0) {
172.1659 +            is.reset();
172.1660 +            return false;
172.1661 +        }
172.1662 +
172.1663 +        int sectDirStart;
172.1664 +        if(byteOrder == 0xFE) {
172.1665 +            sectDirStart = c[0];
172.1666 +            sectDirStart += c[1] << 8;
172.1667 +            sectDirStart += c[2] << 16;
172.1668 +            sectDirStart += c[3] << 24;
172.1669 +        } else {
172.1670 +            sectDirStart =  c[0] << 24;
172.1671 +            sectDirStart += c[1] << 16;
172.1672 +            sectDirStart += c[2] << 8;
172.1673 +            sectDirStart += c[3];
172.1674 +        }
172.1675 +        posn += 4;
172.1676 +        is.reset(); // Reset back to the beginning
172.1677 +
172.1678 +        toSkip = 0x200L + (long)(1<<uSectorShift)*sectDirStart + 0x50L;
172.1679 +
172.1680 +        // Sanity check!
172.1681 +        if (toSkip < 0) {
172.1682 +            return false;
172.1683 +        }
172.1684 +
172.1685 +        /*
172.1686 +         * How far can we skip? Is there any performance problem here?
172.1687 +         * This skip can be fairly long, at least 0x4c650 in at least
172.1688 +         * one case. Have to assume that the skip will fit in an int.
172.1689 +         * Leave room to read whole root dir
172.1690 +         */
172.1691 +        is.mark((int)toSkip+0x30);
172.1692 +
172.1693 +        if ((skipForward(is, toSkip)) < toSkip) {
172.1694 +            is.reset();
172.1695 +            return false;
172.1696 +        }
172.1697 +
172.1698 +        /* should be at beginning of ClassID, which is as follows
172.1699 +         * (in Intel byte order):
172.1700 +         *    00 67 61 56 54 C1 CE 11 85 53 00 AA 00 A1 F9 5B
172.1701 +         *
172.1702 +         * This is stored from Windows as long,short,short,char[8]
172.1703 +         * so for byte order changes, the order only changes for
172.1704 +         * the first 8 bytes in the ClassID.
172.1705 +         *
172.1706 +         * Test against this, ignoring second byte (Intel) since
172.1707 +         * this could change depending on part of Fpx file we have.
172.1708 +         */
172.1709 +
172.1710 +        if (readBytes(c, 16, is) < 0) {
172.1711 +            is.reset();
172.1712 +            return false;
172.1713 +        }
172.1714 +
172.1715 +        // intel byte order
172.1716 +        if (byteOrder == 0xFE &&
172.1717 +            c[0] == 0x00 && c[2] == 0x61 && c[3] == 0x56 &&
172.1718 +            c[4] == 0x54 && c[5] == 0xC1 && c[6] == 0xCE &&
172.1719 +            c[7] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
172.1720 +            c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
172.1721 +            c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
172.1722 +            is.reset();
172.1723 +            return true;
172.1724 +        }
172.1725 +
172.1726 +        // non-intel byte order
172.1727 +        else if (c[3] == 0x00 && c[1] == 0x61 && c[0] == 0x56 &&
172.1728 +            c[5] == 0x54 && c[4] == 0xC1 && c[7] == 0xCE &&
172.1729 +            c[6] == 0x11 && c[8] == 0x85 && c[9] == 0x53 &&
172.1730 +            c[10]== 0x00 && c[11]== 0xAA && c[12]== 0x00 &&
172.1731 +            c[13]== 0xA1 && c[14]== 0xF9 && c[15]== 0x5B) {
172.1732 +            is.reset();
172.1733 +            return true;
172.1734 +        }
172.1735 +        is.reset();
172.1736 +        return false;
172.1737 +    }
172.1738 +
172.1739 +    /**
172.1740 +     * Tries to read the specified number of bytes from the stream
172.1741 +     * Returns -1, If EOF is reached before len bytes are read, returns 0
172.1742 +     * otherwise
172.1743 +     */
172.1744 +    static private int readBytes(int c[], int len, InputStream is)
172.1745 +                throws IOException {
172.1746 +
172.1747 +        byte buf[] = new byte[len];
172.1748 +        if (is.read(buf, 0, len) < len) {
172.1749 +            return -1;
172.1750 +        }
172.1751 +
172.1752 +        // fill the passed in int array
172.1753 +        for (int i = 0; i < len; i++) {
172.1754 +             c[i] = buf[i] & 0xff;
172.1755 +        }
172.1756 +        return 0;
172.1757 +    }
172.1758 +
172.1759 +
172.1760 +    /**
172.1761 +     * Skips through the specified number of bytes from the stream
172.1762 +     * until either EOF is reached, or the specified
172.1763 +     * number of bytes have been skipped
172.1764 +     */
172.1765 +    static private long skipForward(InputStream is, long toSkip)
172.1766 +                throws IOException {
172.1767 +
172.1768 +        long eachSkip = 0;
172.1769 +        long skipped = 0;
172.1770 +
172.1771 +        while (skipped != toSkip) {
172.1772 +            eachSkip = is.skip(toSkip - skipped);
172.1773 +
172.1774 +            // check if EOF is reached
172.1775 +            if (eachSkip <= 0) {
172.1776 +                if (is.read() == -1) {
172.1777 +                    return skipped ;
172.1778 +                } else {
172.1779 +                    skipped++;
172.1780 +                }
172.1781 +            }
172.1782 +            skipped += eachSkip;
172.1783 +        }
172.1784 +        return skipped;
172.1785 +    }
172.1786 +
172.1787 +}
172.1788 +
172.1789 +
172.1790 +class UnknownContentHandler extends ContentHandler {
172.1791 +    static final ContentHandler INSTANCE = new UnknownContentHandler();
172.1792 +
172.1793 +    public Object getContent(URLConnection uc) throws IOException {
172.1794 +        return uc.getInputStream();
172.1795 +    }
172.1796 +}
172.1797 +
172.1798 +/** An RFC 844 or MIME message header.  Includes methods
172.1799 +    for parsing headers from incoming streams, fetching
172.1800 +    values, setting values, and printing headers.
172.1801 +    Key values of null are legal: they indicate lines in
172.1802 +    the header that don't have a valid key, but do have
172.1803 +    a value (this isn't legal according to the standard,
172.1804 +    but lines like this are everywhere). */
172.1805 +class MessageHeader {
172.1806 +    private String keys[];
172.1807 +    private String values[];
172.1808 +    private int nkeys;
172.1809 +
172.1810 +    public MessageHeader () {
172.1811 +        grow();
172.1812 +    }
172.1813 +
172.1814 +    public MessageHeader (InputStream is) throws java.io.IOException {
172.1815 +        parseHeader(is);
172.1816 +    }
172.1817 +
172.1818 +    /**
172.1819 +     * Reset a message header (all key/values removed)
172.1820 +     */
172.1821 +    public synchronized void reset() {
172.1822 +        keys = null;
172.1823 +        values = null;
172.1824 +        nkeys = 0;
172.1825 +        grow();
172.1826 +    }
172.1827 +
172.1828 +    /**
172.1829 +     * Find the value that corresponds to this key.
172.1830 +     * It finds only the first occurrence of the key.
172.1831 +     * @param k the key to find.
172.1832 +     * @return null if not found.
172.1833 +     */
172.1834 +    public synchronized String findValue(String k) {
172.1835 +        if (k == null) {
172.1836 +            for (int i = nkeys; --i >= 0;)
172.1837 +                if (keys[i] == null)
172.1838 +                    return values[i];
172.1839 +        } else
172.1840 +            for (int i = nkeys; --i >= 0;) {
172.1841 +                if (k.equalsIgnoreCase(keys[i]))
172.1842 +                    return values[i];
172.1843 +            }
172.1844 +        return null;
172.1845 +    }
172.1846 +
172.1847 +    // return the location of the key
172.1848 +    public synchronized int getKey(String k) {
172.1849 +        for (int i = nkeys; --i >= 0;)
172.1850 +            if ((keys[i] == k) ||
172.1851 +                (k != null && k.equalsIgnoreCase(keys[i])))
172.1852 +                return i;
172.1853 +        return -1;
172.1854 +    }
172.1855 +
172.1856 +    public synchronized String getKey(int n) {
172.1857 +        if (n < 0 || n >= nkeys) return null;
172.1858 +        return keys[n];
172.1859 +    }
172.1860 +
172.1861 +    public synchronized String getValue(int n) {
172.1862 +        if (n < 0 || n >= nkeys) return null;
172.1863 +        return values[n];
172.1864 +    }
172.1865 +
172.1866 +    /** Deprecated: Use multiValueIterator() instead.
172.1867 +     *
172.1868 +     *  Find the next value that corresponds to this key.
172.1869 +     *  It finds the first value that follows v. To iterate
172.1870 +     *  over all the values of a key use:
172.1871 +     *  <pre>
172.1872 +     *          for(String v=h.findValue(k); v!=null; v=h.findNextValue(k, v)) {
172.1873 +     *              ...
172.1874 +     *          }
172.1875 +     *  </pre>
172.1876 +     */
172.1877 +    public synchronized String findNextValue(String k, String v) {
172.1878 +        boolean foundV = false;
172.1879 +        if (k == null) {
172.1880 +            for (int i = nkeys; --i >= 0;)
172.1881 +                if (keys[i] == null)
172.1882 +                    if (foundV)
172.1883 +                        return values[i];
172.1884 +                    else if (values[i] == v)
172.1885 +                        foundV = true;
172.1886 +        } else
172.1887 +            for (int i = nkeys; --i >= 0;)
172.1888 +                if (k.equalsIgnoreCase(keys[i]))
172.1889 +                    if (foundV)
172.1890 +                        return values[i];
172.1891 +                    else if (values[i] == v)
172.1892 +                        foundV = true;
172.1893 +        return null;
172.1894 +    }
172.1895 +
172.1896 +    class HeaderIterator implements Iterator<String> {
172.1897 +        int index = 0;
172.1898 +        int next = -1;
172.1899 +        String key;
172.1900 +        boolean haveNext = false;
172.1901 +        Object lock;
172.1902 +
172.1903 +        public HeaderIterator (String k, Object lock) {
172.1904 +            key = k;
172.1905 +            this.lock = lock;
172.1906 +        }
172.1907 +        public boolean hasNext () {
172.1908 +            synchronized (lock) {
172.1909 +                if (haveNext) {
172.1910 +                    return true;
172.1911 +                }
172.1912 +                while (index < nkeys) {
172.1913 +                    if (key.equalsIgnoreCase (keys[index])) {
172.1914 +                        haveNext = true;
172.1915 +                        next = index++;
172.1916 +                        return true;
172.1917 +                    }
172.1918 +                    index ++;
172.1919 +                }
172.1920 +                return false;
172.1921 +            }
172.1922 +        }
172.1923 +        public String next() {
172.1924 +            synchronized (lock) {
172.1925 +                if (haveNext) {
172.1926 +                    haveNext = false;
172.1927 +                    return values [next];
172.1928 +                }
172.1929 +                if (hasNext()) {
172.1930 +                    return next();
172.1931 +                } else {
172.1932 +                    throw new NoSuchElementException ("No more elements");
172.1933 +                }
172.1934 +            }
172.1935 +        }
172.1936 +        public void remove () {
172.1937 +            throw new UnsupportedOperationException ("remove not allowed");
172.1938 +        }
172.1939 +    }
172.1940 +
172.1941 +    /**
172.1942 +     * return an Iterator that returns all values of a particular
172.1943 +     * key in sequence
172.1944 +     */
172.1945 +    public Iterator<String> multiValueIterator (String k) {
172.1946 +        return new HeaderIterator (k, this);
172.1947 +    }
172.1948 +
172.1949 +    public synchronized Map<String, List<String>> getHeaders() {
172.1950 +        return getHeaders(null);
172.1951 +    }
172.1952 +
172.1953 +    public synchronized Map<String, List<String>> getHeaders(String[] excludeList) {
172.1954 +        return filterAndAddHeaders(excludeList, null);
172.1955 +    }
172.1956 +
172.1957 +    public synchronized Map<String, List<String>> filterAndAddHeaders(String[] excludeList, Map<String, List<String>>  include) {
172.1958 +        boolean skipIt = false;
172.1959 +        Map<String, List<String>> m = new HashMap<String, List<String>>();
172.1960 +        for (int i = nkeys; --i >= 0;) {
172.1961 +            if (excludeList != null) {
172.1962 +                // check if the key is in the excludeList.
172.1963 +                // if so, don't include it in the Map.
172.1964 +                for (int j = 0; j < excludeList.length; j++) {
172.1965 +                    if ((excludeList[j] != null) &&
172.1966 +                        (excludeList[j].equalsIgnoreCase(keys[i]))) {
172.1967 +                        skipIt = true;
172.1968 +                        break;
172.1969 +                    }
172.1970 +                }
172.1971 +            }
172.1972 +            if (!skipIt) {
172.1973 +                List<String> l = m.get(keys[i]);
172.1974 +                if (l == null) {
172.1975 +                    l = new ArrayList<String>();
172.1976 +                    m.put(keys[i], l);
172.1977 +                }
172.1978 +                l.add(values[i]);
172.1979 +            } else {
172.1980 +                // reset the flag
172.1981 +                skipIt = false;
172.1982 +            }
172.1983 +        }
172.1984 +
172.1985 +        if (include != null) {
172.1986 +            Iterator entries = include.entrySet().iterator();
172.1987 +            while (entries.hasNext()) {
172.1988 +                Map.Entry entry = (Map.Entry)entries.next();
172.1989 +                List l = (List)m.get(entry.getKey());
172.1990 +                if (l == null) {
172.1991 +                    l = new ArrayList();
172.1992 +                    m.put((String)entry.getKey(), l);
172.1993 +                }
172.1994 +                l.add(entry.getValue());
172.1995 +            }
172.1996 +        }
172.1997 +
172.1998 +        for (String key : m.keySet()) {
172.1999 +            m.put(key, Collections.unmodifiableList(m.get(key)));
172.2000 +        }
172.2001 +
172.2002 +        return Collections.unmodifiableMap(m);
172.2003 +    }
172.2004 +
172.2005 +    /** Prints the key-value pairs represented by this
172.2006 +        header.  Also prints the RFC required blank line
172.2007 +        at the end. Omits pairs with a null key. */
172.2008 +    public synchronized void print(PrintStream p) {
172.2009 +        for (int i = 0; i < nkeys; i++)
172.2010 +            if (keys[i] != null) {
172.2011 +                p.print(keys[i] +
172.2012 +                    (values[i] != null ? ": "+values[i]: "") + "\r\n");
172.2013 +            }
172.2014 +        p.print("\r\n");
172.2015 +        p.flush();
172.2016 +    }
172.2017 +
172.2018 +    /** Adds a key value pair to the end of the
172.2019 +        header.  Duplicates are allowed */
172.2020 +    public synchronized void add(String k, String v) {
172.2021 +        grow();
172.2022 +        keys[nkeys] = k;
172.2023 +        values[nkeys] = v;
172.2024 +        nkeys++;
172.2025 +    }
172.2026 +
172.2027 +    /** Prepends a key value pair to the beginning of the
172.2028 +        header.  Duplicates are allowed */
172.2029 +    public synchronized void prepend(String k, String v) {
172.2030 +        grow();
172.2031 +        for (int i = nkeys; i > 0; i--) {
172.2032 +            keys[i] = keys[i-1];
172.2033 +            values[i] = values[i-1];
172.2034 +        }
172.2035 +        keys[0] = k;
172.2036 +        values[0] = v;
172.2037 +        nkeys++;
172.2038 +    }
172.2039 +
172.2040 +    /** Overwrite the previous key/val pair at location 'i'
172.2041 +     * with the new k/v.  If the index didn't exist before
172.2042 +     * the key/val is simply tacked onto the end.
172.2043 +     */
172.2044 +
172.2045 +    public synchronized void set(int i, String k, String v) {
172.2046 +        grow();
172.2047 +        if (i < 0) {
172.2048 +            return;
172.2049 +        } else if (i >= nkeys) {
172.2050 +            add(k, v);
172.2051 +        } else {
172.2052 +            keys[i] = k;
172.2053 +            values[i] = v;
172.2054 +        }
172.2055 +    }
172.2056 +
172.2057 +
172.2058 +    /** grow the key/value arrays as needed */
172.2059 +
172.2060 +    private void grow() {
172.2061 +        if (keys == null || nkeys >= keys.length) {
172.2062 +            String[] nk = new String[nkeys + 4];
172.2063 +            String[] nv = new String[nkeys + 4];
172.2064 +            if (keys != null)
172.2065 +                System.arraycopy(keys, 0, nk, 0, nkeys);
172.2066 +            if (values != null)
172.2067 +                System.arraycopy(values, 0, nv, 0, nkeys);
172.2068 +            keys = nk;
172.2069 +            values = nv;
172.2070 +        }
172.2071 +    }
172.2072 +
172.2073 +    /**
172.2074 +     * Remove the key from the header. If there are multiple values under
172.2075 +     * the same key, they are all removed.
172.2076 +     * Nothing is done if the key doesn't exist.
172.2077 +     * After a remove, the other pairs' order are not changed.
172.2078 +     * @param k the key to remove
172.2079 +     */
172.2080 +    public synchronized void remove(String k) {
172.2081 +        if(k == null) {
172.2082 +            for (int i = 0; i < nkeys; i++) {
172.2083 +                while (keys[i] == null && i < nkeys) {
172.2084 +                    for(int j=i; j<nkeys-1; j++) {
172.2085 +                        keys[j] = keys[j+1];
172.2086 +                        values[j] = values[j+1];
172.2087 +                    }
172.2088 +                    nkeys--;
172.2089 +                }
172.2090 +            }
172.2091 +        } else {
172.2092 +            for (int i = 0; i < nkeys; i++) {
172.2093 +                while (k.equalsIgnoreCase(keys[i]) && i < nkeys) {
172.2094 +                    for(int j=i; j<nkeys-1; j++) {
172.2095 +                        keys[j] = keys[j+1];
172.2096 +                        values[j] = values[j+1];
172.2097 +                    }
172.2098 +                    nkeys--;
172.2099 +                }
172.2100 +            }
172.2101 +        }
172.2102 +    }
172.2103 +
172.2104 +    /** Sets the value of a key.  If the key already
172.2105 +        exists in the header, it's value will be
172.2106 +        changed.  Otherwise a new key/value pair will
172.2107 +        be added to the end of the header. */
172.2108 +    public synchronized void set(String k, String v) {
172.2109 +        for (int i = nkeys; --i >= 0;)
172.2110 +            if (k.equalsIgnoreCase(keys[i])) {
172.2111 +                values[i] = v;
172.2112 +                return;
172.2113 +            }
172.2114 +        add(k, v);
172.2115 +    }
172.2116 +
172.2117 +    /** Set's the value of a key only if there is no
172.2118 +     *  key with that value already.
172.2119 +     */
172.2120 +
172.2121 +    public synchronized void setIfNotSet(String k, String v) {
172.2122 +        if (findValue(k) == null) {
172.2123 +            add(k, v);
172.2124 +        }
172.2125 +    }
172.2126 +
172.2127 +    /** Convert a message-id string to canonical form (strips off
172.2128 +        leading and trailing <>s) */
172.2129 +    public static String canonicalID(String id) {
172.2130 +        if (id == null)
172.2131 +            return "";
172.2132 +        int st = 0;
172.2133 +        int len = id.length();
172.2134 +        boolean substr = false;
172.2135 +        int c;
172.2136 +        while (st < len && ((c = id.charAt(st)) == '<' ||
172.2137 +                            c <= ' ')) {
172.2138 +            st++;
172.2139 +            substr = true;
172.2140 +        }
172.2141 +        while (st < len && ((c = id.charAt(len - 1)) == '>' ||
172.2142 +                            c <= ' ')) {
172.2143 +            len--;
172.2144 +            substr = true;
172.2145 +        }
172.2146 +        return substr ? id.substring(st, len) : id;
172.2147 +    }
172.2148 +
172.2149 +    /** Parse a MIME header from an input stream. */
172.2150 +    public void parseHeader(InputStream is) throws java.io.IOException {
172.2151 +        synchronized (this) {
172.2152 +            nkeys = 0;
172.2153 +        }
172.2154 +        mergeHeader(is);
172.2155 +    }
172.2156 +
172.2157 +    /** Parse and merge a MIME header from an input stream. */
172.2158 +    public void mergeHeader(InputStream is) throws java.io.IOException {
172.2159 +        if (is == null)
172.2160 +            return;
172.2161 +        char s[] = new char[10];
172.2162 +        int firstc = is.read();
172.2163 +        while (firstc != '\n' && firstc != '\r' && firstc >= 0) {
172.2164 +            int len = 0;
172.2165 +            int keyend = -1;
172.2166 +            int c;
172.2167 +            boolean inKey = firstc > ' ';
172.2168 +            s[len++] = (char) firstc;
172.2169 +    parseloop:{
172.2170 +                while ((c = is.read()) >= 0) {
172.2171 +                    switch (c) {
172.2172 +                      case ':':
172.2173 +                        if (inKey && len > 0)
172.2174 +                            keyend = len;
172.2175 +                        inKey = false;
172.2176 +                        break;
172.2177 +                      case '\t':
172.2178 +                        c = ' ';
172.2179 +                      case ' ':
172.2180 +                        inKey = false;
172.2181 +                        break;
172.2182 +                      case '\r':
172.2183 +                      case '\n':
172.2184 +                        firstc = is.read();
172.2185 +                        if (c == '\r' && firstc == '\n') {
172.2186 +                            firstc = is.read();
172.2187 +                            if (firstc == '\r')
172.2188 +                                firstc = is.read();
172.2189 +                        }
172.2190 +                        if (firstc == '\n' || firstc == '\r' || firstc > ' ')
172.2191 +                            break parseloop;
172.2192 +                        /* continuation */
172.2193 +                        c = ' ';
172.2194 +                        break;
172.2195 +                    }
172.2196 +                    if (len >= s.length) {
172.2197 +                        char ns[] = new char[s.length * 2];
172.2198 +                        System.arraycopy(s, 0, ns, 0, len);
172.2199 +                        s = ns;
172.2200 +                    }
172.2201 +                    s[len++] = (char) c;
172.2202 +                }
172.2203 +                firstc = -1;
172.2204 +            }
172.2205 +            while (len > 0 && s[len - 1] <= ' ')
172.2206 +                len--;
172.2207 +            String k;
172.2208 +            if (keyend <= 0) {
172.2209 +                k = null;
172.2210 +                keyend = 0;
172.2211 +            } else {
172.2212 +                k = String.copyValueOf(s, 0, keyend);
172.2213 +                if (keyend < len && s[keyend] == ':')
172.2214 +                    keyend++;
172.2215 +                while (keyend < len && s[keyend] <= ' ')
172.2216 +                    keyend++;
172.2217 +            }
172.2218 +            String v;
172.2219 +            if (keyend >= len)
172.2220 +                v = new String();
172.2221 +            else
172.2222 +                v = String.copyValueOf(s, keyend, len - keyend);
172.2223 +            add(k, v);
172.2224 +        }
172.2225 +    }
172.2226 +
172.2227 +    public synchronized String toString() {
172.2228 +        String result = super.toString() + nkeys + " pairs: ";
172.2229 +        for (int i = 0; i < keys.length && i < nkeys; i++) {
172.2230 +            result += "{"+keys[i]+": "+values[i]+"}";
172.2231 +        }
172.2232 +        return result;
172.2233 +    }
172.2234 +}
172.2235 +
172.2236 +interface ContentHandlerFactory {
172.2237 +
172.2238 +    public ContentHandler createContentHandler(String contentType);
172.2239 +}
172.2240 +
172.2241 +abstract class ContentHandler {
172.2242 +    /**
172.2243 +     * Given a URL connect stream positioned at the beginning of the
172.2244 +     * representation of an object, this method reads that stream and
172.2245 +     * creates an object from it.
172.2246 +     *
172.2247 +     * @param      urlc   a URL connection.
172.2248 +     * @return     the object read by the <code>ContentHandler</code>.
172.2249 +     * @exception  IOException  if an I/O error occurs while reading the object.
172.2250 +     */
172.2251 +    abstract public Object getContent(URLConnection urlc) throws IOException;
172.2252 +
172.2253 +    /**
172.2254 +     * Given a URL connect stream positioned at the beginning of the
172.2255 +     * representation of an object, this method reads that stream and
172.2256 +     * creates an object that matches one of the types specified.
172.2257 +     *
172.2258 +     * The default implementation of this method should call getContent()
172.2259 +     * and screen the return type for a match of the suggested types.
172.2260 +     *
172.2261 +     * @param      urlc   a URL connection.
172.2262 +     * @param      classes      an array of types requested
172.2263 +     * @return     the object read by the <code>ContentHandler</code> that is
172.2264 +     *                 the first match of the suggested types.
172.2265 +     *                 null if none of the requested  are supported.
172.2266 +     * @exception  IOException  if an I/O error occurs while reading the object.
172.2267 +     * @since 1.3
172.2268 +     */
172.2269 +    public Object getContent(URLConnection urlc, Class[] classes) throws IOException {
172.2270 +        Object obj = getContent(urlc);
172.2271 +
172.2272 +        for (int i = 0; i < classes.length; i++) {
172.2273 +          if (classes[i].isInstance(obj)) {
172.2274 +                return obj;
172.2275 +          }
172.2276 +        }
172.2277 +        return null;
172.2278 +    }
172.2279 +
172.2280 +}
172.2281 +class UnknownServiceException extends IOException {
172.2282 +    private static final long serialVersionUID = -4169033248853639508L;
172.2283 +
172.2284 +    /**
172.2285 +     * Constructs a new <code>UnknownServiceException</code> with no
172.2286 +     * detail message.
172.2287 +     */
172.2288 +    public UnknownServiceException() {
172.2289 +    }
172.2290 +
172.2291 +    /**
172.2292 +     * Constructs a new <code>UnknownServiceException</code> with the
172.2293 +     * specified detail message.
172.2294 +     *
172.2295 +     * @param   msg   the detail message.
172.2296 +     */
172.2297 +    public UnknownServiceException(String msg) {
172.2298 +        super(msg);
172.2299 +    }
172.2300 +}
172.2301 +/**
172.2302 + * A simple interface which provides a mechanism to map
172.2303 + * between a file name and a MIME type string.
172.2304 + *
172.2305 + * @author  Steven B. Byrne
172.2306 + * @since   JDK1.1
172.2307 + */
172.2308 +interface FileNameMap {
172.2309 +
172.2310 +    /**
172.2311 +     * Gets the MIME type for the specified file name.
172.2312 +     * @param fileName the specified file name
172.2313 +     * @return a <code>String</code> indicating the MIME
172.2314 +     * type for the specified file name.
172.2315 +     */
172.2316 +    public String getContentTypeFor(String fileName);
172.2317 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/Charset.java	Wed Apr 30 15:04:10 2014 +0200
   173.3 @@ -0,0 +1,765 @@
   173.4 +/*
   173.5 + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   173.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   173.7 + *
   173.8 + * This code is free software; you can redistribute it and/or modify it
   173.9 + * under the terms of the GNU General Public License version 2 only, as
  173.10 + * published by the Free Software Foundation.  Oracle designates this
  173.11 + * particular file as subject to the "Classpath" exception as provided
  173.12 + * by Oracle in the LICENSE file that accompanied this code.
  173.13 + *
  173.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  173.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  173.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  173.17 + * version 2 for more details (a copy is included in the LICENSE file that
  173.18 + * accompanied this code).
  173.19 + *
  173.20 + * You should have received a copy of the GNU General Public License version
  173.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  173.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  173.23 + *
  173.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  173.25 + * or visit www.oracle.com if you need additional information or have any
  173.26 + * questions.
  173.27 + */
  173.28 +
  173.29 +package java.nio.charset;
  173.30 +
  173.31 +//import java.nio.ByteBuffer;
  173.32 +//import java.nio.CharBuffer;
  173.33 +import java.util.Collections;
  173.34 +import java.util.HashSet;
  173.35 +import java.util.Iterator;
  173.36 +import java.util.Locale;
  173.37 +import java.util.Map;
  173.38 +import java.util.Set;
  173.39 +import java.util.SortedMap;
  173.40 +import java.util.TreeMap;
  173.41 +
  173.42 +
  173.43 +/**
  173.44 + * A named mapping between sequences of sixteen-bit Unicode <a
  173.45 + * href="../../lang/Character.html#unicode">code units</a> and sequences of
  173.46 + * bytes.  This class defines methods for creating decoders and encoders and
  173.47 + * for retrieving the various names associated with a charset.  Instances of
  173.48 + * this class are immutable.
  173.49 + *
  173.50 + * <p> This class also defines static methods for testing whether a particular
  173.51 + * charset is supported, for locating charset instances by name, and for
  173.52 + * constructing a map that contains every charset for which support is
  173.53 + * available in the current Java virtual machine.  Support for new charsets can
  173.54 + * be added via the service-provider interface defined in the {@link
  173.55 + * java.nio.charset.spi.CharsetProvider} class.
  173.56 + *
  173.57 + * <p> All of the methods defined in this class are safe for use by multiple
  173.58 + * concurrent threads.
  173.59 + *
  173.60 + *
  173.61 + * <a name="names"><a name="charenc">
  173.62 + * <h4>Charset names</h4>
  173.63 + *
  173.64 + * <p> Charsets are named by strings composed of the following characters:
  173.65 + *
  173.66 + * <ul>
  173.67 + *
  173.68 + *   <li> The uppercase letters <tt>'A'</tt> through <tt>'Z'</tt>
  173.69 + *        (<tt>'&#92;u0041'</tt>&nbsp;through&nbsp;<tt>'&#92;u005a'</tt>),
  173.70 + *
  173.71 + *   <li> The lowercase letters <tt>'a'</tt> through <tt>'z'</tt>
  173.72 + *        (<tt>'&#92;u0061'</tt>&nbsp;through&nbsp;<tt>'&#92;u007a'</tt>),
  173.73 + *
  173.74 + *   <li> The digits <tt>'0'</tt> through <tt>'9'</tt>
  173.75 + *        (<tt>'&#92;u0030'</tt>&nbsp;through&nbsp;<tt>'&#92;u0039'</tt>),
  173.76 + *
  173.77 + *   <li> The dash character <tt>'-'</tt>
  173.78 + *        (<tt>'&#92;u002d'</tt>,&nbsp;<small>HYPHEN-MINUS</small>),
  173.79 + *
  173.80 + *   <li> The plus character <tt>'+'</tt>
  173.81 + *        (<tt>'&#92;u002b'</tt>,&nbsp;<small>PLUS SIGN</small>),
  173.82 + *
  173.83 + *   <li> The period character <tt>'.'</tt>
  173.84 + *        (<tt>'&#92;u002e'</tt>,&nbsp;<small>FULL STOP</small>),
  173.85 + *
  173.86 + *   <li> The colon character <tt>':'</tt>
  173.87 + *        (<tt>'&#92;u003a'</tt>,&nbsp;<small>COLON</small>), and
  173.88 + *
  173.89 + *   <li> The underscore character <tt>'_'</tt>
  173.90 + *        (<tt>'&#92;u005f'</tt>,&nbsp;<small>LOW&nbsp;LINE</small>).
  173.91 + *
  173.92 + * </ul>
  173.93 + *
  173.94 + * A charset name must begin with either a letter or a digit.  The empty string
  173.95 + * is not a legal charset name.  Charset names are not case-sensitive; that is,
  173.96 + * case is always ignored when comparing charset names.  Charset names
  173.97 + * generally follow the conventions documented in <a
  173.98 + * href="http://www.ietf.org/rfc/rfc2278.txt"><i>RFC&nbsp;2278:&nbsp;IANA Charset
  173.99 + * Registration Procedures</i></a>.
 173.100 + *
 173.101 + * <p> Every charset has a <i>canonical name</i> and may also have one or more
 173.102 + * <i>aliases</i>.  The canonical name is returned by the {@link #name() name} method
 173.103 + * of this class.  Canonical names are, by convention, usually in upper case.
 173.104 + * The aliases of a charset are returned by the {@link #aliases() aliases}
 173.105 + * method.
 173.106 + *
 173.107 + * <a name="hn">
 173.108 + *
 173.109 + * <p> Some charsets have an <i>historical name</i> that is defined for
 173.110 + * compatibility with previous versions of the Java platform.  A charset's
 173.111 + * historical name is either its canonical name or one of its aliases.  The
 173.112 + * historical name is returned by the <tt>getEncoding()</tt> methods of the
 173.113 + * {@link java.io.InputStreamReader#getEncoding InputStreamReader} and {@link
 173.114 + * java.io.OutputStreamWriter#getEncoding OutputStreamWriter} classes.
 173.115 + *
 173.116 + * <a name="iana">
 173.117 + *
 173.118 + * <p> If a charset listed in the <a
 173.119 + * href="http://www.iana.org/assignments/character-sets"><i>IANA Charset
 173.120 + * Registry</i></a> is supported by an implementation of the Java platform then
 173.121 + * its canonical name must be the name listed in the registry.  Many charsets
 173.122 + * are given more than one name in the registry, in which case the registry
 173.123 + * identifies one of the names as <i>MIME-preferred</i>.  If a charset has more
 173.124 + * than one registry name then its canonical name must be the MIME-preferred
 173.125 + * name and the other names in the registry must be valid aliases.  If a
 173.126 + * supported charset is not listed in the IANA registry then its canonical name
 173.127 + * must begin with one of the strings <tt>"X-"</tt> or <tt>"x-"</tt>.
 173.128 + *
 173.129 + * <p> The IANA charset registry does change over time, and so the canonical
 173.130 + * name and the aliases of a particular charset may also change over time.  To
 173.131 + * ensure compatibility it is recommended that no alias ever be removed from a
 173.132 + * charset, and that if the canonical name of a charset is changed then its
 173.133 + * previous canonical name be made into an alias.
 173.134 + *
 173.135 + *
 173.136 + * <h4>Standard charsets</h4>
 173.137 + *
 173.138 + * <a name="standard">
 173.139 + *
 173.140 + * <p> Every implementation of the Java platform is required to support the
 173.141 + * following standard charsets.  Consult the release documentation for your
 173.142 + * implementation to see if any other charsets are supported.  The behavior
 173.143 + * of such optional charsets may differ between implementations.
 173.144 + *
 173.145 + * <blockquote><table width="80%" summary="Description of standard charsets">
 173.146 + * <tr><th><p align="left">Charset</p></th><th><p align="left">Description</p></th></tr>
 173.147 + * <tr><td valign=top><tt>US-ASCII</tt></td>
 173.148 + *     <td>Seven-bit ASCII, a.k.a. <tt>ISO646-US</tt>,
 173.149 + *         a.k.a. the Basic Latin block of the Unicode character set</td></tr>
 173.150 + * <tr><td valign=top><tt>ISO-8859-1&nbsp;&nbsp;</tt></td>
 173.151 + *     <td>ISO Latin Alphabet No. 1, a.k.a. <tt>ISO-LATIN-1</tt></td></tr>
 173.152 + * <tr><td valign=top><tt>UTF-8</tt></td>
 173.153 + *     <td>Eight-bit UCS Transformation Format</td></tr>
 173.154 + * <tr><td valign=top><tt>UTF-16BE</tt></td>
 173.155 + *     <td>Sixteen-bit UCS Transformation Format,
 173.156 + *         big-endian byte&nbsp;order</td></tr>
 173.157 + * <tr><td valign=top><tt>UTF-16LE</tt></td>
 173.158 + *     <td>Sixteen-bit UCS Transformation Format,
 173.159 + *         little-endian byte&nbsp;order</td></tr>
 173.160 + * <tr><td valign=top><tt>UTF-16</tt></td>
 173.161 + *     <td>Sixteen-bit UCS Transformation Format,
 173.162 + *         byte&nbsp;order identified by an optional byte-order mark</td></tr>
 173.163 + * </table></blockquote>
 173.164 + *
 173.165 + * <p> The <tt>UTF-8</tt> charset is specified by <a
 173.166 + * href="http://www.ietf.org/rfc/rfc2279.txt"><i>RFC&nbsp;2279</i></a>; the
 173.167 + * transformation format upon which it is based is specified in
 173.168 + * Amendment&nbsp;2 of ISO&nbsp;10646-1 and is also described in the <a
 173.169 + * href="http://www.unicode.org/unicode/standard/standard.html"><i>Unicode
 173.170 + * Standard</i></a>.
 173.171 + *
 173.172 + * <p> The <tt>UTF-16</tt> charsets are specified by <a
 173.173 + * href="http://www.ietf.org/rfc/rfc2781.txt"><i>RFC&nbsp;2781</i></a>; the
 173.174 + * transformation formats upon which they are based are specified in
 173.175 + * Amendment&nbsp;1 of ISO&nbsp;10646-1 and are also described in the <a
 173.176 + * href="http://www.unicode.org/unicode/standard/standard.html"><i>Unicode
 173.177 + * Standard</i></a>.
 173.178 + *
 173.179 + * <p> The <tt>UTF-16</tt> charsets use sixteen-bit quantities and are
 173.180 + * therefore sensitive to byte order.  In these encodings the byte order of a
 173.181 + * stream may be indicated by an initial <i>byte-order mark</i> represented by
 173.182 + * the Unicode character <tt>'&#92;uFEFF'</tt>.  Byte-order marks are handled
 173.183 + * as follows:
 173.184 + *
 173.185 + * <ul>
 173.186 + *
 173.187 + *   <li><p> When decoding, the <tt>UTF-16BE</tt> and <tt>UTF-16LE</tt>
 173.188 + *   charsets interpret the initial byte-order marks as a <small>ZERO-WIDTH
 173.189 + *   NON-BREAKING SPACE</small>; when encoding, they do not write
 173.190 + *   byte-order marks. </p></li>
 173.191 +
 173.192 + *
 173.193 + *   <li><p> When decoding, the <tt>UTF-16</tt> charset interprets the
 173.194 + *   byte-order mark at the beginning of the input stream to indicate the
 173.195 + *   byte-order of the stream but defaults to big-endian if there is no
 173.196 + *   byte-order mark; when encoding, it uses big-endian byte order and writes
 173.197 + *   a big-endian byte-order mark. </p></li>
 173.198 + *
 173.199 + * </ul>
 173.200 + *
 173.201 + * In any case, byte order marks occuring after the first element of an
 173.202 + * input sequence are not omitted since the same code is used to represent
 173.203 + * <small>ZERO-WIDTH NON-BREAKING SPACE</small>.
 173.204 + *
 173.205 + * <p> Every instance of the Java virtual machine has a default charset, which
 173.206 + * may or may not be one of the standard charsets.  The default charset is
 173.207 + * determined during virtual-machine startup and typically depends upon the
 173.208 + * locale and charset being used by the underlying operating system. </p>
 173.209 + *
 173.210 + * <p>The {@link StandardCharsets} class defines constants for each of the
 173.211 + * standard charsets.
 173.212 + *
 173.213 + * <h4>Terminology</h4>
 173.214 + *
 173.215 + * <p> The name of this class is taken from the terms used in
 173.216 + * <a href="http://www.ietf.org/rfc/rfc2278.txt"><i>RFC&nbsp;2278</i></a>.
 173.217 + * In that document a <i>charset</i> is defined as the combination of
 173.218 + * one or more coded character sets and a character-encoding scheme.
 173.219 + * (This definition is confusing; some other software systems define
 173.220 + * <i>charset</i> as a synonym for <i>coded character set</i>.)
 173.221 + *
 173.222 + * <p> A <i>coded character set</i> is a mapping between a set of abstract
 173.223 + * characters and a set of integers.  US-ASCII, ISO&nbsp;8859-1,
 173.224 + * JIS&nbsp;X&nbsp;0201, and Unicode are examples of coded character sets.
 173.225 + *
 173.226 + * <p> Some standards have defined a <i>character set</i> to be simply a
 173.227 + * set of abstract characters without an associated assigned numbering.
 173.228 + * An alphabet is an example of such a character set.  However, the subtle
 173.229 + * distinction between <i>character set</i> and <i>coded character set</i>
 173.230 + * is rarely used in practice; the former has become a short form for the
 173.231 + * latter, including in the Java API specification.
 173.232 + *
 173.233 + * <p> A <i>character-encoding scheme</i> is a mapping between one or more
 173.234 + * coded character sets and a set of octet (eight-bit byte) sequences.
 173.235 + * UTF-8, UTF-16, ISO&nbsp;2022, and EUC are examples of
 173.236 + * character-encoding schemes.  Encoding schemes are often associated with
 173.237 + * a particular coded character set; UTF-8, for example, is used only to
 173.238 + * encode Unicode.  Some schemes, however, are associated with multiple
 173.239 + * coded character sets; EUC, for example, can be used to encode
 173.240 + * characters in a variety of Asian coded character sets.
 173.241 + *
 173.242 + * <p> When a coded character set is used exclusively with a single
 173.243 + * character-encoding scheme then the corresponding charset is usually
 173.244 + * named for the coded character set; otherwise a charset is usually named
 173.245 + * for the encoding scheme and, possibly, the locale of the coded
 173.246 + * character sets that it supports.  Hence <tt>US-ASCII</tt> is both the
 173.247 + * name of a coded character set and of the charset that encodes it, while
 173.248 + * <tt>EUC-JP</tt> is the name of the charset that encodes the
 173.249 + * JIS&nbsp;X&nbsp;0201, JIS&nbsp;X&nbsp;0208, and JIS&nbsp;X&nbsp;0212
 173.250 + * coded character sets for the Japanese language.
 173.251 + *
 173.252 + * <p> The native character encoding of the Java programming language is
 173.253 + * UTF-16.  A charset in the Java platform therefore defines a mapping
 173.254 + * between sequences of sixteen-bit UTF-16 code units (that is, sequences
 173.255 + * of chars) and sequences of bytes. </p>
 173.256 + *
 173.257 + *
 173.258 + * @author Mark Reinhold
 173.259 + * @author JSR-51 Expert Group
 173.260 + * @since 1.4
 173.261 + *
 173.262 + * @see CharsetDecoder
 173.263 + * @see CharsetEncoder
 173.264 + * @see java.nio.charset.spi.CharsetProvider
 173.265 + * @see java.lang.Character
 173.266 + */
 173.267 +
 173.268 +public abstract class Charset
 173.269 +    implements Comparable<Charset>
 173.270 +{
 173.271 +
 173.272 +    /* -- Static methods -- */
 173.273 +
 173.274 +    private static volatile String bugLevel = null;
 173.275 +
 173.276 +    /**
 173.277 +     * Checks that the given string is a legal charset name. </p>
 173.278 +     *
 173.279 +     * @param  s
 173.280 +     *         A purported charset name
 173.281 +     *
 173.282 +     * @throws  IllegalCharsetNameException
 173.283 +     *          If the given name is not a legal charset name
 173.284 +     */
 173.285 +    private static void checkName(String s) {
 173.286 +        int n = s.length();
 173.287 +            if (n == 0)
 173.288 +                throw new IllegalCharsetNameException(s);
 173.289 +        for (int i = 0; i < n; i++) {
 173.290 +            char c = s.charAt(i);
 173.291 +            if (c >= 'A' && c <= 'Z') continue;
 173.292 +            if (c >= 'a' && c <= 'z') continue;
 173.293 +            if (c >= '0' && c <= '9') continue;
 173.294 +            if (c == '-' && i != 0) continue;
 173.295 +            if (c == '+' && i != 0) continue;
 173.296 +            if (c == ':' && i != 0) continue;
 173.297 +            if (c == '_' && i != 0) continue;
 173.298 +            if (c == '.' && i != 0) continue;
 173.299 +            throw new IllegalCharsetNameException(s);
 173.300 +        }
 173.301 +    }
 173.302 +
 173.303 +    // Cache of the most-recently-returned charsets,
 173.304 +    // along with the names that were used to find them
 173.305 +    //
 173.306 +    private static volatile Object[] cache1 = null; // "Level 1" cache
 173.307 +    private static volatile Object[] cache2 = null; // "Level 2" cache
 173.308 +
 173.309 +    private static void cache(String charsetName, Charset cs) {
 173.310 +        cache2 = cache1;
 173.311 +        cache1 = new Object[] { charsetName, cs };
 173.312 +    }
 173.313 +
 173.314 +    // Creates an iterator that walks over the available providers, ignoring
 173.315 +    // those whose lookup or instantiation causes a security exception to be
 173.316 +    // thrown.  Should be invoked with full privileges.
 173.317 +    //
 173.318 +    private static Iterator providers() {
 173.319 +        return Collections.emptyIterator();
 173.320 +    }
 173.321 +
 173.322 +    // Thread-local gate to prevent recursive provider lookups
 173.323 +    private static ThreadLocal<ThreadLocal> gate = new ThreadLocal<ThreadLocal>();
 173.324 +
 173.325 +    private static Charset lookupViaProviders(final String charsetName) {
 173.326 +        return null;
 173.327 +    }
 173.328 +
 173.329 +    /* The extended set of charsets */
 173.330 +    private static Object extendedProviderLock = new Object();
 173.331 +    private static boolean extendedProviderProbed = false;
 173.332 +
 173.333 +
 173.334 +    private static Charset lookupExtendedCharset(String charsetName) {
 173.335 +        return null;
 173.336 +    }
 173.337 +
 173.338 +    private static Charset lookup(String charsetName) {
 173.339 +        if (charsetName == null)
 173.340 +            throw new IllegalArgumentException("Null charset name");
 173.341 +
 173.342 +        Object[] a;
 173.343 +        if ((a = cache1) != null && charsetName.equals(a[0]))
 173.344 +            return (Charset)a[1];
 173.345 +        // We expect most programs to use one Charset repeatedly.
 173.346 +        // We convey a hint to this effect to the VM by putting the
 173.347 +        // level 1 cache miss code in a separate method.
 173.348 +        return lookup2(charsetName);
 173.349 +    }
 173.350 +
 173.351 +    private static Charset lookup2(String charsetName) {
 173.352 +        Object[] a;
 173.353 +        if ((a = cache2) != null && charsetName.equals(a[0])) {
 173.354 +            cache2 = cache1;
 173.355 +            cache1 = a;
 173.356 +            return (Charset)a[1];
 173.357 +        }
 173.358 +
 173.359 +        /* Only need to check the name if we didn't find a charset for it */
 173.360 +        checkName(charsetName);
 173.361 +        return null;
 173.362 +    }
 173.363 +
 173.364 +    /**
 173.365 +     * Tells whether the named charset is supported. </p>
 173.366 +     *
 173.367 +     * @param  charsetName
 173.368 +     *         The name of the requested charset; may be either
 173.369 +     *         a canonical name or an alias
 173.370 +     *
 173.371 +     * @return  <tt>true</tt> if, and only if, support for the named charset
 173.372 +     *          is available in the current Java virtual machine
 173.373 +     *
 173.374 +     * @throws IllegalCharsetNameException
 173.375 +     *         If the given charset name is illegal
 173.376 +     *
 173.377 +     * @throws  IllegalArgumentException
 173.378 +     *          If the given <tt>charsetName</tt> is null
 173.379 +     */
 173.380 +    public static boolean isSupported(String charsetName) {
 173.381 +        return (lookup(charsetName) != null);
 173.382 +    }
 173.383 +
 173.384 +    /**
 173.385 +     * Returns a charset object for the named charset. </p>
 173.386 +     *
 173.387 +     * @param  charsetName
 173.388 +     *         The name of the requested charset; may be either
 173.389 +     *         a canonical name or an alias
 173.390 +     *
 173.391 +     * @return  A charset object for the named charset
 173.392 +     *
 173.393 +     * @throws  IllegalCharsetNameException
 173.394 +     *          If the given charset name is illegal
 173.395 +     *
 173.396 +     * @throws  IllegalArgumentException
 173.397 +     *          If the given <tt>charsetName</tt> is null
 173.398 +     *
 173.399 +     * @throws  UnsupportedCharsetException
 173.400 +     *          If no support for the named charset is available
 173.401 +     *          in this instance of the Java virtual machine
 173.402 +     */
 173.403 +    public static Charset forName(String charsetName) {
 173.404 +        Charset cs = lookup(charsetName);
 173.405 +        if (cs != null)
 173.406 +            return cs;
 173.407 +        throw new UnsupportedCharsetException(charsetName);
 173.408 +    }
 173.409 +
 173.410 +    // Fold charsets from the given iterator into the given map, ignoring
 173.411 +    // charsets whose names already have entries in the map.
 173.412 +    //
 173.413 +    private static void put(Iterator<Charset> i, Map<String,Charset> m) {
 173.414 +        while (i.hasNext()) {
 173.415 +            Charset cs = i.next();
 173.416 +            if (!m.containsKey(cs.name()))
 173.417 +                m.put(cs.name(), cs);
 173.418 +        }
 173.419 +    }
 173.420 +
 173.421 +    /**
 173.422 +     * Constructs a sorted map from canonical charset names to charset objects.
 173.423 +     *
 173.424 +     * <p> The map returned by this method will have one entry for each charset
 173.425 +     * for which support is available in the current Java virtual machine.  If
 173.426 +     * two or more supported charsets have the same canonical name then the
 173.427 +     * resulting map will contain just one of them; which one it will contain
 173.428 +     * is not specified. </p>
 173.429 +     *
 173.430 +     * <p> The invocation of this method, and the subsequent use of the
 173.431 +     * resulting map, may cause time-consuming disk or network I/O operations
 173.432 +     * to occur.  This method is provided for applications that need to
 173.433 +     * enumerate all of the available charsets, for example to allow user
 173.434 +     * charset selection.  This method is not used by the {@link #forName
 173.435 +     * forName} method, which instead employs an efficient incremental lookup
 173.436 +     * algorithm.
 173.437 +     *
 173.438 +     * <p> This method may return different results at different times if new
 173.439 +     * charset providers are dynamically made available to the current Java
 173.440 +     * virtual machine.  In the absence of such changes, the charsets returned
 173.441 +     * by this method are exactly those that can be retrieved via the {@link
 173.442 +     * #forName forName} method.  </p>
 173.443 +     *
 173.444 +     * @return An immutable, case-insensitive map from canonical charset names
 173.445 +     *         to charset objects
 173.446 +     */
 173.447 +    public static SortedMap<String,Charset> availableCharsets() {
 173.448 +        TreeMap<String, Charset> tm = new TreeMap<String,Charset>();
 173.449 +        tm.put("UTF-8", Charset.defaultCharset());
 173.450 +        return tm;
 173.451 +    }
 173.452 +
 173.453 +    private static volatile Charset defaultCharset;
 173.454 +
 173.455 +    /**
 173.456 +     * Returns the default charset of this Java virtual machine.
 173.457 +     *
 173.458 +     * <p> The default charset is determined during virtual-machine startup and
 173.459 +     * typically depends upon the locale and charset of the underlying
 173.460 +     * operating system.
 173.461 +     *
 173.462 +     * @return  A charset object for the default charset
 173.463 +     *
 173.464 +     * @since 1.5
 173.465 +     */
 173.466 +    public static Charset defaultCharset() {
 173.467 +        if (defaultCharset == null) {
 173.468 +            defaultCharset = forName("UTF-8");
 173.469 +        }
 173.470 +        return defaultCharset;
 173.471 +    }
 173.472 +
 173.473 +
 173.474 +    /* -- Instance fields and methods -- */
 173.475 +
 173.476 +    private final String name;          // tickles a bug in oldjavac
 173.477 +    private final String[] aliases;     // tickles a bug in oldjavac
 173.478 +    private Set<String> aliasSet = null;
 173.479 +
 173.480 +    /**
 173.481 +     * Initializes a new charset with the given canonical name and alias
 173.482 +     * set. </p>
 173.483 +     *
 173.484 +     * @param  canonicalName
 173.485 +     *         The canonical name of this charset
 173.486 +     *
 173.487 +     * @param  aliases
 173.488 +     *         An array of this charset's aliases, or null if it has no aliases
 173.489 +     *
 173.490 +     * @throws IllegalCharsetNameException
 173.491 +     *         If the canonical name or any of the aliases are illegal
 173.492 +     */
 173.493 +    protected Charset(String canonicalName, String[] aliases) {
 173.494 +        checkName(canonicalName);
 173.495 +        String[] as = (aliases == null) ? new String[0] : aliases;
 173.496 +        for (int i = 0; i < as.length; i++)
 173.497 +            checkName(as[i]);
 173.498 +        this.name = canonicalName;
 173.499 +        this.aliases = as;
 173.500 +    }
 173.501 +
 173.502 +    /**
 173.503 +     * Returns this charset's canonical name. </p>
 173.504 +     *
 173.505 +     * @return  The canonical name of this charset
 173.506 +     */
 173.507 +    public final String name() {
 173.508 +        return name;
 173.509 +    }
 173.510 +
 173.511 +    /**
 173.512 +     * Returns a set containing this charset's aliases. </p>
 173.513 +     *
 173.514 +     * @return  An immutable set of this charset's aliases
 173.515 +     */
 173.516 +    public final Set<String> aliases() {
 173.517 +        if (aliasSet != null)
 173.518 +            return aliasSet;
 173.519 +        int n = aliases.length;
 173.520 +        HashSet<String> hs = new HashSet<String>(n);
 173.521 +        for (int i = 0; i < n; i++)
 173.522 +            hs.add(aliases[i]);
 173.523 +        aliasSet = Collections.unmodifiableSet(hs);
 173.524 +        return aliasSet;
 173.525 +    }
 173.526 +
 173.527 +    /**
 173.528 +     * Returns this charset's human-readable name for the default locale.
 173.529 +     *
 173.530 +     * <p> The default implementation of this method simply returns this
 173.531 +     * charset's canonical name.  Concrete subclasses of this class may
 173.532 +     * override this method in order to provide a localized display name. </p>
 173.533 +     *
 173.534 +     * @return  The display name of this charset in the default locale
 173.535 +     */
 173.536 +    public String displayName() {
 173.537 +        return name;
 173.538 +    }
 173.539 +
 173.540 +    /**
 173.541 +     * Tells whether or not this charset is registered in the <a
 173.542 +     * href="http://www.iana.org/assignments/character-sets">IANA Charset
 173.543 +     * Registry</a>.  </p>
 173.544 +     *
 173.545 +     * @return  <tt>true</tt> if, and only if, this charset is known by its
 173.546 +     *          implementor to be registered with the IANA
 173.547 +     */
 173.548 +    public final boolean isRegistered() {
 173.549 +        return !name.startsWith("X-") && !name.startsWith("x-");
 173.550 +    }
 173.551 +
 173.552 +    /**
 173.553 +     * Returns this charset's human-readable name for the given locale.
 173.554 +     *
 173.555 +     * <p> The default implementation of this method simply returns this
 173.556 +     * charset's canonical name.  Concrete subclasses of this class may
 173.557 +     * override this method in order to provide a localized display name. </p>
 173.558 +     *
 173.559 +     * @param  locale
 173.560 +     *         The locale for which the display name is to be retrieved
 173.561 +     *
 173.562 +     * @return  The display name of this charset in the given locale
 173.563 +     */
 173.564 +    public String displayName(Locale locale) {
 173.565 +        return name;
 173.566 +    }
 173.567 +
 173.568 +    /**
 173.569 +     * Tells whether or not this charset contains the given charset.
 173.570 +     *
 173.571 +     * <p> A charset <i>C</i> is said to <i>contain</i> a charset <i>D</i> if,
 173.572 +     * and only if, every character representable in <i>D</i> is also
 173.573 +     * representable in <i>C</i>.  If this relationship holds then it is
 173.574 +     * guaranteed that every string that can be encoded in <i>D</i> can also be
 173.575 +     * encoded in <i>C</i> without performing any replacements.
 173.576 +     *
 173.577 +     * <p> That <i>C</i> contains <i>D</i> does not imply that each character
 173.578 +     * representable in <i>C</i> by a particular byte sequence is represented
 173.579 +     * in <i>D</i> by the same byte sequence, although sometimes this is the
 173.580 +     * case.
 173.581 +     *
 173.582 +     * <p> Every charset contains itself.
 173.583 +     *
 173.584 +     * <p> This method computes an approximation of the containment relation:
 173.585 +     * If it returns <tt>true</tt> then the given charset is known to be
 173.586 +     * contained by this charset; if it returns <tt>false</tt>, however, then
 173.587 +     * it is not necessarily the case that the given charset is not contained
 173.588 +     * in this charset.
 173.589 +     *
 173.590 +     * @return  <tt>true</tt> if the given charset is contained in this charset
 173.591 +     */
 173.592 +    public abstract boolean contains(Charset cs);
 173.593 +
 173.594 +    /**
 173.595 +     * Constructs a new decoder for this charset. </p>
 173.596 +     *
 173.597 +     * @return  A new decoder for this charset
 173.598 +     */
 173.599 +    public abstract CharsetDecoder newDecoder();
 173.600 +
 173.601 +    /**
 173.602 +     * Constructs a new encoder for this charset. </p>
 173.603 +     *
 173.604 +     * @return  A new encoder for this charset
 173.605 +     *
 173.606 +     * @throws  UnsupportedOperationException
 173.607 +     *          If this charset does not support encoding
 173.608 +     */
 173.609 +    public abstract CharsetEncoder newEncoder();
 173.610 +
 173.611 +    /**
 173.612 +     * Tells whether or not this charset supports encoding.
 173.613 +     *
 173.614 +     * <p> Nearly all charsets support encoding.  The primary exceptions are
 173.615 +     * special-purpose <i>auto-detect</i> charsets whose decoders can determine
 173.616 +     * which of several possible encoding schemes is in use by examining the
 173.617 +     * input byte sequence.  Such charsets do not support encoding because
 173.618 +     * there is no way to determine which encoding should be used on output.
 173.619 +     * Implementations of such charsets should override this method to return
 173.620 +     * <tt>false</tt>. </p>
 173.621 +     *
 173.622 +     * @return  <tt>true</tt> if, and only if, this charset supports encoding
 173.623 +     */
 173.624 +    public boolean canEncode() {
 173.625 +        return true;
 173.626 +    }
 173.627 +
 173.628 +    /**
 173.629 +     * Convenience method that decodes bytes in this charset into Unicode
 173.630 +     * characters.
 173.631 +     *
 173.632 +     * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
 173.633 +     * same result as the expression
 173.634 +     *
 173.635 +     * <pre>
 173.636 +     *     cs.newDecoder()
 173.637 +     *       .onMalformedInput(CodingErrorAction.REPLACE)
 173.638 +     *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
 173.639 +     *       .decode(bb); </pre>
 173.640 +     *
 173.641 +     * except that it is potentially more efficient because it can cache
 173.642 +     * decoders between successive invocations.
 173.643 +     *
 173.644 +     * <p> This method always replaces malformed-input and unmappable-character
 173.645 +     * sequences with this charset's default replacement byte array.  In order
 173.646 +     * to detect such sequences, use the {@link
 173.647 +     * CharsetDecoder#decode(java.nio.ByteBuffer)} method directly.  </p>
 173.648 +     *
 173.649 +     * @param  bb  The byte buffer to be decoded
 173.650 +     *
 173.651 +     * @return  A char buffer containing the decoded characters
 173.652 +     */
 173.653 +//    public final CharBuffer decode(ByteBuffer bb) {
 173.654 +//        try {
 173.655 +//            return ThreadLocalCoders.decoderFor(this)
 173.656 +//                .onMalformedInput(CodingErrorAction.REPLACE)
 173.657 +//                .onUnmappableCharacter(CodingErrorAction.REPLACE)
 173.658 +//                .decode(bb);
 173.659 +//        } catch (CharacterCodingException x) {
 173.660 +//            throw new Error(x);         // Can't happen
 173.661 +//        }
 173.662 +//    }
 173.663 +
 173.664 +    /**
 173.665 +     * Convenience method that encodes Unicode characters into bytes in this
 173.666 +     * charset.
 173.667 +     *
 173.668 +     * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
 173.669 +     * same result as the expression
 173.670 +     *
 173.671 +     * <pre>
 173.672 +     *     cs.newEncoder()
 173.673 +     *       .onMalformedInput(CodingErrorAction.REPLACE)
 173.674 +     *       .onUnmappableCharacter(CodingErrorAction.REPLACE)
 173.675 +     *       .encode(bb); </pre>
 173.676 +     *
 173.677 +     * except that it is potentially more efficient because it can cache
 173.678 +     * encoders between successive invocations.
 173.679 +     *
 173.680 +     * <p> This method always replaces malformed-input and unmappable-character
 173.681 +     * sequences with this charset's default replacement string.  In order to
 173.682 +     * detect such sequences, use the {@link
 173.683 +     * CharsetEncoder#encode(java.nio.CharBuffer)} method directly.  </p>
 173.684 +     *
 173.685 +     * @param  cb  The char buffer to be encoded
 173.686 +     *
 173.687 +     * @return  A byte buffer containing the encoded characters
 173.688 +     */
 173.689 +//    public final ByteBuffer encode(CharBuffer cb) {
 173.690 +//        try {
 173.691 +//            return ThreadLocalCoders.encoderFor(this)
 173.692 +//                .onMalformedInput(CodingErrorAction.REPLACE)
 173.693 +//                .onUnmappableCharacter(CodingErrorAction.REPLACE)
 173.694 +//                .encode(cb);
 173.695 +//        } catch (CharacterCodingException x) {
 173.696 +//            throw new Error(x);         // Can't happen
 173.697 +//        }
 173.698 +//    }
 173.699 +
 173.700 +    /**
 173.701 +     * Convenience method that encodes a string into bytes in this charset.
 173.702 +     *
 173.703 +     * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
 173.704 +     * same result as the expression
 173.705 +     *
 173.706 +     * <pre>
 173.707 +     *     cs.encode(CharBuffer.wrap(s)); </pre>
 173.708 +     *
 173.709 +     * @param  str  The string to be encoded
 173.710 +     *
 173.711 +     * @return  A byte buffer containing the encoded characters
 173.712 +     */
 173.713 +//    public final ByteBuffer encode(String str) {
 173.714 +//        return encode(CharBuffer.wrap(str));
 173.715 +//    }
 173.716 +
 173.717 +    /**
 173.718 +     * Compares this charset to another.
 173.719 +     *
 173.720 +     * <p> Charsets are ordered by their canonical names, without regard to
 173.721 +     * case. </p>
 173.722 +     *
 173.723 +     * @param  that
 173.724 +     *         The charset to which this charset is to be compared
 173.725 +     *
 173.726 +     * @return A negative integer, zero, or a positive integer as this charset
 173.727 +     *         is less than, equal to, or greater than the specified charset
 173.728 +     */
 173.729 +    public final int compareTo(Charset that) {
 173.730 +        return (name().compareToIgnoreCase(that.name()));
 173.731 +    }
 173.732 +
 173.733 +    /**
 173.734 +     * Computes a hashcode for this charset. </p>
 173.735 +     *
 173.736 +     * @return  An integer hashcode
 173.737 +     */
 173.738 +    public final int hashCode() {
 173.739 +        return name().hashCode();
 173.740 +    }
 173.741 +
 173.742 +    /**
 173.743 +     * Tells whether or not this object is equal to another.
 173.744 +     *
 173.745 +     * <p> Two charsets are equal if, and only if, they have the same canonical
 173.746 +     * names.  A charset is never equal to any other type of object.  </p>
 173.747 +     *
 173.748 +     * @return  <tt>true</tt> if, and only if, this charset is equal to the
 173.749 +     *          given object
 173.750 +     */
 173.751 +    public final boolean equals(Object ob) {
 173.752 +        if (!(ob instanceof Charset))
 173.753 +            return false;
 173.754 +        if (this == ob)
 173.755 +            return true;
 173.756 +        return name.equals(((Charset)ob).name());
 173.757 +    }
 173.758 +
 173.759 +    /**
 173.760 +     * Returns a string describing this charset. </p>
 173.761 +     *
 173.762 +     * @return  A string describing this charset
 173.763 +     */
 173.764 +    public final String toString() {
 173.765 +        return name();
 173.766 +    }
 173.767 +
 173.768 +}
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/CharsetDecoder.java	Wed Apr 30 15:04:10 2014 +0200
   174.3 @@ -0,0 +1,970 @@
   174.4 +/*
   174.5 + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   174.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   174.7 + *
   174.8 + * This code is free software; you can redistribute it and/or modify it
   174.9 + * under the terms of the GNU General Public License version 2 only, as
  174.10 + * published by the Free Software Foundation.  Oracle designates this
  174.11 + * particular file as subject to the "Classpath" exception as provided
  174.12 + * by Oracle in the LICENSE file that accompanied this code.
  174.13 + *
  174.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  174.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  174.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  174.17 + * version 2 for more details (a copy is included in the LICENSE file that
  174.18 + * accompanied this code).
  174.19 + *
  174.20 + * You should have received a copy of the GNU General Public License version
  174.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  174.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  174.23 + *
  174.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  174.25 + * or visit www.oracle.com if you need additional information or have any
  174.26 + * questions.
  174.27 + */
  174.28 +
  174.29 +// -- This file was mechanically generated: Do not edit! -- //
  174.30 +
  174.31 +package java.nio.charset;
  174.32 +
  174.33 +//import java.nio.Buffer;
  174.34 +//import java.nio.ByteBuffer;
  174.35 +//import java.nio.CharBuffer;
  174.36 +//import java.nio.BufferOverflowException;
  174.37 +//import java.nio.BufferUnderflowException;
  174.38 +import java.lang.ref.WeakReference;
  174.39 +//import java.nio.charset.CoderMalfunctionError;                  // javadoc
  174.40 +
  174.41 +
  174.42 +/**
  174.43 + * An engine that can transform a sequence of bytes in a specific charset into a sequence of
  174.44 + * sixteen-bit Unicode characters.
  174.45 + *
  174.46 + * <a name="steps">
  174.47 + *
  174.48 + * <p> The input byte sequence is provided in a byte buffer or a series
  174.49 + * of such buffers.  The output character sequence is written to a character buffer
  174.50 + * or a series of such buffers.  A decoder should always be used by making
  174.51 + * the following sequence of method invocations, hereinafter referred to as a
  174.52 + * <i>decoding operation</i>:
  174.53 + *
  174.54 + * <ol>
  174.55 + *
  174.56 + *   <li><p> Reset the decoder via the {@link #reset reset} method, unless it
  174.57 + *   has not been used before; </p></li>
  174.58 + *
  174.59 + *   <li><p> Invoke the {@link #decode decode} method zero or more times, as
  174.60 + *   long as additional input may be available, passing <tt>false</tt> for the
  174.61 + *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
  174.62 + *   output buffer between invocations; </p></li>
  174.63 + *
  174.64 + *   <li><p> Invoke the {@link #decode decode} method one final time, passing
  174.65 + *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
  174.66 + *
  174.67 + *   <li><p> Invoke the {@link #flush flush} method so that the decoder can
  174.68 + *   flush any internal state to the output buffer. </p></li>
  174.69 + *
  174.70 + * </ol>
  174.71 + *
  174.72 + * Each invocation of the {@link #decode decode} method will decode as many
  174.73 + * bytes as possible from the input buffer, writing the resulting characters
  174.74 + * to the output buffer.  The {@link #decode decode} method returns when more
  174.75 + * input is required, when there is not enough room in the output buffer, or
  174.76 + * when a decoding error has occurred.  In each case a {@link CoderResult}
  174.77 + * object is returned to describe the reason for termination.  An invoker can
  174.78 + * examine this object and fill the input buffer, flush the output buffer, or
  174.79 + * attempt to recover from a decoding error, as appropriate, and try again.
  174.80 + *
  174.81 + * <a name="ce">
  174.82 + *
  174.83 + * <p> There are two general types of decoding errors.  If the input byte
  174.84 + * sequence is not legal for this charset then the input is considered <i>malformed</i>.  If
  174.85 + * the input byte sequence is legal but cannot be mapped to a valid
  174.86 + * Unicode character then an <i>unmappable character</i> has been encountered.
  174.87 + *
  174.88 + * <a name="cae">
  174.89 + *
  174.90 + * <p> How a decoding error is handled depends upon the action requested for
  174.91 + * that type of error, which is described by an instance of the {@link
  174.92 + * CodingErrorAction} class.  The possible error actions are to {@link
  174.93 + * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
  174.94 + * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
  174.95 + * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
  174.96 + * </code>replace<code>} the erroneous input with the current value of the
  174.97 + * replacement string.  The replacement
  174.98 + *
  174.99 +
 174.100 +
 174.101 +
 174.102 +
 174.103 +
 174.104 + * has the initial value <tt>"&#92;uFFFD"</tt>;
 174.105 +
 174.106 + *
 174.107 + * its value may be changed via the {@link #replaceWith(java.lang.String)
 174.108 + * replaceWith} method.
 174.109 + *
 174.110 + * <p> The default action for malformed-input and unmappable-character errors
 174.111 + * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
 174.112 + * malformed-input error action may be changed via the {@link
 174.113 + * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
 174.114 + * unmappable-character action may be changed via the {@link
 174.115 + * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
 174.116 + *
 174.117 + * <p> This class is designed to handle many of the details of the decoding
 174.118 + * process, including the implementation of error actions.  A decoder for a
 174.119 + * specific charset, which is a concrete subclass of this class, need only
 174.120 + * implement the abstract {@link #decodeLoop decodeLoop} method, which
 174.121 + * encapsulates the basic decoding loop.  A subclass that maintains internal
 174.122 + * state should, additionally, override the {@link #implFlush implFlush} and
 174.123 + * {@link #implReset implReset} methods.
 174.124 + *
 174.125 + * <p> Instances of this class are not safe for use by multiple concurrent
 174.126 + * threads.  </p>
 174.127 + *
 174.128 + *
 174.129 + * @author Mark Reinhold
 174.130 + * @author JSR-51 Expert Group
 174.131 + * @since 1.4
 174.132 + *
 174.133 + * @see ByteBuffer
 174.134 + * @see CharBuffer
 174.135 + * @see Charset
 174.136 + * @see CharsetEncoder
 174.137 + */
 174.138 +
 174.139 +public abstract class CharsetDecoder {
 174.140 +
 174.141 +    private final Charset charset;
 174.142 +    private final float averageCharsPerByte;
 174.143 +    private final float maxCharsPerByte;
 174.144 +
 174.145 +    private String replacement;
 174.146 +//    private CodingErrorAction malformedInputAction
 174.147 +//        = CodingErrorAction.REPORT;
 174.148 +//    private CodingErrorAction unmappableCharacterAction
 174.149 +//        = CodingErrorAction.REPORT;
 174.150 +
 174.151 +    // Internal states
 174.152 +    //
 174.153 +    private static final int ST_RESET   = 0;
 174.154 +    private static final int ST_CODING  = 1;
 174.155 +    private static final int ST_END     = 2;
 174.156 +    private static final int ST_FLUSHED = 3;
 174.157 +
 174.158 +    private int state = ST_RESET;
 174.159 +
 174.160 +    private static String stateNames[]
 174.161 +        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
 174.162 +
 174.163 +
 174.164 +    /**
 174.165 +     * Initializes a new decoder.  The new decoder will have the given
 174.166 +     * chars-per-byte and replacement values. </p>
 174.167 +     *
 174.168 +     * @param  averageCharsPerByte
 174.169 +     *         A positive float value indicating the expected number of
 174.170 +     *         characters that will be produced for each input byte
 174.171 +     *
 174.172 +     * @param  maxCharsPerByte
 174.173 +     *         A positive float value indicating the maximum number of
 174.174 +     *         characters that will be produced for each input byte
 174.175 +     *
 174.176 +     * @param  replacement
 174.177 +     *         The initial replacement; must not be <tt>null</tt>, must have
 174.178 +     *         non-zero length, must not be longer than maxCharsPerByte,
 174.179 +     *         and must be {@link #isLegalReplacement </code>legal<code>}
 174.180 +     *
 174.181 +     * @throws  IllegalArgumentException
 174.182 +     *          If the preconditions on the parameters do not hold
 174.183 +     */
 174.184 +    private
 174.185 +    CharsetDecoder(Charset cs,
 174.186 +                   float averageCharsPerByte,
 174.187 +                   float maxCharsPerByte,
 174.188 +                   String replacement)
 174.189 +    {
 174.190 +        this.charset = cs;
 174.191 +        if (averageCharsPerByte <= 0.0f)
 174.192 +            throw new IllegalArgumentException("Non-positive "
 174.193 +                                               + "averageCharsPerByte");
 174.194 +        if (maxCharsPerByte <= 0.0f)
 174.195 +            throw new IllegalArgumentException("Non-positive "
 174.196 +                                               + "maxCharsPerByte");
 174.197 +        if (averageCharsPerByte > maxCharsPerByte)
 174.198 +            throw new IllegalArgumentException("averageCharsPerByte"
 174.199 +                                               + " exceeds "
 174.200 +                                               + "maxCharsPerByte");
 174.201 +        this.replacement = replacement;
 174.202 +        this.averageCharsPerByte = averageCharsPerByte;
 174.203 +        this.maxCharsPerByte = maxCharsPerByte;
 174.204 +        replaceWith(replacement);
 174.205 +    }
 174.206 +
 174.207 +    /**
 174.208 +     * Initializes a new decoder.  The new decoder will have the given
 174.209 +     * chars-per-byte values and its replacement will be the
 174.210 +     * string <tt>"&#92;uFFFD"</tt>. </p>
 174.211 +     *
 174.212 +     * @param  averageCharsPerByte
 174.213 +     *         A positive float value indicating the expected number of
 174.214 +     *         characters that will be produced for each input byte
 174.215 +     *
 174.216 +     * @param  maxCharsPerByte
 174.217 +     *         A positive float value indicating the maximum number of
 174.218 +     *         characters that will be produced for each input byte
 174.219 +     *
 174.220 +     * @throws  IllegalArgumentException
 174.221 +     *          If the preconditions on the parameters do not hold
 174.222 +     */
 174.223 +    protected CharsetDecoder(Charset cs,
 174.224 +                             float averageCharsPerByte,
 174.225 +                             float maxCharsPerByte)
 174.226 +    {
 174.227 +        this(cs,
 174.228 +             averageCharsPerByte, maxCharsPerByte,
 174.229 +             "\uFFFD");
 174.230 +    }
 174.231 +
 174.232 +    /**
 174.233 +     * Returns the charset that created this decoder.  </p>
 174.234 +     *
 174.235 +     * @return  This decoder's charset
 174.236 +     */
 174.237 +    public final Charset charset() {
 174.238 +        return charset;
 174.239 +    }
 174.240 +
 174.241 +    /**
 174.242 +     * Returns this decoder's replacement value. </p>
 174.243 +     *
 174.244 +     * @return  This decoder's current replacement,
 174.245 +     *          which is never <tt>null</tt> and is never empty
 174.246 +     */
 174.247 +    public final String replacement() {
 174.248 +        return replacement;
 174.249 +    }
 174.250 +
 174.251 +    /**
 174.252 +     * Changes this decoder's replacement value.
 174.253 +     *
 174.254 +     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
 174.255 +     * method, passing the new replacement, after checking that the new
 174.256 +     * replacement is acceptable.  </p>
 174.257 +     *
 174.258 +     * @param  newReplacement
 174.259 +     *
 174.260 +
 174.261 +     *         The new replacement; must not be <tt>null</tt>
 174.262 +     *         and must have non-zero length
 174.263 +
 174.264 +
 174.265 +
 174.266 +
 174.267 +
 174.268 +
 174.269 +
 174.270 +     *
 174.271 +     * @return  This decoder
 174.272 +     *
 174.273 +     * @throws  IllegalArgumentException
 174.274 +     *          If the preconditions on the parameter do not hold
 174.275 +     */
 174.276 +    public final CharsetDecoder replaceWith(String newReplacement) {
 174.277 +        if (newReplacement == null)
 174.278 +            throw new IllegalArgumentException("Null replacement");
 174.279 +        int len = newReplacement.length();
 174.280 +        if (len == 0)
 174.281 +            throw new IllegalArgumentException("Empty replacement");
 174.282 +        if (len > maxCharsPerByte)
 174.283 +            throw new IllegalArgumentException("Replacement too long");
 174.284 +
 174.285 +
 174.286 +
 174.287 +
 174.288 +        this.replacement = newReplacement;
 174.289 +        implReplaceWith(newReplacement);
 174.290 +        return this;
 174.291 +    }
 174.292 +
 174.293 +    /**
 174.294 +     * Reports a change to this decoder's replacement value.
 174.295 +     *
 174.296 +     * <p> The default implementation of this method does nothing.  This method
 174.297 +     * should be overridden by decoders that require notification of changes to
 174.298 +     * the replacement.  </p>
 174.299 +     *
 174.300 +     * @param  newReplacement
 174.301 +     */
 174.302 +    protected void implReplaceWith(String newReplacement) {
 174.303 +    }
 174.304 +
 174.305 +
 174.306 +
 174.307 +
 174.308 +
 174.309 +
 174.310 +
 174.311 +
 174.312 +
 174.313 +
 174.314 +
 174.315 +
 174.316 +
 174.317 +
 174.318 +
 174.319 +
 174.320 +
 174.321 +
 174.322 +
 174.323 +
 174.324 +
 174.325 +
 174.326 +
 174.327 +
 174.328 +
 174.329 +
 174.330 +
 174.331 +
 174.332 +
 174.333 +
 174.334 +
 174.335 +
 174.336 +
 174.337 +
 174.338 +
 174.339 +
 174.340 +
 174.341 +
 174.342 +
 174.343 +
 174.344 +
 174.345 +    /**
 174.346 +     * Returns this decoder's current action for malformed-input errors.  </p>
 174.347 +     *
 174.348 +     * @return The current malformed-input action, which is never <tt>null</tt>
 174.349 +     */
 174.350 +//    public CodingErrorAction malformedInputAction() {
 174.351 +//        return malformedInputAction;
 174.352 +//    }
 174.353 +
 174.354 +    /**
 174.355 +     * Changes this decoder's action for malformed-input errors.  </p>
 174.356 +     *
 174.357 +     * <p> This method invokes the {@link #implOnMalformedInput
 174.358 +     * implOnMalformedInput} method, passing the new action.  </p>
 174.359 +     *
 174.360 +     * @param  newAction  The new action; must not be <tt>null</tt>
 174.361 +     *
 174.362 +     * @return  This decoder
 174.363 +     *
 174.364 +     * @throws IllegalArgumentException
 174.365 +     *         If the precondition on the parameter does not hold
 174.366 +     */
 174.367 +//    public final CharsetDecoder onMalformedInput(CodingErrorAction newAction) {
 174.368 +//        if (newAction == null)
 174.369 +//            throw new IllegalArgumentException("Null action");
 174.370 +//        malformedInputAction = newAction;
 174.371 +//        implOnMalformedInput(newAction);
 174.372 +//        return this;
 174.373 +//    }
 174.374 +
 174.375 +    /**
 174.376 +     * Reports a change to this decoder's malformed-input action.
 174.377 +     *
 174.378 +     * <p> The default implementation of this method does nothing.  This method
 174.379 +     * should be overridden by decoders that require notification of changes to
 174.380 +     * the malformed-input action.  </p>
 174.381 +     */
 174.382 +//    protected void implOnMalformedInput(CodingErrorAction newAction) { }
 174.383 +
 174.384 +    /**
 174.385 +     * Returns this decoder's current action for unmappable-character errors.
 174.386 +     * </p>
 174.387 +     *
 174.388 +     * @return The current unmappable-character action, which is never
 174.389 +     *         <tt>null</tt>
 174.390 +     */
 174.391 +//    public CodingErrorAction unmappableCharacterAction() {
 174.392 +//        return unmappableCharacterAction;
 174.393 +//    }
 174.394 +
 174.395 +    /**
 174.396 +     * Changes this decoder's action for unmappable-character errors.
 174.397 +     *
 174.398 +     * <p> This method invokes the {@link #implOnUnmappableCharacter
 174.399 +     * implOnUnmappableCharacter} method, passing the new action.  </p>
 174.400 +     *
 174.401 +     * @param  newAction  The new action; must not be <tt>null</tt>
 174.402 +     *
 174.403 +     * @return  This decoder
 174.404 +     *
 174.405 +     * @throws IllegalArgumentException
 174.406 +     *         If the precondition on the parameter does not hold
 174.407 +     */
 174.408 +//    public final CharsetDecoder onUnmappableCharacter(CodingErrorAction
 174.409 +//                                                      newAction)
 174.410 +//    {
 174.411 +//        if (newAction == null)
 174.412 +//            throw new IllegalArgumentException("Null action");
 174.413 +//        unmappableCharacterAction = newAction;
 174.414 +//        implOnUnmappableCharacter(newAction);
 174.415 +//        return this;
 174.416 +//    }
 174.417 +
 174.418 +    /**
 174.419 +     * Reports a change to this decoder's unmappable-character action.
 174.420 +     *
 174.421 +     * <p> The default implementation of this method does nothing.  This method
 174.422 +     * should be overridden by decoders that require notification of changes to
 174.423 +     * the unmappable-character action.  </p>
 174.424 +     */
 174.425 +//    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
 174.426 +
 174.427 +    /**
 174.428 +     * Returns the average number of characters that will be produced for each
 174.429 +     * byte of input.  This heuristic value may be used to estimate the size
 174.430 +     * of the output buffer required for a given input sequence. </p>
 174.431 +     *
 174.432 +     * @return  The average number of characters produced
 174.433 +     *          per byte of input
 174.434 +     */
 174.435 +    public final float averageCharsPerByte() {
 174.436 +        return averageCharsPerByte;
 174.437 +    }
 174.438 +
 174.439 +    /**
 174.440 +     * Returns the maximum number of characters that will be produced for each
 174.441 +     * byte of input.  This value may be used to compute the worst-case size
 174.442 +     * of the output buffer required for a given input sequence. </p>
 174.443 +     *
 174.444 +     * @return  The maximum number of characters that will be produced per
 174.445 +     *          byte of input
 174.446 +     */
 174.447 +    public final float maxCharsPerByte() {
 174.448 +        return maxCharsPerByte;
 174.449 +    }
 174.450 +
 174.451 +    /**
 174.452 +     * Decodes as many bytes as possible from the given input buffer,
 174.453 +     * writing the results to the given output buffer.
 174.454 +     *
 174.455 +     * <p> The buffers are read from, and written to, starting at their current
 174.456 +     * positions.  At most {@link Buffer#remaining in.remaining()} bytes
 174.457 +     * will be read and at most {@link Buffer#remaining out.remaining()}
 174.458 +     * characters will be written.  The buffers' positions will be advanced to
 174.459 +     * reflect the bytes read and the characters written, but their marks and
 174.460 +     * limits will not be modified.
 174.461 +     *
 174.462 +     * <p> In addition to reading bytes from the input buffer and writing
 174.463 +     * characters to the output buffer, this method returns a {@link CoderResult}
 174.464 +     * object to describe its reason for termination:
 174.465 +     *
 174.466 +     * <ul>
 174.467 +     *
 174.468 +     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
 174.469 +     *   input buffer as possible has been decoded.  If there is no further
 174.470 +     *   input then the invoker can proceed to the next step of the
 174.471 +     *   <a href="#steps">decoding operation</a>.  Otherwise this method
 174.472 +     *   should be invoked again with further input.  </p></li>
 174.473 +     *
 174.474 +     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
 174.475 +     *   insufficient space in the output buffer to decode any more bytes.
 174.476 +     *   This method should be invoked again with an output buffer that has
 174.477 +     *   more {@linkplain Buffer#remaining remaining} characters. This is
 174.478 +     *   typically done by draining any decoded characters from the output
 174.479 +     *   buffer.  </p></li>
 174.480 +     *
 174.481 +     *   <li><p> A {@link CoderResult#malformedForLength
 174.482 +     *   </code>malformed-input<code>} result indicates that a malformed-input
 174.483 +     *   error has been detected.  The malformed bytes begin at the input
 174.484 +     *   buffer's (possibly incremented) position; the number of malformed
 174.485 +     *   bytes may be determined by invoking the result object's {@link
 174.486 +     *   CoderResult#length() length} method.  This case applies only if the
 174.487 +     *   {@link #onMalformedInput </code>malformed action<code>} of this decoder
 174.488 +     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
 174.489 +     *   will be ignored or replaced, as requested.  </p></li>
 174.490 +     *
 174.491 +     *   <li><p> An {@link CoderResult#unmappableForLength
 174.492 +     *   </code>unmappable-character<code>} result indicates that an
 174.493 +     *   unmappable-character error has been detected.  The bytes that
 174.494 +     *   decode the unmappable character begin at the input buffer's (possibly
 174.495 +     *   incremented) position; the number of such bytes may be determined
 174.496 +     *   by invoking the result object's {@link CoderResult#length() length}
 174.497 +     *   method.  This case applies only if the {@link #onUnmappableCharacter
 174.498 +     *   </code>unmappable action<code>} of this decoder is {@link
 174.499 +     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
 174.500 +     *   ignored or replaced, as requested.  </p></li>
 174.501 +     *
 174.502 +     * </ul>
 174.503 +     *
 174.504 +     * In any case, if this method is to be reinvoked in the same decoding
 174.505 +     * operation then care should be taken to preserve any bytes remaining
 174.506 +     * in the input buffer so that they are available to the next invocation.
 174.507 +     *
 174.508 +     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
 174.509 +     * the invoker can provide further input beyond that contained in the given
 174.510 +     * input buffer.  If there is a possibility of providing additional input
 174.511 +     * then the invoker should pass <tt>false</tt> for this parameter; if there
 174.512 +     * is no possibility of providing further input then the invoker should
 174.513 +     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
 174.514 +     * common, to pass <tt>false</tt> in one invocation and later discover that
 174.515 +     * no further input was actually available.  It is critical, however, that
 174.516 +     * the final invocation of this method in a sequence of invocations always
 174.517 +     * pass <tt>true</tt> so that any remaining undecoded input will be treated
 174.518 +     * as being malformed.
 174.519 +     *
 174.520 +     * <p> This method works by invoking the {@link #decodeLoop decodeLoop}
 174.521 +     * method, interpreting its results, handling error conditions, and
 174.522 +     * reinvoking it as necessary.  </p>
 174.523 +     *
 174.524 +     *
 174.525 +     * @param  in
 174.526 +     *         The input byte buffer
 174.527 +     *
 174.528 +     * @param  out
 174.529 +     *         The output character buffer
 174.530 +     *
 174.531 +     * @param  endOfInput
 174.532 +     *         <tt>true</tt> if, and only if, the invoker can provide no
 174.533 +     *         additional input bytes beyond those in the given buffer
 174.534 +     *
 174.535 +     * @return  A coder-result object describing the reason for termination
 174.536 +     *
 174.537 +     * @throws  IllegalStateException
 174.538 +     *          If a decoding operation is already in progress and the previous
 174.539 +     *          step was an invocation neither of the {@link #reset reset}
 174.540 +     *          method, nor of this method with a value of <tt>false</tt> for
 174.541 +     *          the <tt>endOfInput</tt> parameter, nor of this method with a
 174.542 +     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
 174.543 +     *          but a return value indicating an incomplete decoding operation
 174.544 +     *
 174.545 +     * @throws  CoderMalfunctionError
 174.546 +     *          If an invocation of the decodeLoop method threw
 174.547 +     *          an unexpected exception
 174.548 +     */
 174.549 +//    public final CoderResult decode(ByteBuffer in, CharBuffer out,
 174.550 +//                                    boolean endOfInput)
 174.551 +//    {
 174.552 +//        int newState = endOfInput ? ST_END : ST_CODING;
 174.553 +//        if ((state != ST_RESET) && (state != ST_CODING)
 174.554 +//            && !(endOfInput && (state == ST_END)))
 174.555 +//            throwIllegalStateException(state, newState);
 174.556 +//        state = newState;
 174.557 +//
 174.558 +//        for (;;) {
 174.559 +//
 174.560 +//            CoderResult cr;
 174.561 +//            try {
 174.562 +//                cr = decodeLoop(in, out);
 174.563 +//            } catch (BufferUnderflowException x) {
 174.564 +//                throw new CoderMalfunctionError(x);
 174.565 +//            } catch (BufferOverflowException x) {
 174.566 +//                throw new CoderMalfunctionError(x);
 174.567 +//            }
 174.568 +//
 174.569 +//            if (cr.isOverflow())
 174.570 +//                return cr;
 174.571 +//
 174.572 +//            if (cr.isUnderflow()) {
 174.573 +//                if (endOfInput && in.hasRemaining()) {
 174.574 +//                    cr = CoderResult.malformedForLength(in.remaining());
 174.575 +//                    // Fall through to malformed-input case
 174.576 +//                } else {
 174.577 +//                    return cr;
 174.578 +//                }
 174.579 +//            }
 174.580 +//
 174.581 +//            CodingErrorAction action = null;
 174.582 +//            if (cr.isMalformed())
 174.583 +//                action = malformedInputAction;
 174.584 +//            else if (cr.isUnmappable())
 174.585 +//                action = unmappableCharacterAction;
 174.586 +//            else
 174.587 +//                assert false : cr.toString();
 174.588 +//
 174.589 +//            if (action == CodingErrorAction.REPORT)
 174.590 +//                return cr;
 174.591 +//
 174.592 +//            if (action == CodingErrorAction.REPLACE) {
 174.593 +//                if (out.remaining() < replacement.length())
 174.594 +//                    return CoderResult.OVERFLOW;
 174.595 +//                out.put(replacement);
 174.596 +//            }
 174.597 +//
 174.598 +//            if ((action == CodingErrorAction.IGNORE)
 174.599 +//                || (action == CodingErrorAction.REPLACE)) {
 174.600 +//                // Skip erroneous input either way
 174.601 +//                in.position(in.position() + cr.length());
 174.602 +//                continue;
 174.603 +//            }
 174.604 +//
 174.605 +//            assert false;
 174.606 +//        }
 174.607 +//
 174.608 +//    }
 174.609 +
 174.610 +    /**
 174.611 +     * Flushes this decoder.
 174.612 +     *
 174.613 +     * <p> Some decoders maintain internal state and may need to write some
 174.614 +     * final characters to the output buffer once the overall input sequence has
 174.615 +     * been read.
 174.616 +     *
 174.617 +     * <p> Any additional output is written to the output buffer beginning at
 174.618 +     * its current position.  At most {@link Buffer#remaining out.remaining()}
 174.619 +     * characters will be written.  The buffer's position will be advanced
 174.620 +     * appropriately, but its mark and limit will not be modified.
 174.621 +     *
 174.622 +     * <p> If this method completes successfully then it returns {@link
 174.623 +     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
 174.624 +     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
 174.625 +     * then this method must be invoked again, with an output buffer that has
 174.626 +     * more room, in order to complete the current <a href="#steps">decoding
 174.627 +     * operation</a>.
 174.628 +     *
 174.629 +     * <p> If this decoder has already been flushed then invoking this method
 174.630 +     * has no effect.
 174.631 +     *
 174.632 +     * <p> This method invokes the {@link #implFlush implFlush} method to
 174.633 +     * perform the actual flushing operation.  </p>
 174.634 +     *
 174.635 +     * @param  out
 174.636 +     *         The output character buffer
 174.637 +     *
 174.638 +     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 174.639 +     *          {@link CoderResult#OVERFLOW}
 174.640 +     *
 174.641 +     * @throws  IllegalStateException
 174.642 +     *          If the previous step of the current decoding operation was an
 174.643 +     *          invocation neither of the {@link #flush flush} method nor of
 174.644 +     *          the three-argument {@link
 174.645 +     *          #decode(ByteBuffer,CharBuffer,boolean) decode} method
 174.646 +     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
 174.647 +     *          parameter
 174.648 +     */
 174.649 +//    public final CoderResult flush(CharBuffer out) {
 174.650 +//        if (state == ST_END) {
 174.651 +//            CoderResult cr = implFlush(out);
 174.652 +//            if (cr.isUnderflow())
 174.653 +//                state = ST_FLUSHED;
 174.654 +//            return cr;
 174.655 +//        }
 174.656 +//
 174.657 +//        if (state != ST_FLUSHED)
 174.658 +//            throwIllegalStateException(state, ST_FLUSHED);
 174.659 +//
 174.660 +//        return CoderResult.UNDERFLOW; // Already flushed
 174.661 +//    }
 174.662 +
 174.663 +    /**
 174.664 +     * Flushes this decoder.
 174.665 +     *
 174.666 +     * <p> The default implementation of this method does nothing, and always
 174.667 +     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
 174.668 +     * by decoders that may need to write final characters to the output buffer
 174.669 +     * once the entire input sequence has been read. </p>
 174.670 +     *
 174.671 +     * @param  out
 174.672 +     *         The output character buffer
 174.673 +     *
 174.674 +     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 174.675 +     *          {@link CoderResult#OVERFLOW}
 174.676 +     */
 174.677 +//    protected CoderResult implFlush(CharBuffer out) {
 174.678 +//        return CoderResult.UNDERFLOW;
 174.679 +//    }
 174.680 +
 174.681 +    /**
 174.682 +     * Resets this decoder, clearing any internal state.
 174.683 +     *
 174.684 +     * <p> This method resets charset-independent state and also invokes the
 174.685 +     * {@link #implReset() implReset} method in order to perform any
 174.686 +     * charset-specific reset actions.  </p>
 174.687 +     *
 174.688 +     * @return  This decoder
 174.689 +     *
 174.690 +     */
 174.691 +    public final CharsetDecoder reset() {
 174.692 +        implReset();
 174.693 +        state = ST_RESET;
 174.694 +        return this;
 174.695 +    }
 174.696 +
 174.697 +    /**
 174.698 +     * Resets this decoder, clearing any charset-specific internal state.
 174.699 +     *
 174.700 +     * <p> The default implementation of this method does nothing.  This method
 174.701 +     * should be overridden by decoders that maintain internal state.  </p>
 174.702 +     */
 174.703 +    protected void implReset() { }
 174.704 +
 174.705 +    /**
 174.706 +     * Decodes one or more bytes into one or more characters.
 174.707 +     *
 174.708 +     * <p> This method encapsulates the basic decoding loop, decoding as many
 174.709 +     * bytes as possible until it either runs out of input, runs out of room
 174.710 +     * in the output buffer, or encounters a decoding error.  This method is
 174.711 +     * invoked by the {@link #decode decode} method, which handles result
 174.712 +     * interpretation and error recovery.
 174.713 +     *
 174.714 +     * <p> The buffers are read from, and written to, starting at their current
 174.715 +     * positions.  At most {@link Buffer#remaining in.remaining()} bytes
 174.716 +     * will be read, and at most {@link Buffer#remaining out.remaining()}
 174.717 +     * characters will be written.  The buffers' positions will be advanced to
 174.718 +     * reflect the bytes read and the characters written, but their marks and
 174.719 +     * limits will not be modified.
 174.720 +     *
 174.721 +     * <p> This method returns a {@link CoderResult} object to describe its
 174.722 +     * reason for termination, in the same manner as the {@link #decode decode}
 174.723 +     * method.  Most implementations of this method will handle decoding errors
 174.724 +     * by returning an appropriate result object for interpretation by the
 174.725 +     * {@link #decode decode} method.  An optimized implementation may instead
 174.726 +     * examine the relevant error action and implement that action itself.
 174.727 +     *
 174.728 +     * <p> An implementation of this method may perform arbitrary lookahead by
 174.729 +     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
 174.730 +     * input.  </p>
 174.731 +     *
 174.732 +     * @param  in
 174.733 +     *         The input byte buffer
 174.734 +     *
 174.735 +     * @param  out
 174.736 +     *         The output character buffer
 174.737 +     *
 174.738 +     * @return  A coder-result object describing the reason for termination
 174.739 +     */
 174.740 +//    protected abstract CoderResult decodeLoop(ByteBuffer in,
 174.741 +//                                              CharBuffer out);
 174.742 +
 174.743 +    /**
 174.744 +     * Convenience method that decodes the remaining content of a single input
 174.745 +     * byte buffer into a newly-allocated character buffer.
 174.746 +     *
 174.747 +     * <p> This method implements an entire <a href="#steps">decoding
 174.748 +     * operation</a>; that is, it resets this decoder, then it decodes the
 174.749 +     * bytes in the given byte buffer, and finally it flushes this
 174.750 +     * decoder.  This method should therefore not be invoked if a decoding
 174.751 +     * operation is already in progress.  </p>
 174.752 +     *
 174.753 +     * @param  in
 174.754 +     *         The input byte buffer
 174.755 +     *
 174.756 +     * @return A newly-allocated character buffer containing the result of the
 174.757 +     *         decoding operation.  The buffer's position will be zero and its
 174.758 +     *         limit will follow the last character written.
 174.759 +     *
 174.760 +     * @throws  IllegalStateException
 174.761 +     *          If a decoding operation is already in progress
 174.762 +     *
 174.763 +     * @throws  MalformedInputException
 174.764 +     *          If the byte sequence starting at the input buffer's current
 174.765 +     *          position is not legal for this charset and the current malformed-input action
 174.766 +     *          is {@link CodingErrorAction#REPORT}
 174.767 +     *
 174.768 +     * @throws  UnmappableCharacterException
 174.769 +     *          If the byte sequence starting at the input buffer's current
 174.770 +     *          position cannot be mapped to an equivalent character sequence and
 174.771 +     *          the current unmappable-character action is {@link
 174.772 +     *          CodingErrorAction#REPORT}
 174.773 +     */
 174.774 +//    public final CharBuffer decode(ByteBuffer in)
 174.775 +//        throws CharacterCodingException
 174.776 +//    {
 174.777 +//        int n = (int)(in.remaining() * averageCharsPerByte());
 174.778 +//        CharBuffer out = CharBuffer.allocate(n);
 174.779 +//
 174.780 +//        if ((n == 0) && (in.remaining() == 0))
 174.781 +//            return out;
 174.782 +//        reset();
 174.783 +//        for (;;) {
 174.784 +//            CoderResult cr = in.hasRemaining() ?
 174.785 +//                decode(in, out, true) : CoderResult.UNDERFLOW;
 174.786 +//            if (cr.isUnderflow())
 174.787 +//                cr = flush(out);
 174.788 +//
 174.789 +//            if (cr.isUnderflow())
 174.790 +//                break;
 174.791 +//            if (cr.isOverflow()) {
 174.792 +//                n = 2*n + 1;    // Ensure progress; n might be 0!
 174.793 +//                CharBuffer o = CharBuffer.allocate(n);
 174.794 +//                out.flip();
 174.795 +//                o.put(out);
 174.796 +//                out = o;
 174.797 +//                continue;
 174.798 +//            }
 174.799 +//            cr.throwException();
 174.800 +//        }
 174.801 +//        out.flip();
 174.802 +//        return out;
 174.803 +//    }
 174.804 +
 174.805 +
 174.806 +
 174.807 +    /**
 174.808 +     * Tells whether or not this decoder implements an auto-detecting charset.
 174.809 +     *
 174.810 +     * <p> The default implementation of this method always returns
 174.811 +     * <tt>false</tt>; it should be overridden by auto-detecting decoders to
 174.812 +     * return <tt>true</tt>.  </p>
 174.813 +     *
 174.814 +     * @return  <tt>true</tt> if, and only if, this decoder implements an
 174.815 +     *          auto-detecting charset
 174.816 +     */
 174.817 +    public boolean isAutoDetecting() {
 174.818 +        return false;
 174.819 +    }
 174.820 +
 174.821 +    /**
 174.822 +     * Tells whether or not this decoder has yet detected a
 174.823 +     * charset&nbsp;&nbsp;<i>(optional operation)</i>.
 174.824 +     *
 174.825 +     * <p> If this decoder implements an auto-detecting charset then at a
 174.826 +     * single point during a decoding operation this method may start returning
 174.827 +     * <tt>true</tt> to indicate that a specific charset has been detected in
 174.828 +     * the input byte sequence.  Once this occurs, the {@link #detectedCharset
 174.829 +     * detectedCharset} method may be invoked to retrieve the detected charset.
 174.830 +     *
 174.831 +     * <p> That this method returns <tt>false</tt> does not imply that no bytes
 174.832 +     * have yet been decoded.  Some auto-detecting decoders are capable of
 174.833 +     * decoding some, or even all, of an input byte sequence without fixing on
 174.834 +     * a particular charset.
 174.835 +     *
 174.836 +     * <p> The default implementation of this method always throws an {@link
 174.837 +     * UnsupportedOperationException}; it should be overridden by
 174.838 +     * auto-detecting decoders to return <tt>true</tt> once the input charset
 174.839 +     * has been determined.  </p>
 174.840 +     *
 174.841 +     * @return  <tt>true</tt> if, and only if, this decoder has detected a
 174.842 +     *          specific charset
 174.843 +     *
 174.844 +     * @throws  UnsupportedOperationException
 174.845 +     *          If this decoder does not implement an auto-detecting charset
 174.846 +     */
 174.847 +    public boolean isCharsetDetected() {
 174.848 +        throw new UnsupportedOperationException();
 174.849 +    }
 174.850 +
 174.851 +    /**
 174.852 +     * Retrieves the charset that was detected by this
 174.853 +     * decoder&nbsp;&nbsp;<i>(optional operation)</i>.
 174.854 +     *
 174.855 +     * <p> If this decoder implements an auto-detecting charset then this
 174.856 +     * method returns the actual charset once it has been detected.  After that
 174.857 +     * point, this method returns the same value for the duration of the
 174.858 +     * current decoding operation.  If not enough input bytes have yet been
 174.859 +     * read to determine the actual charset then this method throws an {@link
 174.860 +     * IllegalStateException}.
 174.861 +     *
 174.862 +     * <p> The default implementation of this method always throws an {@link
 174.863 +     * UnsupportedOperationException}; it should be overridden by
 174.864 +     * auto-detecting decoders to return the appropriate value.  </p>
 174.865 +     *
 174.866 +     * @return  The charset detected by this auto-detecting decoder,
 174.867 +     *          or <tt>null</tt> if the charset has not yet been determined
 174.868 +     *
 174.869 +     * @throws  IllegalStateException
 174.870 +     *          If insufficient bytes have been read to determine a charset
 174.871 +     *
 174.872 +     * @throws  UnsupportedOperationException
 174.873 +     *          If this decoder does not implement an auto-detecting charset
 174.874 +     */
 174.875 +    public Charset detectedCharset() {
 174.876 +        throw new UnsupportedOperationException();
 174.877 +    }
 174.878 +
 174.879 +
 174.880 +
 174.881 +
 174.882 +
 174.883 +
 174.884 +
 174.885 +
 174.886 +
 174.887 +
 174.888 +
 174.889 +
 174.890 +
 174.891 +
 174.892 +
 174.893 +
 174.894 +
 174.895 +
 174.896 +
 174.897 +
 174.898 +
 174.899 +
 174.900 +
 174.901 +
 174.902 +
 174.903 +
 174.904 +
 174.905 +
 174.906 +
 174.907 +
 174.908 +
 174.909 +
 174.910 +
 174.911 +
 174.912 +
 174.913 +
 174.914 +
 174.915 +
 174.916 +
 174.917 +
 174.918 +
 174.919 +
 174.920 +
 174.921 +
 174.922 +
 174.923 +
 174.924 +
 174.925 +
 174.926 +
 174.927 +
 174.928 +
 174.929 +
 174.930 +
 174.931 +
 174.932 +
 174.933 +
 174.934 +
 174.935 +
 174.936 +
 174.937 +
 174.938 +
 174.939 +
 174.940 +
 174.941 +
 174.942 +
 174.943 +
 174.944 +
 174.945 +
 174.946 +
 174.947 +
 174.948 +
 174.949 +
 174.950 +
 174.951 +
 174.952 +
 174.953 +
 174.954 +
 174.955 +
 174.956 +
 174.957 +
 174.958 +
 174.959 +
 174.960 +
 174.961 +
 174.962 +
 174.963 +
 174.964 +
 174.965 +
 174.966 +
 174.967 +
 174.968 +    private void throwIllegalStateException(int from, int to) {
 174.969 +        throw new IllegalStateException("Current state = " + stateNames[from]
 174.970 +                                        + ", new state = " + stateNames[to]);
 174.971 +    }
 174.972 +
 174.973 +}
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/CharsetEncoder.java	Wed Apr 30 15:04:10 2014 +0200
   175.3 @@ -0,0 +1,970 @@
   175.4 +/*
   175.5 + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   175.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   175.7 + *
   175.8 + * This code is free software; you can redistribute it and/or modify it
   175.9 + * under the terms of the GNU General Public License version 2 only, as
  175.10 + * published by the Free Software Foundation.  Oracle designates this
  175.11 + * particular file as subject to the "Classpath" exception as provided
  175.12 + * by Oracle in the LICENSE file that accompanied this code.
  175.13 + *
  175.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  175.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  175.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  175.17 + * version 2 for more details (a copy is included in the LICENSE file that
  175.18 + * accompanied this code).
  175.19 + *
  175.20 + * You should have received a copy of the GNU General Public License version
  175.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  175.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  175.23 + *
  175.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  175.25 + * or visit www.oracle.com if you need additional information or have any
  175.26 + * questions.
  175.27 + */
  175.28 +
  175.29 +// -- This file was mechanically generated: Do not edit! -- //
  175.30 +
  175.31 +package java.nio.charset;
  175.32 +
  175.33 +//import java.nio.Buffer;
  175.34 +//import java.nio.ByteBuffer;
  175.35 +//import java.nio.CharBuffer;
  175.36 +//import java.nio.BufferOverflowException;
  175.37 +//import java.nio.BufferUnderflowException;
  175.38 +import java.lang.ref.WeakReference;
  175.39 +//import java.nio.charset.CoderMalfunctionError;                  // javadoc
  175.40 +
  175.41 +
  175.42 +/**
  175.43 + * An engine that can transform a sequence of sixteen-bit Unicode characters into a sequence of
  175.44 + * bytes in a specific charset.
  175.45 + *
  175.46 + * <a name="steps">
  175.47 + *
  175.48 + * <p> The input character sequence is provided in a character buffer or a series
  175.49 + * of such buffers.  The output byte sequence is written to a byte buffer
  175.50 + * or a series of such buffers.  An encoder should always be used by making
  175.51 + * the following sequence of method invocations, hereinafter referred to as an
  175.52 + * <i>encoding operation</i>:
  175.53 + *
  175.54 + * <ol>
  175.55 + *
  175.56 + *   <li><p> Reset the encoder via the {@link #reset reset} method, unless it
  175.57 + *   has not been used before; </p></li>
  175.58 + *
  175.59 + *   <li><p> Invoke the {@link #encode encode} method zero or more times, as
  175.60 + *   long as additional input may be available, passing <tt>false</tt> for the
  175.61 + *   <tt>endOfInput</tt> argument and filling the input buffer and flushing the
  175.62 + *   output buffer between invocations; </p></li>
  175.63 + *
  175.64 + *   <li><p> Invoke the {@link #encode encode} method one final time, passing
  175.65 + *   <tt>true</tt> for the <tt>endOfInput</tt> argument; and then </p></li>
  175.66 + *
  175.67 + *   <li><p> Invoke the {@link #flush flush} method so that the encoder can
  175.68 + *   flush any internal state to the output buffer. </p></li>
  175.69 + *
  175.70 + * </ol>
  175.71 + *
  175.72 + * Each invocation of the {@link #encode encode} method will encode as many
  175.73 + * characters as possible from the input buffer, writing the resulting bytes
  175.74 + * to the output buffer.  The {@link #encode encode} method returns when more
  175.75 + * input is required, when there is not enough room in the output buffer, or
  175.76 + * when an encoding error has occurred.  In each case a {@link CoderResult}
  175.77 + * object is returned to describe the reason for termination.  An invoker can
  175.78 + * examine this object and fill the input buffer, flush the output buffer, or
  175.79 + * attempt to recover from an encoding error, as appropriate, and try again.
  175.80 + *
  175.81 + * <a name="ce">
  175.82 + *
  175.83 + * <p> There are two general types of encoding errors.  If the input character
  175.84 + * sequence is not a legal sixteen-bit Unicode sequence then the input is considered <i>malformed</i>.  If
  175.85 + * the input character sequence is legal but cannot be mapped to a valid
  175.86 + * byte sequence in the given charset then an <i>unmappable character</i> has been encountered.
  175.87 + *
  175.88 + * <a name="cae">
  175.89 + *
  175.90 + * <p> How an encoding error is handled depends upon the action requested for
  175.91 + * that type of error, which is described by an instance of the {@link
  175.92 + * CodingErrorAction} class.  The possible error actions are to {@link
  175.93 + * CodingErrorAction#IGNORE </code>ignore<code>} the erroneous input, {@link
  175.94 + * CodingErrorAction#REPORT </code>report<code>} the error to the invoker via
  175.95 + * the returned {@link CoderResult} object, or {@link CodingErrorAction#REPLACE
  175.96 + * </code>replace<code>} the erroneous input with the current value of the
  175.97 + * replacement byte array.  The replacement
  175.98 + *
  175.99 +
 175.100 + * is initially set to the encoder's default replacement, which often
 175.101 + * (but not always) has the initial value&nbsp;<tt>{</tt>&nbsp;<tt>(byte)'?'</tt>&nbsp;<tt>}</tt>;
 175.102 +
 175.103 +
 175.104 +
 175.105 +
 175.106 + *
 175.107 + * its value may be changed via the {@link #replaceWith(byte[])
 175.108 + * replaceWith} method.
 175.109 + *
 175.110 + * <p> The default action for malformed-input and unmappable-character errors
 175.111 + * is to {@link CodingErrorAction#REPORT </code>report<code>} them.  The
 175.112 + * malformed-input error action may be changed via the {@link
 175.113 + * #onMalformedInput(CodingErrorAction) onMalformedInput} method; the
 175.114 + * unmappable-character action may be changed via the {@link
 175.115 + * #onUnmappableCharacter(CodingErrorAction) onUnmappableCharacter} method.
 175.116 + *
 175.117 + * <p> This class is designed to handle many of the details of the encoding
 175.118 + * process, including the implementation of error actions.  An encoder for a
 175.119 + * specific charset, which is a concrete subclass of this class, need only
 175.120 + * implement the abstract {@link #encodeLoop encodeLoop} method, which
 175.121 + * encapsulates the basic encoding loop.  A subclass that maintains internal
 175.122 + * state should, additionally, override the {@link #implFlush implFlush} and
 175.123 + * {@link #implReset implReset} methods.
 175.124 + *
 175.125 + * <p> Instances of this class are not safe for use by multiple concurrent
 175.126 + * threads.  </p>
 175.127 + *
 175.128 + *
 175.129 + * @author Mark Reinhold
 175.130 + * @author JSR-51 Expert Group
 175.131 + * @since 1.4
 175.132 + *
 175.133 + * @see ByteBuffer
 175.134 + * @see CharBuffer
 175.135 + * @see Charset
 175.136 + * @see CharsetDecoder
 175.137 + */
 175.138 +
 175.139 +public abstract class CharsetEncoder {
 175.140 +
 175.141 +    private final Charset charset;
 175.142 +    private final float averageBytesPerChar;
 175.143 +    private final float maxBytesPerChar;
 175.144 +
 175.145 +    private byte[] replacement;
 175.146 +//    private CodingErrorAction malformedInputAction
 175.147 +//        = CodingErrorAction.REPORT;
 175.148 +//    private CodingErrorAction unmappableCharacterAction
 175.149 +//        = CodingErrorAction.REPORT;
 175.150 +
 175.151 +    // Internal states
 175.152 +    //
 175.153 +    private static final int ST_RESET   = 0;
 175.154 +    private static final int ST_CODING  = 1;
 175.155 +    private static final int ST_END     = 2;
 175.156 +    private static final int ST_FLUSHED = 3;
 175.157 +
 175.158 +    private int state = ST_RESET;
 175.159 +
 175.160 +    private static String stateNames[]
 175.161 +        = { "RESET", "CODING", "CODING_END", "FLUSHED" };
 175.162 +
 175.163 +
 175.164 +    /**
 175.165 +     * Initializes a new encoder.  The new encoder will have the given
 175.166 +     * bytes-per-char and replacement values. </p>
 175.167 +     *
 175.168 +     * @param  averageBytesPerChar
 175.169 +     *         A positive float value indicating the expected number of
 175.170 +     *         bytes that will be produced for each input character
 175.171 +     *
 175.172 +     * @param  maxBytesPerChar
 175.173 +     *         A positive float value indicating the maximum number of
 175.174 +     *         bytes that will be produced for each input character
 175.175 +     *
 175.176 +     * @param  replacement
 175.177 +     *         The initial replacement; must not be <tt>null</tt>, must have
 175.178 +     *         non-zero length, must not be longer than maxBytesPerChar,
 175.179 +     *         and must be {@link #isLegalReplacement </code>legal<code>}
 175.180 +     *
 175.181 +     * @throws  IllegalArgumentException
 175.182 +     *          If the preconditions on the parameters do not hold
 175.183 +     */
 175.184 +    protected
 175.185 +    CharsetEncoder(Charset cs,
 175.186 +                   float averageBytesPerChar,
 175.187 +                   float maxBytesPerChar,
 175.188 +                   byte[] replacement)
 175.189 +    {
 175.190 +        this.charset = cs;
 175.191 +        if (averageBytesPerChar <= 0.0f)
 175.192 +            throw new IllegalArgumentException("Non-positive "
 175.193 +                                               + "averageBytesPerChar");
 175.194 +        if (maxBytesPerChar <= 0.0f)
 175.195 +            throw new IllegalArgumentException("Non-positive "
 175.196 +                                               + "maxBytesPerChar");
 175.197 +        if (averageBytesPerChar > maxBytesPerChar)
 175.198 +            throw new IllegalArgumentException("averageBytesPerChar"
 175.199 +                                               + " exceeds "
 175.200 +                                               + "maxBytesPerChar");
 175.201 +        this.replacement = replacement;
 175.202 +        this.averageBytesPerChar = averageBytesPerChar;
 175.203 +        this.maxBytesPerChar = maxBytesPerChar;
 175.204 +        replaceWith(replacement);
 175.205 +    }
 175.206 +
 175.207 +    /**
 175.208 +     * Initializes a new encoder.  The new encoder will have the given
 175.209 +     * bytes-per-char values and its replacement will be the
 175.210 +     * byte array <tt>{</tt>&nbsp;<tt>(byte)'?'</tt>&nbsp;<tt>}</tt>. </p>
 175.211 +     *
 175.212 +     * @param  averageBytesPerChar
 175.213 +     *         A positive float value indicating the expected number of
 175.214 +     *         bytes that will be produced for each input character
 175.215 +     *
 175.216 +     * @param  maxBytesPerChar
 175.217 +     *         A positive float value indicating the maximum number of
 175.218 +     *         bytes that will be produced for each input character
 175.219 +     *
 175.220 +     * @throws  IllegalArgumentException
 175.221 +     *          If the preconditions on the parameters do not hold
 175.222 +     */
 175.223 +    protected CharsetEncoder(Charset cs,
 175.224 +                             float averageBytesPerChar,
 175.225 +                             float maxBytesPerChar)
 175.226 +    {
 175.227 +        this(cs,
 175.228 +             averageBytesPerChar, maxBytesPerChar,
 175.229 +             new byte[] { (byte)'?' });
 175.230 +    }
 175.231 +
 175.232 +    /**
 175.233 +     * Returns the charset that created this encoder.  </p>
 175.234 +     *
 175.235 +     * @return  This encoder's charset
 175.236 +     */
 175.237 +    public final Charset charset() {
 175.238 +        return charset;
 175.239 +    }
 175.240 +
 175.241 +    /**
 175.242 +     * Returns this encoder's replacement value. </p>
 175.243 +     *
 175.244 +     * @return  This encoder's current replacement,
 175.245 +     *          which is never <tt>null</tt> and is never empty
 175.246 +     */
 175.247 +    public final byte[] replacement() {
 175.248 +        return replacement;
 175.249 +    }
 175.250 +
 175.251 +    /**
 175.252 +     * Changes this encoder's replacement value.
 175.253 +     *
 175.254 +     * <p> This method invokes the {@link #implReplaceWith implReplaceWith}
 175.255 +     * method, passing the new replacement, after checking that the new
 175.256 +     * replacement is acceptable.  </p>
 175.257 +     *
 175.258 +     * @param  newReplacement
 175.259 +     *
 175.260 +
 175.261 +
 175.262 +
 175.263 +
 175.264 +
 175.265 +     *         The new replacement; must not be <tt>null</tt>, must have
 175.266 +     *         non-zero length, must not be longer than the value returned by
 175.267 +     *         the {@link #maxBytesPerChar() maxBytesPerChar} method, and
 175.268 +     *         must be {@link #isLegalReplacement </code>legal<code>}
 175.269 +
 175.270 +     *
 175.271 +     * @return  This encoder
 175.272 +     *
 175.273 +     * @throws  IllegalArgumentException
 175.274 +     *          If the preconditions on the parameter do not hold
 175.275 +     */
 175.276 +    public final CharsetEncoder replaceWith(byte[] newReplacement) {
 175.277 +        if (newReplacement == null)
 175.278 +            throw new IllegalArgumentException("Null replacement");
 175.279 +        int len = newReplacement.length;
 175.280 +        if (len == 0)
 175.281 +            throw new IllegalArgumentException("Empty replacement");
 175.282 +        if (len > maxBytesPerChar)
 175.283 +            throw new IllegalArgumentException("Replacement too long");
 175.284 +
 175.285 +//        if (!isLegalReplacement(newReplacement))
 175.286 +//            throw new IllegalArgumentException("Illegal replacement");
 175.287 +
 175.288 +        this.replacement = newReplacement;
 175.289 +        implReplaceWith(newReplacement);
 175.290 +        return this;
 175.291 +    }
 175.292 +
 175.293 +    /**
 175.294 +     * Reports a change to this encoder's replacement value.
 175.295 +     *
 175.296 +     * <p> The default implementation of this method does nothing.  This method
 175.297 +     * should be overridden by encoders that require notification of changes to
 175.298 +     * the replacement.  </p>
 175.299 +     *
 175.300 +     * @param  newReplacement
 175.301 +     */
 175.302 +    protected void implReplaceWith(byte[] newReplacement) {
 175.303 +    }
 175.304 +
 175.305 +
 175.306 +
 175.307 +    private WeakReference<CharsetDecoder> cachedDecoder = null;
 175.308 +
 175.309 +    /**
 175.310 +     * Tells whether or not the given byte array is a legal replacement value
 175.311 +     * for this encoder.
 175.312 +     *
 175.313 +     * <p> A replacement is legal if, and only if, it is a legal sequence of
 175.314 +     * bytes in this encoder's charset; that is, it must be possible to decode
 175.315 +     * the replacement into one or more sixteen-bit Unicode characters.
 175.316 +     *
 175.317 +     * <p> The default implementation of this method is not very efficient; it
 175.318 +     * should generally be overridden to improve performance.  </p>
 175.319 +     *
 175.320 +     * @param  repl  The byte array to be tested
 175.321 +     *
 175.322 +     * @return  <tt>true</tt> if, and only if, the given byte array
 175.323 +     *          is a legal replacement value for this encoder
 175.324 +     */
 175.325 +//    public boolean isLegalReplacement(byte[] repl) {
 175.326 +//        WeakReference<CharsetDecoder> wr = cachedDecoder;
 175.327 +//        CharsetDecoder dec = null;
 175.328 +//        if ((wr == null) || ((dec = wr.get()) == null)) {
 175.329 +//            dec = charset().newDecoder();
 175.330 +//            dec.onMalformedInput(CodingErrorAction.REPORT);
 175.331 +//            dec.onUnmappableCharacter(CodingErrorAction.REPORT);
 175.332 +//            cachedDecoder = new WeakReference<CharsetDecoder>(dec);
 175.333 +//        } else {
 175.334 +//            dec.reset();
 175.335 +//        }
 175.336 +//        ByteBuffer bb = ByteBuffer.wrap(repl);
 175.337 +//        CharBuffer cb = CharBuffer.allocate((int)(bb.remaining()
 175.338 +//                                                  * dec.maxCharsPerByte()));
 175.339 +//        CoderResult cr = dec.decode(bb, cb, true);
 175.340 +//        return !cr.isError();
 175.341 +//    }
 175.342 +
 175.343 +
 175.344 +
 175.345 +    /**
 175.346 +     * Returns this encoder's current action for malformed-input errors.  </p>
 175.347 +     *
 175.348 +     * @return The current malformed-input action, which is never <tt>null</tt>
 175.349 +     */
 175.350 +//    public CodingErrorAction malformedInputAction() {
 175.351 +//        return malformedInputAction;
 175.352 +//    }
 175.353 +
 175.354 +    /**
 175.355 +     * Changes this encoder's action for malformed-input errors.  </p>
 175.356 +     *
 175.357 +     * <p> This method invokes the {@link #implOnMalformedInput
 175.358 +     * implOnMalformedInput} method, passing the new action.  </p>
 175.359 +     *
 175.360 +     * @param  newAction  The new action; must not be <tt>null</tt>
 175.361 +     *
 175.362 +     * @return  This encoder
 175.363 +     *
 175.364 +     * @throws IllegalArgumentException
 175.365 +     *         If the precondition on the parameter does not hold
 175.366 +     */
 175.367 +//    public final CharsetEncoder onMalformedInput(CodingErrorAction newAction) {
 175.368 +//        if (newAction == null)
 175.369 +//            throw new IllegalArgumentException("Null action");
 175.370 +//        malformedInputAction = newAction;
 175.371 +//        implOnMalformedInput(newAction);
 175.372 +//        return this;
 175.373 +//    }
 175.374 +
 175.375 +    /**
 175.376 +     * Reports a change to this encoder's malformed-input action.
 175.377 +     *
 175.378 +     * <p> The default implementation of this method does nothing.  This method
 175.379 +     * should be overridden by encoders that require notification of changes to
 175.380 +     * the malformed-input action.  </p>
 175.381 +     */
 175.382 +//    protected void implOnMalformedInput(CodingErrorAction newAction) { }
 175.383 +
 175.384 +    /**
 175.385 +     * Returns this encoder's current action for unmappable-character errors.
 175.386 +     * </p>
 175.387 +     *
 175.388 +     * @return The current unmappable-character action, which is never
 175.389 +     *         <tt>null</tt>
 175.390 +     */
 175.391 +//    public CodingErrorAction unmappableCharacterAction() {
 175.392 +//        return unmappableCharacterAction;
 175.393 +//    }
 175.394 +
 175.395 +    /**
 175.396 +     * Changes this encoder's action for unmappable-character errors.
 175.397 +     *
 175.398 +     * <p> This method invokes the {@link #implOnUnmappableCharacter
 175.399 +     * implOnUnmappableCharacter} method, passing the new action.  </p>
 175.400 +     *
 175.401 +     * @param  newAction  The new action; must not be <tt>null</tt>
 175.402 +     *
 175.403 +     * @return  This encoder
 175.404 +     *
 175.405 +     * @throws IllegalArgumentException
 175.406 +     *         If the precondition on the parameter does not hold
 175.407 +     */
 175.408 +//    public final CharsetEncoder onUnmappableCharacter(CodingErrorAction
 175.409 +//                                                      newAction)
 175.410 +//    {
 175.411 +//        if (newAction == null)
 175.412 +//            throw new IllegalArgumentException("Null action");
 175.413 +//        unmappableCharacterAction = newAction;
 175.414 +//        implOnUnmappableCharacter(newAction);
 175.415 +//        return this;
 175.416 +//    }
 175.417 +
 175.418 +    /**
 175.419 +     * Reports a change to this encoder's unmappable-character action.
 175.420 +     *
 175.421 +     * <p> The default implementation of this method does nothing.  This method
 175.422 +     * should be overridden by encoders that require notification of changes to
 175.423 +     * the unmappable-character action.  </p>
 175.424 +     */
 175.425 +//    protected void implOnUnmappableCharacter(CodingErrorAction newAction) { }
 175.426 +
 175.427 +    /**
 175.428 +     * Returns the average number of bytes that will be produced for each
 175.429 +     * character of input.  This heuristic value may be used to estimate the size
 175.430 +     * of the output buffer required for a given input sequence. </p>
 175.431 +     *
 175.432 +     * @return  The average number of bytes produced
 175.433 +     *          per character of input
 175.434 +     */
 175.435 +    public final float averageBytesPerChar() {
 175.436 +        return averageBytesPerChar;
 175.437 +    }
 175.438 +
 175.439 +    /**
 175.440 +     * Returns the maximum number of bytes that will be produced for each
 175.441 +     * character of input.  This value may be used to compute the worst-case size
 175.442 +     * of the output buffer required for a given input sequence. </p>
 175.443 +     *
 175.444 +     * @return  The maximum number of bytes that will be produced per
 175.445 +     *          character of input
 175.446 +     */
 175.447 +    public final float maxBytesPerChar() {
 175.448 +        return maxBytesPerChar;
 175.449 +    }
 175.450 +
 175.451 +    /**
 175.452 +     * Encodes as many characters as possible from the given input buffer,
 175.453 +     * writing the results to the given output buffer.
 175.454 +     *
 175.455 +     * <p> The buffers are read from, and written to, starting at their current
 175.456 +     * positions.  At most {@link Buffer#remaining in.remaining()} characters
 175.457 +     * will be read and at most {@link Buffer#remaining out.remaining()}
 175.458 +     * bytes will be written.  The buffers' positions will be advanced to
 175.459 +     * reflect the characters read and the bytes written, but their marks and
 175.460 +     * limits will not be modified.
 175.461 +     *
 175.462 +     * <p> In addition to reading characters from the input buffer and writing
 175.463 +     * bytes to the output buffer, this method returns a {@link CoderResult}
 175.464 +     * object to describe its reason for termination:
 175.465 +     *
 175.466 +     * <ul>
 175.467 +     *
 175.468 +     *   <li><p> {@link CoderResult#UNDERFLOW} indicates that as much of the
 175.469 +     *   input buffer as possible has been encoded.  If there is no further
 175.470 +     *   input then the invoker can proceed to the next step of the
 175.471 +     *   <a href="#steps">encoding operation</a>.  Otherwise this method
 175.472 +     *   should be invoked again with further input.  </p></li>
 175.473 +     *
 175.474 +     *   <li><p> {@link CoderResult#OVERFLOW} indicates that there is
 175.475 +     *   insufficient space in the output buffer to encode any more characters.
 175.476 +     *   This method should be invoked again with an output buffer that has
 175.477 +     *   more {@linkplain Buffer#remaining remaining} bytes. This is
 175.478 +     *   typically done by draining any encoded bytes from the output
 175.479 +     *   buffer.  </p></li>
 175.480 +     *
 175.481 +     *   <li><p> A {@link CoderResult#malformedForLength
 175.482 +     *   </code>malformed-input<code>} result indicates that a malformed-input
 175.483 +     *   error has been detected.  The malformed characters begin at the input
 175.484 +     *   buffer's (possibly incremented) position; the number of malformed
 175.485 +     *   characters may be determined by invoking the result object's {@link
 175.486 +     *   CoderResult#length() length} method.  This case applies only if the
 175.487 +     *   {@link #onMalformedInput </code>malformed action<code>} of this encoder
 175.488 +     *   is {@link CodingErrorAction#REPORT}; otherwise the malformed input
 175.489 +     *   will be ignored or replaced, as requested.  </p></li>
 175.490 +     *
 175.491 +     *   <li><p> An {@link CoderResult#unmappableForLength
 175.492 +     *   </code>unmappable-character<code>} result indicates that an
 175.493 +     *   unmappable-character error has been detected.  The characters that
 175.494 +     *   encode the unmappable character begin at the input buffer's (possibly
 175.495 +     *   incremented) position; the number of such characters may be determined
 175.496 +     *   by invoking the result object's {@link CoderResult#length() length}
 175.497 +     *   method.  This case applies only if the {@link #onUnmappableCharacter
 175.498 +     *   </code>unmappable action<code>} of this encoder is {@link
 175.499 +     *   CodingErrorAction#REPORT}; otherwise the unmappable character will be
 175.500 +     *   ignored or replaced, as requested.  </p></li>
 175.501 +     *
 175.502 +     * </ul>
 175.503 +     *
 175.504 +     * In any case, if this method is to be reinvoked in the same encoding
 175.505 +     * operation then care should be taken to preserve any characters remaining
 175.506 +     * in the input buffer so that they are available to the next invocation.
 175.507 +     *
 175.508 +     * <p> The <tt>endOfInput</tt> parameter advises this method as to whether
 175.509 +     * the invoker can provide further input beyond that contained in the given
 175.510 +     * input buffer.  If there is a possibility of providing additional input
 175.511 +     * then the invoker should pass <tt>false</tt> for this parameter; if there
 175.512 +     * is no possibility of providing further input then the invoker should
 175.513 +     * pass <tt>true</tt>.  It is not erroneous, and in fact it is quite
 175.514 +     * common, to pass <tt>false</tt> in one invocation and later discover that
 175.515 +     * no further input was actually available.  It is critical, however, that
 175.516 +     * the final invocation of this method in a sequence of invocations always
 175.517 +     * pass <tt>true</tt> so that any remaining unencoded input will be treated
 175.518 +     * as being malformed.
 175.519 +     *
 175.520 +     * <p> This method works by invoking the {@link #encodeLoop encodeLoop}
 175.521 +     * method, interpreting its results, handling error conditions, and
 175.522 +     * reinvoking it as necessary.  </p>
 175.523 +     *
 175.524 +     *
 175.525 +     * @param  in
 175.526 +     *         The input character buffer
 175.527 +     *
 175.528 +     * @param  out
 175.529 +     *         The output byte buffer
 175.530 +     *
 175.531 +     * @param  endOfInput
 175.532 +     *         <tt>true</tt> if, and only if, the invoker can provide no
 175.533 +     *         additional input characters beyond those in the given buffer
 175.534 +     *
 175.535 +     * @return  A coder-result object describing the reason for termination
 175.536 +     *
 175.537 +     * @throws  IllegalStateException
 175.538 +     *          If an encoding operation is already in progress and the previous
 175.539 +     *          step was an invocation neither of the {@link #reset reset}
 175.540 +     *          method, nor of this method with a value of <tt>false</tt> for
 175.541 +     *          the <tt>endOfInput</tt> parameter, nor of this method with a
 175.542 +     *          value of <tt>true</tt> for the <tt>endOfInput</tt> parameter
 175.543 +     *          but a return value indicating an incomplete encoding operation
 175.544 +     *
 175.545 +     * @throws  CoderMalfunctionError
 175.546 +     *          If an invocation of the encodeLoop method threw
 175.547 +     *          an unexpected exception
 175.548 +     */
 175.549 +//    public final CoderResult encode(CharBuffer in, ByteBuffer out,
 175.550 +//                                    boolean endOfInput)
 175.551 +//    {
 175.552 +//        int newState = endOfInput ? ST_END : ST_CODING;
 175.553 +//        if ((state != ST_RESET) && (state != ST_CODING)
 175.554 +//            && !(endOfInput && (state == ST_END)))
 175.555 +//            throwIllegalStateException(state, newState);
 175.556 +//        state = newState;
 175.557 +//
 175.558 +//        for (;;) {
 175.559 +//
 175.560 +//            CoderResult cr;
 175.561 +//            try {
 175.562 +//                cr = encodeLoop(in, out);
 175.563 +//            } catch (BufferUnderflowException x) {
 175.564 +//                throw new CoderMalfunctionError(x);
 175.565 +//            } catch (BufferOverflowException x) {
 175.566 +//                throw new CoderMalfunctionError(x);
 175.567 +//            }
 175.568 +//
 175.569 +//            if (cr.isOverflow())
 175.570 +//                return cr;
 175.571 +//
 175.572 +//            if (cr.isUnderflow()) {
 175.573 +//                if (endOfInput && in.hasRemaining()) {
 175.574 +//                    cr = CoderResult.malformedForLength(in.remaining());
 175.575 +//                    // Fall through to malformed-input case
 175.576 +//                } else {
 175.577 +//                    return cr;
 175.578 +//                }
 175.579 +//            }
 175.580 +//
 175.581 +//            CodingErrorAction action = null;
 175.582 +//            if (cr.isMalformed())
 175.583 +//                action = malformedInputAction;
 175.584 +//            else if (cr.isUnmappable())
 175.585 +//                action = unmappableCharacterAction;
 175.586 +//            else
 175.587 +//                assert false : cr.toString();
 175.588 +//
 175.589 +//            if (action == CodingErrorAction.REPORT)
 175.590 +//                return cr;
 175.591 +//
 175.592 +//            if (action == CodingErrorAction.REPLACE) {
 175.593 +//                if (out.remaining() < replacement.length)
 175.594 +//                    return CoderResult.OVERFLOW;
 175.595 +//                out.put(replacement);
 175.596 +//            }
 175.597 +//
 175.598 +//            if ((action == CodingErrorAction.IGNORE)
 175.599 +//                || (action == CodingErrorAction.REPLACE)) {
 175.600 +//                // Skip erroneous input either way
 175.601 +//                in.position(in.position() + cr.length());
 175.602 +//                continue;
 175.603 +//            }
 175.604 +//
 175.605 +//            assert false;
 175.606 +//        }
 175.607 +//
 175.608 +//    }
 175.609 +
 175.610 +    /**
 175.611 +     * Flushes this encoder.
 175.612 +     *
 175.613 +     * <p> Some encoders maintain internal state and may need to write some
 175.614 +     * final bytes to the output buffer once the overall input sequence has
 175.615 +     * been read.
 175.616 +     *
 175.617 +     * <p> Any additional output is written to the output buffer beginning at
 175.618 +     * its current position.  At most {@link Buffer#remaining out.remaining()}
 175.619 +     * bytes will be written.  The buffer's position will be advanced
 175.620 +     * appropriately, but its mark and limit will not be modified.
 175.621 +     *
 175.622 +     * <p> If this method completes successfully then it returns {@link
 175.623 +     * CoderResult#UNDERFLOW}.  If there is insufficient room in the output
 175.624 +     * buffer then it returns {@link CoderResult#OVERFLOW}.  If this happens
 175.625 +     * then this method must be invoked again, with an output buffer that has
 175.626 +     * more room, in order to complete the current <a href="#steps">encoding
 175.627 +     * operation</a>.
 175.628 +     *
 175.629 +     * <p> If this encoder has already been flushed then invoking this method
 175.630 +     * has no effect.
 175.631 +     *
 175.632 +     * <p> This method invokes the {@link #implFlush implFlush} method to
 175.633 +     * perform the actual flushing operation.  </p>
 175.634 +     *
 175.635 +     * @param  out
 175.636 +     *         The output byte buffer
 175.637 +     *
 175.638 +     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 175.639 +     *          {@link CoderResult#OVERFLOW}
 175.640 +     *
 175.641 +     * @throws  IllegalStateException
 175.642 +     *          If the previous step of the current encoding operation was an
 175.643 +     *          invocation neither of the {@link #flush flush} method nor of
 175.644 +     *          the three-argument {@link
 175.645 +     *          #encode(CharBuffer,ByteBuffer,boolean) encode} method
 175.646 +     *          with a value of <tt>true</tt> for the <tt>endOfInput</tt>
 175.647 +     *          parameter
 175.648 +     */
 175.649 +//    public final CoderResult flush(ByteBuffer out) {
 175.650 +//        if (state == ST_END) {
 175.651 +//            CoderResult cr = implFlush(out);
 175.652 +//            if (cr.isUnderflow())
 175.653 +//                state = ST_FLUSHED;
 175.654 +//            return cr;
 175.655 +//        }
 175.656 +//
 175.657 +//        if (state != ST_FLUSHED)
 175.658 +//            throwIllegalStateException(state, ST_FLUSHED);
 175.659 +//
 175.660 +//        return CoderResult.UNDERFLOW; // Already flushed
 175.661 +//    }
 175.662 +
 175.663 +    /**
 175.664 +     * Flushes this encoder.
 175.665 +     *
 175.666 +     * <p> The default implementation of this method does nothing, and always
 175.667 +     * returns {@link CoderResult#UNDERFLOW}.  This method should be overridden
 175.668 +     * by encoders that may need to write final bytes to the output buffer
 175.669 +     * once the entire input sequence has been read. </p>
 175.670 +     *
 175.671 +     * @param  out
 175.672 +     *         The output byte buffer
 175.673 +     *
 175.674 +     * @return  A coder-result object, either {@link CoderResult#UNDERFLOW} or
 175.675 +     *          {@link CoderResult#OVERFLOW}
 175.676 +     */
 175.677 +//    protected CoderResult implFlush(ByteBuffer out) {
 175.678 +//        return CoderResult.UNDERFLOW;
 175.679 +//    }
 175.680 +
 175.681 +    /**
 175.682 +     * Resets this encoder, clearing any internal state.
 175.683 +     *
 175.684 +     * <p> This method resets charset-independent state and also invokes the
 175.685 +     * {@link #implReset() implReset} method in order to perform any
 175.686 +     * charset-specific reset actions.  </p>
 175.687 +     *
 175.688 +     * @return  This encoder
 175.689 +     *
 175.690 +     */
 175.691 +    public final CharsetEncoder reset() {
 175.692 +        implReset();
 175.693 +        state = ST_RESET;
 175.694 +        return this;
 175.695 +    }
 175.696 +
 175.697 +    /**
 175.698 +     * Resets this encoder, clearing any charset-specific internal state.
 175.699 +     *
 175.700 +     * <p> The default implementation of this method does nothing.  This method
 175.701 +     * should be overridden by encoders that maintain internal state.  </p>
 175.702 +     */
 175.703 +    protected void implReset() { }
 175.704 +
 175.705 +    /**
 175.706 +     * Encodes one or more characters into one or more bytes.
 175.707 +     *
 175.708 +     * <p> This method encapsulates the basic encoding loop, encoding as many
 175.709 +     * characters as possible until it either runs out of input, runs out of room
 175.710 +     * in the output buffer, or encounters an encoding error.  This method is
 175.711 +     * invoked by the {@link #encode encode} method, which handles result
 175.712 +     * interpretation and error recovery.
 175.713 +     *
 175.714 +     * <p> The buffers are read from, and written to, starting at their current
 175.715 +     * positions.  At most {@link Buffer#remaining in.remaining()} characters
 175.716 +     * will be read, and at most {@link Buffer#remaining out.remaining()}
 175.717 +     * bytes will be written.  The buffers' positions will be advanced to
 175.718 +     * reflect the characters read and the bytes written, but their marks and
 175.719 +     * limits will not be modified.
 175.720 +     *
 175.721 +     * <p> This method returns a {@link CoderResult} object to describe its
 175.722 +     * reason for termination, in the same manner as the {@link #encode encode}
 175.723 +     * method.  Most implementations of this method will handle encoding errors
 175.724 +     * by returning an appropriate result object for interpretation by the
 175.725 +     * {@link #encode encode} method.  An optimized implementation may instead
 175.726 +     * examine the relevant error action and implement that action itself.
 175.727 +     *
 175.728 +     * <p> An implementation of this method may perform arbitrary lookahead by
 175.729 +     * returning {@link CoderResult#UNDERFLOW} until it receives sufficient
 175.730 +     * input.  </p>
 175.731 +     *
 175.732 +     * @param  in
 175.733 +     *         The input character buffer
 175.734 +     *
 175.735 +     * @param  out
 175.736 +     *         The output byte buffer
 175.737 +     *
 175.738 +     * @return  A coder-result object describing the reason for termination
 175.739 +     */
 175.740 +//    protected abstract CoderResult encodeLoop(CharBuffer in,
 175.741 +//                                              ByteBuffer out);
 175.742 +
 175.743 +    /**
 175.744 +     * Convenience method that encodes the remaining content of a single input
 175.745 +     * character buffer into a newly-allocated byte buffer.
 175.746 +     *
 175.747 +     * <p> This method implements an entire <a href="#steps">encoding
 175.748 +     * operation</a>; that is, it resets this encoder, then it encodes the
 175.749 +     * characters in the given character buffer, and finally it flushes this
 175.750 +     * encoder.  This method should therefore not be invoked if an encoding
 175.751 +     * operation is already in progress.  </p>
 175.752 +     *
 175.753 +     * @param  in
 175.754 +     *         The input character buffer
 175.755 +     *
 175.756 +     * @return A newly-allocated byte buffer containing the result of the
 175.757 +     *         encoding operation.  The buffer's position will be zero and its
 175.758 +     *         limit will follow the last byte written.
 175.759 +     *
 175.760 +     * @throws  IllegalStateException
 175.761 +     *          If an encoding operation is already in progress
 175.762 +     *
 175.763 +     * @throws  MalformedInputException
 175.764 +     *          If the character sequence starting at the input buffer's current
 175.765 +     *          position is not a legal sixteen-bit Unicode sequence and the current malformed-input action
 175.766 +     *          is {@link CodingErrorAction#REPORT}
 175.767 +     *
 175.768 +     * @throws  UnmappableCharacterException
 175.769 +     *          If the character sequence starting at the input buffer's current
 175.770 +     *          position cannot be mapped to an equivalent byte sequence and
 175.771 +     *          the current unmappable-character action is {@link
 175.772 +     *          CodingErrorAction#REPORT}
 175.773 +     */
 175.774 +//    public final ByteBuffer encode(CharBuffer in)
 175.775 +//        throws CharacterCodingException
 175.776 +//    {
 175.777 +//        int n = (int)(in.remaining() * averageBytesPerChar());
 175.778 +//        ByteBuffer out = ByteBuffer.allocate(n);
 175.779 +//
 175.780 +//        if ((n == 0) && (in.remaining() == 0))
 175.781 +//            return out;
 175.782 +//        reset();
 175.783 +//        for (;;) {
 175.784 +//            CoderResult cr = in.hasRemaining() ?
 175.785 +//                encode(in, out, true) : CoderResult.UNDERFLOW;
 175.786 +//            if (cr.isUnderflow())
 175.787 +//                cr = flush(out);
 175.788 +//
 175.789 +//            if (cr.isUnderflow())
 175.790 +//                break;
 175.791 +//            if (cr.isOverflow()) {
 175.792 +//                n = 2*n + 1;    // Ensure progress; n might be 0!
 175.793 +//                ByteBuffer o = ByteBuffer.allocate(n);
 175.794 +//                out.flip();
 175.795 +//                o.put(out);
 175.796 +//                out = o;
 175.797 +//                continue;
 175.798 +//            }
 175.799 +//            cr.throwException();
 175.800 +//        }
 175.801 +//        out.flip();
 175.802 +//        return out;
 175.803 +//    }
 175.804 +
 175.805 +
 175.806 +
 175.807 +
 175.808 +
 175.809 +
 175.810 +
 175.811 +
 175.812 +
 175.813 +
 175.814 +
 175.815 +
 175.816 +
 175.817 +
 175.818 +
 175.819 +
 175.820 +
 175.821 +
 175.822 +
 175.823 +
 175.824 +
 175.825 +
 175.826 +
 175.827 +
 175.828 +
 175.829 +
 175.830 +
 175.831 +
 175.832 +
 175.833 +
 175.834 +
 175.835 +
 175.836 +
 175.837 +
 175.838 +
 175.839 +
 175.840 +
 175.841 +
 175.842 +
 175.843 +
 175.844 +
 175.845 +
 175.846 +
 175.847 +
 175.848 +
 175.849 +
 175.850 +
 175.851 +
 175.852 +
 175.853 +
 175.854 +
 175.855 +
 175.856 +
 175.857 +
 175.858 +
 175.859 +
 175.860 +
 175.861 +
 175.862 +
 175.863 +
 175.864 +
 175.865 +
 175.866 +
 175.867 +
 175.868 +
 175.869 +
 175.870 +
 175.871 +
 175.872 +
 175.873 +
 175.874 +
 175.875 +
 175.876 +
 175.877 +
 175.878 +
 175.879 +
 175.880 +
 175.881 +
 175.882 +
 175.883 +//    private boolean canEncode(CharBuffer cb) {
 175.884 +//        if (state == ST_FLUSHED)
 175.885 +//            reset();
 175.886 +//        else if (state != ST_RESET)
 175.887 +//            throwIllegalStateException(state, ST_CODING);
 175.888 +//        CodingErrorAction ma = malformedInputAction();
 175.889 +//        CodingErrorAction ua = unmappableCharacterAction();
 175.890 +//        try {
 175.891 +//            onMalformedInput(CodingErrorAction.REPORT);
 175.892 +//            onUnmappableCharacter(CodingErrorAction.REPORT);
 175.893 +//            encode(cb);
 175.894 +//        } catch (CharacterCodingException x) {
 175.895 +//            return false;
 175.896 +//        } finally {
 175.897 +//            onMalformedInput(ma);
 175.898 +//            onUnmappableCharacter(ua);
 175.899 +//            reset();
 175.900 +//        }
 175.901 +//        return true;
 175.902 +//    }
 175.903 +
 175.904 +    /**
 175.905 +     * Tells whether or not this encoder can encode the given character.
 175.906 +     *
 175.907 +     * <p> This method returns <tt>false</tt> if the given character is a
 175.908 +     * surrogate character; such characters can be interpreted only when they
 175.909 +     * are members of a pair consisting of a high surrogate followed by a low
 175.910 +     * surrogate.  The {@link #canEncode(java.lang.CharSequence)
 175.911 +     * canEncode(CharSequence)} method may be used to test whether or not a
 175.912 +     * character sequence can be encoded.
 175.913 +     *
 175.914 +     * <p> This method may modify this encoder's state; it should therefore not
 175.915 +     * be invoked if an <a href="#steps">encoding operation</a> is already in
 175.916 +     * progress.
 175.917 +     *
 175.918 +     * <p> The default implementation of this method is not very efficient; it
 175.919 +     * should generally be overridden to improve performance.  </p>
 175.920 +     *
 175.921 +     * @return  <tt>true</tt> if, and only if, this encoder can encode
 175.922 +     *          the given character
 175.923 +     *
 175.924 +     * @throws  IllegalStateException
 175.925 +     *          If an encoding operation is already in progress
 175.926 +     */
 175.927 +//    public boolean canEncode(char c) {
 175.928 +//        CharBuffer cb = CharBuffer.allocate(1);
 175.929 +//        cb.put(c);
 175.930 +//        cb.flip();
 175.931 +//        return canEncode(cb);
 175.932 +//    }
 175.933 +
 175.934 +    /**
 175.935 +     * Tells whether or not this encoder can encode the given character
 175.936 +     * sequence.
 175.937 +     *
 175.938 +     * <p> If this method returns <tt>false</tt> for a particular character
 175.939 +     * sequence then more information about why the sequence cannot be encoded
 175.940 +     * may be obtained by performing a full <a href="#steps">encoding
 175.941 +     * operation</a>.
 175.942 +     *
 175.943 +     * <p> This method may modify this encoder's state; it should therefore not
 175.944 +     * be invoked if an encoding operation is already in progress.
 175.945 +     *
 175.946 +     * <p> The default implementation of this method is not very efficient; it
 175.947 +     * should generally be overridden to improve performance.  </p>
 175.948 +     *
 175.949 +     * @return  <tt>true</tt> if, and only if, this encoder can encode
 175.950 +     *          the given character without throwing any exceptions and without
 175.951 +     *          performing any replacements
 175.952 +     *
 175.953 +     * @throws  IllegalStateException
 175.954 +     *          If an encoding operation is already in progress
 175.955 +     */
 175.956 +//    public boolean canEncode(CharSequence cs) {
 175.957 +//        CharBuffer cb;
 175.958 +//        if (cs instanceof CharBuffer)
 175.959 +//            cb = ((CharBuffer)cs).duplicate();
 175.960 +//        else
 175.961 +//            cb = CharBuffer.wrap(cs.toString());
 175.962 +//        return canEncode(cb);
 175.963 +//    }
 175.964 +
 175.965 +
 175.966 +
 175.967 +
 175.968 +    private void throwIllegalStateException(int from, int to) {
 175.969 +        throw new IllegalStateException("Current state = " + stateNames[from]
 175.970 +                                        + ", new state = " + stateNames[to]);
 175.971 +    }
 175.972 +
 175.973 +}
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/IllegalCharsetNameException.java	Wed Apr 30 15:04:10 2014 +0200
   176.3 @@ -0,0 +1,68 @@
   176.4 +/*
   176.5 + * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
   176.6 + *
   176.7 + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
   176.8 + *
   176.9 + *
  176.10 + *
  176.11 + *
  176.12 + *
  176.13 + *
  176.14 + *
  176.15 + *
  176.16 + *
  176.17 + *
  176.18 + *
  176.19 + *
  176.20 + *
  176.21 + *
  176.22 + *
  176.23 + *
  176.24 + *
  176.25 + *
  176.26 + *
  176.27 + *
  176.28 + *
  176.29 + */
  176.30 +
  176.31 +// -- This file was mechanically generated: Do not edit! -- //
  176.32 +
  176.33 +package java.nio.charset;
  176.34 +
  176.35 +
  176.36 +/**
  176.37 + * Unchecked exception thrown when a string that is not a
  176.38 + * <a href=Charset.html#names>legal charset name</a> is used as such.
  176.39 + *
  176.40 + * @since 1.4
  176.41 + */
  176.42 +
  176.43 +public class IllegalCharsetNameException
  176.44 +    extends IllegalArgumentException
  176.45 +{
  176.46 +
  176.47 +    private static final long serialVersionUID = 1457525358470002989L;
  176.48 +
  176.49 +    private String charsetName;
  176.50 +
  176.51 +    /**
  176.52 +     * Constructs an instance of this class. </p>
  176.53 +     *
  176.54 +     * @param  charsetName
  176.55 +     *         The illegal charset name
  176.56 +     */
  176.57 +    public IllegalCharsetNameException(String charsetName) {
  176.58 +        super(String.valueOf(charsetName));
  176.59 +	this.charsetName = charsetName;
  176.60 +    }
  176.61 +
  176.62 +    /**
  176.63 +     * Retrieves the illegal charset name. </p>
  176.64 +     *
  176.65 +     * @return  The illegal charset name
  176.66 +     */
  176.67 +    public String getCharsetName() {
  176.68 +        return charsetName;
  176.69 +    }
  176.70 +
  176.71 +}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/rt/emul/compact/src/main/java/java/nio/charset/UnsupportedCharsetException.java	Wed Apr 30 15:04:10 2014 +0200
   177.3 @@ -0,0 +1,68 @@
   177.4 +/*
   177.5 + * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
   177.6 + *
   177.7 + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
   177.8 + *
   177.9 + *
  177.10 + *
  177.11 + *
  177.12 + *
  177.13 + *
  177.14 + *
  177.15 + *
  177.16 + *
  177.17 + *
  177.18 + *
  177.19 + *
  177.20 + *
  177.21 + *
  177.22 + *
  177.23 + *
  177.24 + *
  177.25 + *
  177.26 + *
  177.27 + *
  177.28 + *
  177.29 + */
  177.30 +
  177.31 +// -- This file was mechanically generated: Do not edit! -- //
  177.32 +
  177.33 +package java.nio.charset;
  177.34 +
  177.35 +
  177.36 +/**
  177.37 + * Unchecked exception thrown when no support is available
  177.38 + * for a requested charset.
  177.39 + *
  177.40 + * @since 1.4
  177.41 + */
  177.42 +
  177.43 +public class UnsupportedCharsetException
  177.44 +    extends IllegalArgumentException
  177.45 +{
  177.46 +
  177.47 +    private static final long serialVersionUID = 1490765524727386367L;
  177.48 +
  177.49 +    private String charsetName;
  177.50 +
  177.51 +    /**
  177.52 +     * Constructs an instance of this class. </p>
  177.53 +     *
  177.54 +     * @param  charsetName
  177.55 +     *         The name of the unsupported charset
  177.56 +     */
  177.57 +    public UnsupportedCharsetException(String charsetName) {
  177.58 +        super(String.valueOf(charsetName));
  177.59 +	this.charsetName = charsetName;
  177.60 +    }
  177.61 +
  177.62 +    /**
  177.63 +     * Retrieves the name of the unsupported charset. </p>
  177.64 +     *
  177.65 +     * @return  The name of the unsupported charset
  177.66 +     */
  177.67 +    public String getCharsetName() {
  177.68 +        return charsetName;
  177.69 +    }
  177.70 +
  177.71 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/rt/emul/compact/src/main/java/java/security/AccessController.java	Wed Apr 30 15:04:10 2014 +0200
   178.3 @@ -0,0 +1,504 @@
   178.4 +/*
   178.5 + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
   178.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   178.7 + *
   178.8 + * This code is free software; you can redistribute it and/or modify it
   178.9 + * under the terms of the GNU General Public License version 2 only, as
  178.10 + * published by the Free Software Foundation.  Oracle designates this
  178.11 + * particular file as subject to the "Classpath" exception as provided
  178.12 + * by Oracle in the LICENSE file that accompanied this code.
  178.13 + *
  178.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  178.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  178.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  178.17 + * version 2 for more details (a copy is included in the LICENSE file that
  178.18 + * accompanied this code).
  178.19 + *
  178.20 + * You should have received a copy of the GNU General Public License version
  178.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  178.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  178.23 + *
  178.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  178.25 + * or visit www.oracle.com if you need additional information or have any
  178.26 + * questions.
  178.27 + */
  178.28 +
  178.29 +package java.security;
  178.30 +
  178.31 +/**
  178.32 + * <p> The AccessController class is used for access control operations
  178.33 + * and decisions.
  178.34 + *
  178.35 + * <p> More specifically, the AccessController class is used for
  178.36 + * three purposes:
  178.37 + *
  178.38 + * <ul>
  178.39 + * <li> to decide whether an access to a critical system
  178.40 + * resource is to be allowed or denied, based on the security policy
  178.41 + * currently in effect,<p>
  178.42 + * <li>to mark code as being "privileged", thus affecting subsequent
  178.43 + * access determinations, and<p>
  178.44 + * <li>to obtain a "snapshot" of the current calling context so
  178.45 + * access-control decisions from a different context can be made with
  178.46 + * respect to the saved context. </ul>
  178.47 + *
  178.48 + * <p> The {@link #checkPermission(Permission) checkPermission} method
  178.49 + * determines whether the access request indicated by a specified
  178.50 + * permission should be granted or denied. A sample call appears
  178.51 + * below. In this example, <code>checkPermission</code> will determine
  178.52 + * whether or not to grant "read" access to the file named "testFile" in
  178.53 + * the "/temp" directory.
  178.54 + *
  178.55 + * <pre>
  178.56 + *
  178.57 + * FilePermission perm = new FilePermission("/temp/testFile", "read");
  178.58 + * AccessController.checkPermission(perm);
  178.59 + *
  178.60 + * </pre>
  178.61 + *
  178.62 + * <p> If a requested access is allowed,
  178.63 + * <code>checkPermission</code> returns quietly. If denied, an
  178.64 + * AccessControlException is
  178.65 + * thrown. AccessControlException can also be thrown if the requested
  178.66 + * permission is of an incorrect type or contains an invalid value.
  178.67 + * Such information is given whenever possible.
  178.68 + *
  178.69 + * Suppose the current thread traversed m callers, in the order of caller 1
  178.70 + * to caller 2 to caller m. Then caller m invoked the
  178.71 + * <code>checkPermission</code> method.
  178.72 + * The <code>checkPermission </code>method determines whether access
  178.73 + * is granted or denied based on the following algorithm:
  178.74 + *
  178.75 + *  <pre> {@code
  178.76 + * for (int i = m; i > 0; i--) {
  178.77 + *
  178.78 + *     if (caller i's domain does not have the permission)
  178.79 + *         throw AccessControlException
  178.80 + *
  178.81 + *     else if (caller i is marked as privileged) {
  178.82 + *         if (a context was specified in the call to doPrivileged)
  178.83 + *             context.checkPermission(permission)
  178.84 + *         return;
  178.85 + *     }
  178.86 + * };
  178.87 + *
  178.88 + * // Next, check the context inherited when the thread was created.
  178.89 + * // Whenever a new thread is created, the AccessControlContext at
  178.90 + * // that time is stored and associated with the new thread, as the
  178.91 + * // "inherited" context.
  178.92 + *
  178.93 + * inheritedContext.checkPermission(permission);
  178.94 + * }</pre>
  178.95 + *
  178.96 + * <p> A caller can be marked as being "privileged"
  178.97 + * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
  178.98 + * When making access control decisions, the <code>checkPermission</code>
  178.99 + * method stops checking if it reaches a caller that
 178.100 + * was marked as "privileged" via a <code>doPrivileged</code>
 178.101 + * call without a context argument (see below for information about a
 178.102 + * context argument). If that caller's domain has the
 178.103 + * specified permission, no further checking is done and
 178.104 + * <code>checkPermission</code>
 178.105 + * returns quietly, indicating that the requested access is allowed.
 178.106 + * If that domain does not have the specified permission, an exception
 178.107 + * is thrown, as usual.
 178.108 + *
 178.109 + * <p> The normal use of the "privileged" feature is as follows. If you
 178.110 + * don't need to return a value from within the "privileged" block, do
 178.111 + * the following:
 178.112 + *
 178.113 + *  <pre> {@code
 178.114 + * somemethod() {
 178.115 + *     ...normal code here...
 178.116 + *     AccessController.doPrivileged(new PrivilegedAction<Void>() {
 178.117 + *         public Void run() {
 178.118 + *             // privileged code goes here, for example:
 178.119 + *             System.loadLibrary("awt");
 178.120 + *             return null; // nothing to return
 178.121 + *         }
 178.122 + *     });
 178.123 + *     ...normal code here...
 178.124 + * }}</pre>
 178.125 + *
 178.126 + * <p>
 178.127 + * PrivilegedAction is an interface with a single method, named
 178.128 + * <code>run</code>.
 178.129 + * The above example shows creation of an implementation
 178.130 + * of that interface; a concrete implementation of the
 178.131 + * <code>run</code> method is supplied.
 178.132 + * When the call to <code>doPrivileged</code> is made, an
 178.133 + * instance of the PrivilegedAction implementation is passed
 178.134 + * to it. The <code>doPrivileged</code> method calls the
 178.135 + * <code>run</code> method from the PrivilegedAction
 178.136 + * implementation after enabling privileges, and returns the
 178.137 + * <code>run</code> method's return value as the
 178.138 + * <code>doPrivileged</code> return value (which is
 178.139 + * ignored in this example).
 178.140 + *
 178.141 + * <p> If you need to return a value, you can do something like the following:
 178.142 + *
 178.143 + *  <pre> {@code
 178.144 + * somemethod() {
 178.145 + *     ...normal code here...
 178.146 + *     String user = AccessController.doPrivileged(
 178.147 + *         new PrivilegedAction<String>() {
 178.148 + *         public String run() {
 178.149 + *             return System.getProperty("user.name");
 178.150 + *             }
 178.151 + *         });
 178.152 + *     ...normal code here...
 178.153 + * }}</pre>
 178.154 + *
 178.155 + * <p>If the action performed in your <code>run</code> method could
 178.156 + * throw a "checked" exception (those listed in the <code>throws</code> clause
 178.157 + * of a method), then you need to use the
 178.158 + * <code>PrivilegedExceptionAction</code> interface instead of the
 178.159 + * <code>PrivilegedAction</code> interface:
 178.160 + *
 178.161 + *  <pre> {@code
 178.162 + * somemethod() throws FileNotFoundException {
 178.163 + *     ...normal code here...
 178.164 + *     try {
 178.165 + *         FileInputStream fis = AccessController.doPrivileged(
 178.166 + *         new PrivilegedExceptionAction<FileInputStream>() {
 178.167 + *             public FileInputStream run() throws FileNotFoundException {
 178.168 + *                 return new FileInputStream("someFile");
 178.169 + *             }
 178.170 + *         });
 178.171 + *     } catch (PrivilegedActionException e) {
 178.172 + *         // e.getException() should be an instance of FileNotFoundException,
 178.173 + *         // as only "checked" exceptions will be "wrapped" in a
 178.174 + *         // PrivilegedActionException.
 178.175 + *         throw (FileNotFoundException) e.getException();
 178.176 + *     }
 178.177 + *     ...normal code here...
 178.178 + *  }}</pre>
 178.179 + *
 178.180 + * <p> Be *very* careful in your use of the "privileged" construct, and
 178.181 + * always remember to make the privileged code section as small as possible.
 178.182 + *
 178.183 + * <p> Note that <code>checkPermission</code> always performs security checks
 178.184 + * within the context of the currently executing thread.
 178.185 + * Sometimes a security check that should be made within a given context
 178.186 + * will actually need to be done from within a
 178.187 + * <i>different</i> context (for example, from within a worker thread).
 178.188 + * The {@link #getContext() getContext} method and
 178.189 + * AccessControlContext class are provided
 178.190 + * for this situation. The <code>getContext</code> method takes a "snapshot"
 178.191 + * of the current calling context, and places
 178.192 + * it in an AccessControlContext object, which it returns. A sample call is
 178.193 + * the following:
 178.194 + *
 178.195 + * <pre>
 178.196 + *
 178.197 + * AccessControlContext acc = AccessController.getContext()
 178.198 + *
 178.199 + * </pre>
 178.200 + *
 178.201 + * <p>
 178.202 + * AccessControlContext itself has a <code>checkPermission</code> method
 178.203 + * that makes access decisions based on the context <i>it</i> encapsulates,
 178.204 + * rather than that of the current execution thread.
 178.205 + * Code within a different context can thus call that method on the
 178.206 + * previously-saved AccessControlContext object. A sample call is the
 178.207 + * following:
 178.208 + *
 178.209 + * <pre>
 178.210 + *
 178.211 + * acc.checkPermission(permission)
 178.212 + *
 178.213 + * </pre>
 178.214 + *
 178.215 + * <p> There are also times where you don't know a priori which permissions
 178.216 + * to check the context against. In these cases you can use the
 178.217 + * doPrivileged method that takes a context:
 178.218 + *
 178.219 + *  <pre> {@code
 178.220 + * somemethod() {
 178.221 + *     AccessController.doPrivileged(new PrivilegedAction<Object>() {
 178.222 + *         public Object run() {
 178.223 + *             // Code goes here. Any permission checks within this
 178.224 + *             // run method will require that the intersection of the
 178.225 + *             // callers protection domain and the snapshot's
 178.226 + *             // context have the desired permission.
 178.227 + *         }
 178.228 + *     }, acc);
 178.229 + *     ...normal code here...
 178.230 + * }}</pre>
 178.231 + *
 178.232 + * @see AccessControlContext
 178.233 + *
 178.234 + * @author Li Gong
 178.235 + * @author Roland Schemers
 178.236 + */
 178.237 +
 178.238 +public final class AccessController {
 178.239 +
 178.240 +    /**
 178.241 +     * Don't allow anyone to instantiate an AccessController
 178.242 +     */
 178.243 +    private AccessController() { }
 178.244 +
 178.245 +    /**
 178.246 +     * Performs the specified <code>PrivilegedAction</code> with privileges
 178.247 +     * enabled. The action is performed with <i>all</i> of the permissions
 178.248 +     * possessed by the caller's protection domain.
 178.249 +     *
 178.250 +     * <p> If the action's <code>run</code> method throws an (unchecked)
 178.251 +     * exception, it will propagate through this method.
 178.252 +     *
 178.253 +     * <p> Note that any DomainCombiner associated with the current
 178.254 +     * AccessControlContext will be ignored while the action is performed.
 178.255 +     *
 178.256 +     * @param action the action to be performed.
 178.257 +     *
 178.258 +     * @return the value returned by the action's <code>run</code> method.
 178.259 +     *
 178.260 +     * @exception NullPointerException if the action is <code>null</code>
 178.261 +     *
 178.262 +     * @see #doPrivileged(PrivilegedAction,AccessControlContext)
 178.263 +     * @see #doPrivileged(PrivilegedExceptionAction)
 178.264 +     * @see #doPrivilegedWithCombiner(PrivilegedAction)
 178.265 +     * @see java.security.DomainCombiner
 178.266 +     */
 178.267 +
 178.268 +    public static <T> T doPrivileged(PrivilegedAction<T> action) {
 178.269 +        return action.run();
 178.270 +    }
 178.271 +
 178.272 +    /**
 178.273 +     * Performs the specified <code>PrivilegedAction</code> with privileges
 178.274 +     * enabled. The action is performed with <i>all</i> of the permissions
 178.275 +     * possessed by the caller's protection domain.
 178.276 +     *
 178.277 +     * <p> If the action's <code>run</code> method throws an (unchecked)
 178.278 +     * exception, it will propagate through this method.
 178.279 +     *
 178.280 +     * <p> This method preserves the current AccessControlContext's
 178.281 +     * DomainCombiner (which may be null) while the action is performed.
 178.282 +     *
 178.283 +     * @param action the action to be performed.
 178.284 +     *
 178.285 +     * @return the value returned by the action's <code>run</code> method.
 178.286 +     *
 178.287 +     * @exception NullPointerException if the action is <code>null</code>
 178.288 +     *
 178.289 +     * @see #doPrivileged(PrivilegedAction)
 178.290 +     * @see java.security.DomainCombiner
 178.291 +     *
 178.292 +     * @since 1.6
 178.293 +     */
 178.294 +    public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
 178.295 +        return action.run();
 178.296 +    }
 178.297 +
 178.298 +
 178.299 +    /**
 178.300 +     * Performs the specified <code>PrivilegedAction</code> with privileges
 178.301 +     * enabled and restricted by the specified
 178.302 +     * <code>AccessControlContext</code>.
 178.303 +     * The action is performed with the intersection of the permissions
 178.304 +     * possessed by the caller's protection domain, and those possessed
 178.305 +     * by the domains represented by the specified
 178.306 +     * <code>AccessControlContext</code>.
 178.307 +     * <p>
 178.308 +     * If the action's <code>run</code> method throws an (unchecked) exception,
 178.309 +     * it will propagate through this method.
 178.310 +     *
 178.311 +     * @param action the action to be performed.
 178.312 +     * @param context an <i>access control context</i>
 178.313 +     *                representing the restriction to be applied to the
 178.314 +     *                caller's domain's privileges before performing
 178.315 +     *                the specified action.  If the context is
 178.316 +     *                <code>null</code>,
 178.317 +     *                then no additional restriction is applied.
 178.318 +     *
 178.319 +     * @return the value returned by the action's <code>run</code> method.
 178.320 +     *
 178.321 +     * @exception NullPointerException if the action is <code>null</code>
 178.322 +     *
 178.323 +     * @see #doPrivileged(PrivilegedAction)
 178.324 +     * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 178.325 +     */
 178.326 +//    public static native <T> T doPrivileged(PrivilegedAction<T> action,
 178.327 +//                                            AccessControlContext context);
 178.328 +
 178.329 +    /**
 178.330 +     * Performs the specified <code>PrivilegedExceptionAction</code> with
 178.331 +     * privileges enabled.  The action is performed with <i>all</i> of the
 178.332 +     * permissions possessed by the caller's protection domain.
 178.333 +     *
 178.334 +     * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
 178.335 +     * exception, it will propagate through this method.
 178.336 +     *
 178.337 +     * <p> Note that any DomainCombiner associated with the current
 178.338 +     * AccessControlContext will be ignored while the action is performed.
 178.339 +     *
 178.340 +     * @param action the action to be performed
 178.341 +     *
 178.342 +     * @return the value returned by the action's <code>run</code> method
 178.343 +     *
 178.344 +     * @exception PrivilegedActionException if the specified action's
 178.345 +     *         <code>run</code> method threw a <i>checked</i> exception
 178.346 +     * @exception NullPointerException if the action is <code>null</code>
 178.347 +     *
 178.348 +     * @see #doPrivileged(PrivilegedAction)
 178.349 +     * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 178.350 +     * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
 178.351 +     * @see java.security.DomainCombiner
 178.352 +     */
 178.353 +    public static <T> T
 178.354 +        doPrivileged(PrivilegedExceptionAction<T> action)
 178.355 +        throws PrivilegedActionException {
 178.356 +        try {
 178.357 +            return action.run();
 178.358 +        } catch (Exception ex) {
 178.359 +            throw new PrivilegedActionException(ex);
 178.360 +        }
 178.361 +    }
 178.362 +
 178.363 +
 178.364 +    /**
 178.365 +     * Performs the specified <code>PrivilegedExceptionAction</code> with
 178.366 +     * privileges enabled.  The action is performed with <i>all</i> of the
 178.367 +     * permissions possessed by the caller's protection domain.
 178.368 +     *
 178.369 +     * <p> If the action's <code>run</code> method throws an <i>unchecked</i>
 178.370 +     * exception, it will propagate through this method.
 178.371 +     *
 178.372 +     * <p> This method preserves the current AccessControlContext's
 178.373 +     * DomainCombiner (which may be null) while the action is performed.
 178.374 +     *
 178.375 +     * @param action the action to be performed.
 178.376 +     *
 178.377 +     * @return the value returned by the action's <code>run</code> method
 178.378 +     *
 178.379 +     * @exception PrivilegedActionException if the specified action's
 178.380 +     *         <code>run</code> method threw a <i>checked</i> exception
 178.381 +     * @exception NullPointerException if the action is <code>null</code>
 178.382 +     *
 178.383 +     * @see #doPrivileged(PrivilegedAction)
 178.384 +     * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 178.385 +     * @see java.security.DomainCombiner
 178.386 +     *
 178.387 +     * @since 1.6
 178.388 +     */
 178.389 +    public static <T> T doPrivilegedWithCombiner
 178.390 +        (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
 178.391 +        return doPrivileged(action);
 178.392 +    }
 178.393 +
 178.394 +    /**
 178.395 +     * Performs the specified <code>PrivilegedExceptionAction</code> with
 178.396 +     * privileges enabled and restricted by the specified
 178.397 +     * <code>AccessControlContext</code>.  The action is performed with the
 178.398 +     * intersection of the permissions possessed by the caller's
 178.399 +     * protection domain, and those possessed by the domains represented by the
 178.400 +     * specified <code>AccessControlContext</code>.
 178.401 +     * <p>
 178.402 +     * If the action's <code>run</code> method throws an <i>unchecked</i>
 178.403 +     * exception, it will propagate through this method.
 178.404 +     *
 178.405 +     * @param action the action to be performed
 178.406 +     * @param context an <i>access control context</i>
 178.407 +     *                representing the restriction to be applied to the
 178.408 +     *                caller's domain's privileges before performing
 178.409 +     *                the specified action.  If the context is
 178.410 +     *                <code>null</code>,
 178.411 +     *                then no additional restriction is applied.
 178.412 +     *
 178.413 +     * @return the value returned by the action's <code>run</code> method
 178.414 +     *
 178.415 +     * @exception PrivilegedActionException if the specified action's
 178.416 +     *         <code>run</code> method
 178.417 +     *         threw a <i>checked</i> exception
 178.418 +     * @exception NullPointerException if the action is <code>null</code>
 178.419 +     *
 178.420 +     * @see #doPrivileged(PrivilegedAction)
 178.421 +     * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 178.422 +     */
 178.423 +//    public static native <T> T
 178.424 +//        doPrivileged(PrivilegedExceptionAction<T> action,
 178.425 +//                     AccessControlContext context)
 178.426 +//        throws PrivilegedActionException;
 178.427 +
 178.428 +    /**
 178.429 +     * This method takes a "snapshot" of the current calling context, which
 178.430 +     * includes the current Thread's inherited AccessControlContext,
 178.431 +     * and places it in an AccessControlContext object. This context may then
 178.432 +     * be checked at a later point, possibly in another thread.
 178.433 +     *
 178.434 +     * @see AccessControlContext
 178.435 +     *
 178.436 +     * @return the AccessControlContext based on the current context.
 178.437 +     */
 178.438 +
 178.439 +//    public static AccessControlContext getContext()
 178.440 +//    {
 178.441 +//        AccessControlContext acc = getStackAccessControlContext();
 178.442 +//        if (acc == null) {
 178.443 +//            // all we had was privileged system code. We don't want
 178.444 +//            // to return null though, so we construct a real ACC.
 178.445 +//            return new AccessControlContext(null, true);
 178.446 +//        } else {
 178.447 +//            return acc.optimize();
 178.448 +//        }
 178.449 +//    }
 178.450 +
 178.451 +    /**
 178.452 +     * Determines whether the access request indicated by the
 178.453 +     * specified permission should be allowed or denied, based on
 178.454 +     * the current AccessControlContext and security policy.
 178.455 +     * This method quietly returns if the access request
 178.456 +     * is permitted, or throws an AccessControlException otherwise. The
 178.457 +     * getPermission method of the AccessControlException returns the
 178.458 +     * <code>perm</code> Permission object instance.
 178.459 +     *
 178.460 +     * @param perm the requested permission.
 178.461 +     *
 178.462 +     * @exception AccessControlException if the specified permission
 178.463 +     *            is not permitted, based on the current security policy.
 178.464 +     * @exception NullPointerException if the specified permission
 178.465 +     *            is <code>null</code> and is checked based on the
 178.466 +     *            security policy currently in effect.
 178.467 +     */
 178.468 +
 178.469 +//    public static void checkPermission(Permission perm)
 178.470 +//                 throws AccessControlException
 178.471 +//    {
 178.472 +//        //System.err.println("checkPermission "+perm);
 178.473 +//        //Thread.currentThread().dumpStack();
 178.474 +//
 178.475 +//        if (perm == null) {
 178.476 +//            throw new NullPointerException("permission can't be null");
 178.477 +//        }
 178.478 +//
 178.479 +//        AccessControlContext stack = getStackAccessControlContext();
 178.480 +//        // if context is null, we had privileged system code on the stack.
 178.481 +//        if (stack == null) {
 178.482 +//            Debug debug = AccessControlContext.getDebug();
 178.483 +//            boolean dumpDebug = false;
 178.484 +//            if (debug != null) {
 178.485 +//                dumpDebug = !Debug.isOn("codebase=");
 178.486 +//                dumpDebug &= !Debug.isOn("permission=") ||
 178.487 +//                    Debug.isOn("permission=" + perm.getClass().getCanonicalName());
 178.488 +//            }
 178.489 +//
 178.490 +//            if (dumpDebug && Debug.isOn("stack")) {
 178.491 +//                Thread.currentThread().dumpStack();
 178.492 +//            }
 178.493 +//
 178.494 +//            if (dumpDebug && Debug.isOn("domain")) {
 178.495 +//                debug.println("domain (context is null)");
 178.496 +//            }
 178.497 +//
 178.498 +//            if (dumpDebug) {
 178.499 +//                debug.println("access allowed "+perm);
 178.500 +//            }
 178.501 +//            return;
 178.502 +//        }
 178.503 +//
 178.504 +//        AccessControlContext acc = stack.optimize();
 178.505 +//        acc.checkPermission(perm);
 178.506 +//    }
 178.507 +}
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/rt/emul/compact/src/main/java/java/security/PrivilegedAction.java	Wed Apr 30 15:04:10 2014 +0200
   179.3 @@ -0,0 +1,56 @@
   179.4 +/*
   179.5 + * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
   179.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   179.7 + *
   179.8 + * This code is free software; you can redistribute it and/or modify it
   179.9 + * under the terms of the GNU General Public License version 2 only, as
  179.10 + * published by the Free Software Foundation.  Oracle designates this
  179.11 + * particular file as subject to the "Classpath" exception as provided
  179.12 + * by Oracle in the LICENSE file that accompanied this code.
  179.13 + *
  179.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  179.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  179.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  179.17 + * version 2 for more details (a copy is included in the LICENSE file that
  179.18 + * accompanied this code).
  179.19 + *
  179.20 + * You should have received a copy of the GNU General Public License version
  179.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  179.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  179.23 + *
  179.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  179.25 + * or visit www.oracle.com if you need additional information or have any
  179.26 + * questions.
  179.27 + */
  179.28 +
  179.29 +package java.security;
  179.30 +
  179.31 +
  179.32 +/**
  179.33 + * A computation to be performed with privileges enabled.  The computation is
  179.34 + * performed by invoking <code>AccessController.doPrivileged</code> on the
  179.35 + * <code>PrivilegedAction</code> object.  This interface is used only for
  179.36 + * computations that do not throw checked exceptions; computations that
  179.37 + * throw checked exceptions must use <code>PrivilegedExceptionAction</code>
  179.38 + * instead.
  179.39 + *
  179.40 + * @see AccessController
  179.41 + * @see AccessController#doPrivileged(PrivilegedAction)
  179.42 + * @see PrivilegedExceptionAction
  179.43 + */
  179.44 +
  179.45 +public interface PrivilegedAction<T> {
  179.46 +    /**
  179.47 +     * Performs the computation.  This method will be called by
  179.48 +     * <code>AccessController.doPrivileged</code> after enabling privileges.
  179.49 +     *
  179.50 +     * @return a class-dependent value that may represent the results of the
  179.51 +     *         computation. Each class that implements
  179.52 +     *         <code>PrivilegedAction</code>
  179.53 +     *         should document what (if anything) this value represents.
  179.54 +     * @see AccessController#doPrivileged(PrivilegedAction)
  179.55 +     * @see AccessController#doPrivileged(PrivilegedAction,
  179.56 +     *                                     AccessControlContext)
  179.57 +     */
  179.58 +    T run();
  179.59 +}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/rt/emul/compact/src/main/java/java/security/PrivilegedActionException.java	Wed Apr 30 15:04:10 2014 +0200
   180.3 @@ -0,0 +1,105 @@
   180.4 +/*
   180.5 + * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
   180.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   180.7 + *
   180.8 + * This code is free software; you can redistribute it and/or modify it
   180.9 + * under the terms of the GNU General Public License version 2 only, as
  180.10 + * published by the Free Software Foundation.  Oracle designates this
  180.11 + * particular file as subject to the "Classpath" exception as provided
  180.12 + * by Oracle in the LICENSE file that accompanied this code.
  180.13 + *
  180.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  180.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  180.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  180.17 + * version 2 for more details (a copy is included in the LICENSE file that
  180.18 + * accompanied this code).
  180.19 + *
  180.20 + * You should have received a copy of the GNU General Public License version
  180.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  180.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  180.23 + *
  180.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  180.25 + * or visit www.oracle.com if you need additional information or have any
  180.26 + * questions.
  180.27 + */
  180.28 +
  180.29 +package java.security;
  180.30 +
  180.31 +/**
  180.32 + * This exception is thrown by
  180.33 + * <code>doPrivileged(PrivilegedExceptionAction)</code> and
  180.34 + * <code>doPrivileged(PrivilegedExceptionAction,
  180.35 + * AccessControlContext context)</code> to indicate
  180.36 + * that the action being performed threw a checked exception.  The exception
  180.37 + * thrown by the action can be obtained by calling the
  180.38 + * <code>getException</code> method.  In effect, an
  180.39 + * <code>PrivilegedActionException</code> is a "wrapper"
  180.40 + * for an exception thrown by a privileged action.
  180.41 + *
  180.42 + * <p>As of release 1.4, this exception has been retrofitted to conform to
  180.43 + * the general purpose exception-chaining mechanism.  The "exception thrown
  180.44 + * by the privileged computation" that is provided at construction time and
  180.45 + * accessed via the {@link #getException()} method is now known as the
  180.46 + * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
  180.47 + * method, as well as the aforementioned "legacy method."
  180.48 + *
  180.49 + * @see PrivilegedExceptionAction
  180.50 + * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  180.51 + * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  180.52 + */
  180.53 +public class PrivilegedActionException extends Exception {
  180.54 +    // use serialVersionUID from JDK 1.2.2 for interoperability
  180.55 +    private static final long serialVersionUID = 4724086851538908602L;
  180.56 +
  180.57 +    /**
  180.58 +     * @serial
  180.59 +     */
  180.60 +    private Exception exception;
  180.61 +
  180.62 +    /**
  180.63 +     * Constructs a new PrivilegedActionException &quot;wrapping&quot;
  180.64 +     * the specific Exception.
  180.65 +     *
  180.66 +     * @param exception The exception thrown
  180.67 +     */
  180.68 +    public PrivilegedActionException(Exception exception) {
  180.69 +        super((Throwable)null);  // Disallow initCause
  180.70 +        this.exception = exception;
  180.71 +    }
  180.72 +
  180.73 +    /**
  180.74 +     * Returns the exception thrown by the privileged computation that
  180.75 +     * resulted in this <code>PrivilegedActionException</code>.
  180.76 +     *
  180.77 +     * <p>This method predates the general-purpose exception chaining facility.
  180.78 +     * The {@link Throwable#getCause()} method is now the preferred means of
  180.79 +     * obtaining this information.
  180.80 +     *
  180.81 +     * @return the exception thrown by the privileged computation that
  180.82 +     *         resulted in this <code>PrivilegedActionException</code>.
  180.83 +     * @see PrivilegedExceptionAction
  180.84 +     * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  180.85 +     * @see AccessController#doPrivileged(PrivilegedExceptionAction,
  180.86 +     *                                            AccessControlContext)
  180.87 +     */
  180.88 +    public Exception getException() {
  180.89 +        return exception;
  180.90 +    }
  180.91 +
  180.92 +    /**
  180.93 +     * Returns the cause of this exception (the exception thrown by
  180.94 +     * the privileged computation that resulted in this
  180.95 +     * <code>PrivilegedActionException</code>).
  180.96 +     *
  180.97 +     * @return  the cause of this exception.
  180.98 +     * @since   1.4
  180.99 +     */
 180.100 +    public Throwable getCause() {
 180.101 +        return exception;
 180.102 +    }
 180.103 +
 180.104 +    public String toString() {
 180.105 +        String s = getClass().getName();
 180.106 +        return (exception != null) ? (s + ": " + exception.toString()) : s;
 180.107 +    }
 180.108 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/rt/emul/compact/src/main/java/java/security/PrivilegedExceptionAction.java	Wed Apr 30 15:04:10 2014 +0200
   181.3 @@ -0,0 +1,62 @@
   181.4 +/*
   181.5 + * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
   181.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   181.7 + *
   181.8 + * This code is free software; you can redistribute it and/or modify it
   181.9 + * under the terms of the GNU General Public License version 2 only, as
  181.10 + * published by the Free Software Foundation.  Oracle designates this
  181.11 + * particular file as subject to the "Classpath" exception as provided
  181.12 + * by Oracle in the LICENSE file that accompanied this code.
  181.13 + *
  181.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  181.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  181.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  181.17 + * version 2 for more details (a copy is included in the LICENSE file that
  181.18 + * accompanied this code).
  181.19 + *
  181.20 + * You should have received a copy of the GNU General Public License version
  181.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  181.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  181.23 + *
  181.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  181.25 + * or visit www.oracle.com if you need additional information or have any
  181.26 + * questions.
  181.27 + */
  181.28 +
  181.29 +package java.security;
  181.30 +
  181.31 +
  181.32 +/**
  181.33 + * A computation to be performed with privileges enabled, that throws one or
  181.34 + * more checked exceptions.  The computation is performed by invoking
  181.35 + * <code>AccessController.doPrivileged</code> on the
  181.36 + * <code>PrivilegedExceptionAction</code> object.  This interface is
  181.37 + * used only for computations that throw checked exceptions;
  181.38 + * computations that do not throw
  181.39 + * checked exceptions should use <code>PrivilegedAction</code> instead.
  181.40 + *
  181.41 + * @see AccessController
  181.42 + * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  181.43 + * @see AccessController#doPrivileged(PrivilegedExceptionAction,
  181.44 + *                                              AccessControlContext)
  181.45 + * @see PrivilegedAction
  181.46 + */
  181.47 +
  181.48 +public interface PrivilegedExceptionAction<T> {
  181.49 +    /**
  181.50 +     * Performs the computation.  This method will be called by
  181.51 +     * <code>AccessController.doPrivileged</code> after enabling privileges.
  181.52 +     *
  181.53 +     * @return a class-dependent value that may represent the results of the
  181.54 +     *         computation.  Each class that implements
  181.55 +     *         <code>PrivilegedExceptionAction</code> should document what
  181.56 +     *         (if anything) this value represents.
  181.57 +     * @throws Exception an exceptional condition has occurred.  Each class
  181.58 +     *         that implements <code>PrivilegedExceptionAction</code> should
  181.59 +     *         document the exceptions that its run method can throw.
  181.60 +     * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  181.61 +     * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  181.62 +     */
  181.63 +
  181.64 +    T run() throws Exception;
  181.65 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/rt/emul/compact/src/main/java/java/text/Annotation.java	Wed Apr 30 15:04:10 2014 +0200
   182.3 @@ -0,0 +1,84 @@
   182.4 +/*
   182.5 + * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
   182.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   182.7 + *
   182.8 + * This code is free software; you can redistribute it and/or modify it
   182.9 + * under the terms of the GNU General Public License version 2 only, as
  182.10 + * published by the Free Software Foundation.  Oracle designates this
  182.11 + * particular file as subject to the "Classpath" exception as provided
  182.12 + * by Oracle in the LICENSE file that accompanied this code.
  182.13 + *
  182.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  182.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  182.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  182.17 + * version 2 for more details (a copy is included in the LICENSE file that
  182.18 + * accompanied this code).
  182.19 + *
  182.20 + * You should have received a copy of the GNU General Public License version
  182.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  182.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  182.23 + *
  182.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  182.25 + * or visit www.oracle.com if you need additional information or have any
  182.26 + * questions.
  182.27 + */
  182.28 +
  182.29 +package java.text;
  182.30 +
  182.31 +/**
  182.32 +* An Annotation object is used as a wrapper for a text attribute value if
  182.33 +* the attribute has annotation characteristics. These characteristics are:
  182.34 +* <ul>
  182.35 +* <li>The text range that the attribute is applied to is critical to the
  182.36 +* semantics of the range. That means, the attribute cannot be applied to subranges
  182.37 +* of the text range that it applies to, and, if two adjacent text ranges have
  182.38 +* the same value for this attribute, the attribute still cannot be applied to
  182.39 +* the combined range as a whole with this value.
  182.40 +* <li>The attribute or its value usually do no longer apply if the underlying text is
  182.41 +* changed.
  182.42 +* </ul>
  182.43 +*
  182.44 +* An example is grammatical information attached to a sentence:
  182.45 +* For the previous sentence, you can say that "an example"
  182.46 +* is the subject, but you cannot say the same about "an", "example", or "exam".
  182.47 +* When the text is changed, the grammatical information typically becomes invalid.
  182.48 +* Another example is Japanese reading information (yomi).
  182.49 +*
  182.50 +* <p>
  182.51 +* Wrapping the attribute value into an Annotation object guarantees that
  182.52 +* adjacent text runs don't get merged even if the attribute values are equal,
  182.53 +* and indicates to text containers that the attribute should be discarded if
  182.54 +* the underlying text is modified.
  182.55 +*
  182.56 +* @see AttributedCharacterIterator
  182.57 +* @since 1.2
  182.58 +*/
  182.59 +
  182.60 +public class Annotation {
  182.61 +
  182.62 +    /**
  182.63 +     * Constructs an annotation record with the given value, which
  182.64 +     * may be null.
  182.65 +     * @param value The value of the attribute
  182.66 +     */
  182.67 +    public Annotation(Object value) {
  182.68 +        this.value = value;
  182.69 +    }
  182.70 +
  182.71 +    /**
  182.72 +     * Returns the value of the attribute, which may be null.
  182.73 +     */
  182.74 +    public Object getValue() {
  182.75 +        return value;
  182.76 +    }
  182.77 +
  182.78 +    /**
  182.79 +     * Returns the String representation of this Annotation.
  182.80 +     */
  182.81 +    public String toString() {
  182.82 +        return getClass().getName() + "[value=" + value + "]";
  182.83 +    }
  182.84 +
  182.85 +    private Object value;
  182.86 +
  182.87 +};
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/rt/emul/compact/src/main/java/java/text/AttributedCharacterIterator.java	Wed Apr 30 15:04:10 2014 +0200
   183.3 @@ -0,0 +1,254 @@
   183.4 +/*
   183.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   183.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   183.7 + *
   183.8 + * This code is free software; you can redistribute it and/or modify it
   183.9 + * under the terms of the GNU General Public License version 2 only, as
  183.10 + * published by the Free Software Foundation.  Oracle designates this
  183.11 + * particular file as subject to the "Classpath" exception as provided
  183.12 + * by Oracle in the LICENSE file that accompanied this code.
  183.13 + *
  183.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  183.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  183.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  183.17 + * version 2 for more details (a copy is included in the LICENSE file that
  183.18 + * accompanied this code).
  183.19 + *
  183.20 + * You should have received a copy of the GNU General Public License version
  183.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  183.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  183.23 + *
  183.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  183.25 + * or visit www.oracle.com if you need additional information or have any
  183.26 + * questions.
  183.27 + */
  183.28 +
  183.29 +package java.text;
  183.30 +
  183.31 +import java.io.InvalidObjectException;
  183.32 +import java.io.Serializable;
  183.33 +import java.util.HashMap;
  183.34 +import java.util.Map;
  183.35 +import java.util.Set;
  183.36 +
  183.37 +/**
  183.38 + * An {@code AttributedCharacterIterator} allows iteration through both text and
  183.39 + * related attribute information.
  183.40 + *
  183.41 + * <p>
  183.42 + * An attribute is a key/value pair, identified by the key.  No two
  183.43 + * attributes on a given character can have the same key.
  183.44 + *
  183.45 + * <p>The values for an attribute are immutable, or must not be mutated
  183.46 + * by clients or storage.  They are always passed by reference, and not
  183.47 + * cloned.
  183.48 + *
  183.49 + * <p>A <em>run with respect to an attribute</em> is a maximum text range for
  183.50 + * which:
  183.51 + * <ul>
  183.52 + * <li>the attribute is undefined or {@code null} for the entire range, or
  183.53 + * <li>the attribute value is defined and has the same non-{@code null} value for the
  183.54 + *     entire range.
  183.55 + * </ul>
  183.56 + *
  183.57 + * <p>A <em>run with respect to a set of attributes</em> is a maximum text range for
  183.58 + * which this condition is met for each member attribute.
  183.59 + *
  183.60 + * <p>When getting a run with no explicit attributes specified (i.e.,
  183.61 + * calling {@link #getRunStart()} and {@link #getRunLimit()}), any
  183.62 + * contiguous text segments having the same attributes (the same set
  183.63 + * of attribute/value pairs) are treated as separate runs if the
  183.64 + * attributes have been given to those text segments separately.
  183.65 + *
  183.66 + * <p>The returned indexes are limited to the range of the iterator.
  183.67 + *
  183.68 + * <p>The returned attribute information is limited to runs that contain
  183.69 + * the current character.
  183.70 + *
  183.71 + * <p>
  183.72 + * Attribute keys are instances of {@link AttributedCharacterIterator.Attribute} and its
  183.73 + * subclasses, such as {@link java.awt.font.TextAttribute}.
  183.74 + *
  183.75 + * @see AttributedCharacterIterator.Attribute
  183.76 + * @see java.awt.font.TextAttribute
  183.77 + * @see AttributedString
  183.78 + * @see Annotation
  183.79 + * @since 1.2
  183.80 + */
  183.81 +
  183.82 +public interface AttributedCharacterIterator extends CharacterIterator {
  183.83 +
  183.84 +    /**
  183.85 +     * Defines attribute keys that are used to identify text attributes. These
  183.86 +     * keys are used in {@code AttributedCharacterIterator} and {@code AttributedString}.
  183.87 +     * @see AttributedCharacterIterator
  183.88 +     * @see AttributedString
  183.89 +     * @since 1.2
  183.90 +     */
  183.91 +
  183.92 +    public static class Attribute implements Serializable {
  183.93 +
  183.94 +        /**
  183.95 +         * The name of this {@code Attribute}. The name is used primarily by {@code readResolve}
  183.96 +         * to look up the corresponding predefined instance when deserializing
  183.97 +         * an instance.
  183.98 +         * @serial
  183.99 +         */
 183.100 +        private String name;
 183.101 +
 183.102 +        // table of all instances in this class, used by readResolve
 183.103 +        private static final Map instanceMap = new HashMap(7);
 183.104 +
 183.105 +        /**
 183.106 +         * Constructs an {@code Attribute} with the given name.
 183.107 +         */
 183.108 +        protected Attribute(String name) {
 183.109 +            this.name = name;
 183.110 +            if (this.getClass() == Attribute.class) {
 183.111 +                instanceMap.put(name, this);
 183.112 +            }
 183.113 +        }
 183.114 +
 183.115 +        /**
 183.116 +         * Compares two objects for equality. This version only returns true
 183.117 +         * for <code>x.equals(y)</code> if <code>x</code> and <code>y</code> refer
 183.118 +         * to the same object, and guarantees this for all subclasses.
 183.119 +         */
 183.120 +        public final boolean equals(Object obj) {
 183.121 +            return super.equals(obj);
 183.122 +        }
 183.123 +
 183.124 +        /**
 183.125 +         * Returns a hash code value for the object. This version is identical to
 183.126 +         * the one in {@code Object}, but is also final.
 183.127 +         */
 183.128 +        public final int hashCode() {
 183.129 +            return super.hashCode();
 183.130 +        }
 183.131 +
 183.132 +        /**
 183.133 +         * Returns a string representation of the object. This version returns the
 183.134 +         * concatenation of class name, {@code "("}, a name identifying the attribute
 183.135 +         * and {@code ")"}.
 183.136 +         */
 183.137 +        public String toString() {
 183.138 +            return getClass().getName() + "(" + name + ")";
 183.139 +        }
 183.140 +
 183.141 +        /**
 183.142 +         * Returns the name of the attribute.
 183.143 +         */
 183.144 +        protected String getName() {
 183.145 +            return name;
 183.146 +        }
 183.147 +
 183.148 +        /**
 183.149 +         * Resolves instances being deserialized to the predefined constants.
 183.150 +         */
 183.151 +        protected Object readResolve() throws InvalidObjectException {
 183.152 +            if (this.getClass() != Attribute.class) {
 183.153 +                throw new InvalidObjectException("subclass didn't correctly implement readResolve");
 183.154 +            }
 183.155 +
 183.156 +            Attribute instance = (Attribute) instanceMap.get(getName());
 183.157 +            if (instance != null) {
 183.158 +                return instance;
 183.159 +            } else {
 183.160 +                throw new InvalidObjectException("unknown attribute name");
 183.161 +            }
 183.162 +        }
 183.163 +
 183.164 +        /**
 183.165 +         * Attribute key for the language of some text.
 183.166 +         * <p> Values are instances of {@link java.util.Locale Locale}.
 183.167 +         * @see java.util.Locale
 183.168 +         */
 183.169 +        public static final Attribute LANGUAGE = new Attribute("language");
 183.170 +
 183.171 +        /**
 183.172 +         * Attribute key for the reading of some text. In languages where the written form
 183.173 +         * and the pronunciation of a word are only loosely related (such as Japanese),
 183.174 +         * it is often necessary to store the reading (pronunciation) along with the
 183.175 +         * written form.
 183.176 +         * <p>Values are instances of {@link Annotation} holding instances of {@link String}.
 183.177 +         * @see Annotation
 183.178 +         * @see java.lang.String
 183.179 +         */
 183.180 +        public static final Attribute READING = new Attribute("reading");
 183.181 +
 183.182 +        /**
 183.183 +         * Attribute key for input method segments. Input methods often break
 183.184 +         * up text into segments, which usually correspond to words.
 183.185 +         * <p>Values are instances of {@link Annotation} holding a {@code null} reference.
 183.186 +         * @see Annotation
 183.187 +         */
 183.188 +        public static final Attribute INPUT_METHOD_SEGMENT = new Attribute("input_method_segment");
 183.189 +
 183.190 +        // make sure the serial version doesn't change between compiler versions
 183.191 +        private static final long serialVersionUID = -9142742483513960612L;
 183.192 +
 183.193 +    };
 183.194 +
 183.195 +    /**
 183.196 +     * Returns the index of the first character of the run
 183.197 +     * with respect to all attributes containing the current character.
 183.198 +     *
 183.199 +     * <p>Any contiguous text segments having the same attributes (the
 183.200 +     * same set of attribute/value pairs) are treated as separate runs
 183.201 +     * if the attributes have been given to those text segments separately.
 183.202 +     */
 183.203 +    public int getRunStart();
 183.204 +
 183.205 +    /**
 183.206 +     * Returns the index of the first character of the run
 183.207 +     * with respect to the given {@code attribute} containing the current character.
 183.208 +     */
 183.209 +    public int getRunStart(Attribute attribute);
 183.210 +
 183.211 +    /**
 183.212 +     * Returns the index of the first character of the run
 183.213 +     * with respect to the given {@code attributes} containing the current character.
 183.214 +     */
 183.215 +    public int getRunStart(Set<? extends Attribute> attributes);
 183.216 +
 183.217 +    /**
 183.218 +     * Returns the index of the first character following the run
 183.219 +     * with respect to all attributes containing the current character.
 183.220 +     *
 183.221 +     * <p>Any contiguous text segments having the same attributes (the
 183.222 +     * same set of attribute/value pairs) are treated as separate runs
 183.223 +     * if the attributes have been given to those text segments separately.
 183.224 +     */
 183.225 +    public int getRunLimit();
 183.226 +
 183.227 +    /**
 183.228 +     * Returns the index of the first character following the run
 183.229 +     * with respect to the given {@code attribute} containing the current character.
 183.230 +     */
 183.231 +    public int getRunLimit(Attribute attribute);
 183.232 +
 183.233 +    /**
 183.234 +     * Returns the index of the first character following the run
 183.235 +     * with respect to the given {@code attributes} containing the current character.
 183.236 +     */
 183.237 +    public int getRunLimit(Set<? extends Attribute> attributes);
 183.238 +
 183.239 +    /**
 183.240 +     * Returns a map with the attributes defined on the current
 183.241 +     * character.
 183.242 +     */
 183.243 +    public Map<Attribute,Object> getAttributes();
 183.244 +
 183.245 +    /**
 183.246 +     * Returns the value of the named {@code attribute} for the current character.
 183.247 +     * Returns {@code null} if the {@code attribute} is not defined.
 183.248 +     */
 183.249 +    public Object getAttribute(Attribute attribute);
 183.250 +
 183.251 +    /**
 183.252 +     * Returns the keys of all attributes defined on the
 183.253 +     * iterator's text range. The set is empty if no
 183.254 +     * attributes are defined.
 183.255 +     */
 183.256 +    public Set<Attribute> getAllAttributeKeys();
 183.257 +};
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/rt/emul/compact/src/main/java/java/text/AttributedString.java	Wed Apr 30 15:04:10 2014 +0200
   184.3 @@ -0,0 +1,1120 @@
   184.4 +/*
   184.5 + * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
   184.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   184.7 + *
   184.8 + * This code is free software; you can redistribute it and/or modify it
   184.9 + * under the terms of the GNU General Public License version 2 only, as
  184.10 + * published by the Free Software Foundation.  Oracle designates this
  184.11 + * particular file as subject to the "Classpath" exception as provided
  184.12 + * by Oracle in the LICENSE file that accompanied this code.
  184.13 + *
  184.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  184.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  184.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  184.17 + * version 2 for more details (a copy is included in the LICENSE file that
  184.18 + * accompanied this code).
  184.19 + *
  184.20 + * You should have received a copy of the GNU General Public License version
  184.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  184.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  184.23 + *
  184.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  184.25 + * or visit www.oracle.com if you need additional information or have any
  184.26 + * questions.
  184.27 + */
  184.28 +
  184.29 +package java.text;
  184.30 +
  184.31 +import java.util.*;
  184.32 +import java.text.AttributedCharacterIterator.Attribute;
  184.33 +
  184.34 +/**
  184.35 + * An AttributedString holds text and related attribute information. It
  184.36 + * may be used as the actual data storage in some cases where a text
  184.37 + * reader wants to access attributed text through the AttributedCharacterIterator
  184.38 + * interface.
  184.39 + *
  184.40 + * <p>
  184.41 + * An attribute is a key/value pair, identified by the key.  No two
  184.42 + * attributes on a given character can have the same key.
  184.43 + *
  184.44 + * <p>The values for an attribute are immutable, or must not be mutated
  184.45 + * by clients or storage.  They are always passed by reference, and not
  184.46 + * cloned.
  184.47 + *
  184.48 + * @see AttributedCharacterIterator
  184.49 + * @see Annotation
  184.50 + * @since 1.2
  184.51 + */
  184.52 +
  184.53 +public class AttributedString {
  184.54 +
  184.55 +    // since there are no vectors of int, we have to use arrays.
  184.56 +    // We allocate them in chunks of 10 elements so we don't have to allocate all the time.
  184.57 +    private static final int ARRAY_SIZE_INCREMENT = 10;
  184.58 +
  184.59 +    // field holding the text
  184.60 +    String text;
  184.61 +
  184.62 +    // fields holding run attribute information
  184.63 +    // run attributes are organized by run
  184.64 +    int runArraySize;               // current size of the arrays
  184.65 +    int runCount;                   // actual number of runs, <= runArraySize
  184.66 +    int runStarts[];                // start index for each run
  184.67 +    Vector runAttributes[];         // vector of attribute keys for each run
  184.68 +    Vector runAttributeValues[];    // parallel vector of attribute values for each run
  184.69 +
  184.70 +    /**
  184.71 +     * Constructs an AttributedString instance with the given
  184.72 +     * AttributedCharacterIterators.
  184.73 +     *
  184.74 +     * @param iterators AttributedCharacterIterators to construct
  184.75 +     * AttributedString from.
  184.76 +     * @throws NullPointerException if iterators is null
  184.77 +     */
  184.78 +    AttributedString(AttributedCharacterIterator[] iterators) {
  184.79 +        if (iterators == null) {
  184.80 +            throw new NullPointerException("Iterators must not be null");
  184.81 +        }
  184.82 +        if (iterators.length == 0) {
  184.83 +            text = "";
  184.84 +        }
  184.85 +        else {
  184.86 +            // Build the String contents
  184.87 +            StringBuffer buffer = new StringBuffer();
  184.88 +            for (int counter = 0; counter < iterators.length; counter++) {
  184.89 +                appendContents(buffer, iterators[counter]);
  184.90 +            }
  184.91 +
  184.92 +            text = buffer.toString();
  184.93 +
  184.94 +            if (text.length() > 0) {
  184.95 +                // Determine the runs, creating a new run when the attributes
  184.96 +                // differ.
  184.97 +                int offset = 0;
  184.98 +                Map last = null;
  184.99 +
 184.100 +                for (int counter = 0; counter < iterators.length; counter++) {
 184.101 +                    AttributedCharacterIterator iterator = iterators[counter];
 184.102 +                    int start = iterator.getBeginIndex();
 184.103 +                    int end = iterator.getEndIndex();
 184.104 +                    int index = start;
 184.105 +
 184.106 +                    while (index < end) {
 184.107 +                        iterator.setIndex(index);
 184.108 +
 184.109 +                        Map attrs = iterator.getAttributes();
 184.110 +
 184.111 +                        if (mapsDiffer(last, attrs)) {
 184.112 +                            setAttributes(attrs, index - start + offset);
 184.113 +                        }
 184.114 +                        last = attrs;
 184.115 +                        index = iterator.getRunLimit();
 184.116 +                    }
 184.117 +                    offset += (end - start);
 184.118 +                }
 184.119 +            }
 184.120 +        }
 184.121 +    }
 184.122 +
 184.123 +    /**
 184.124 +     * Constructs an AttributedString instance with the given text.
 184.125 +     * @param text The text for this attributed string.
 184.126 +     * @exception NullPointerException if <code>text</code> is null.
 184.127 +     */
 184.128 +    public AttributedString(String text) {
 184.129 +        if (text == null) {
 184.130 +            throw new NullPointerException();
 184.131 +        }
 184.132 +        this.text = text;
 184.133 +    }
 184.134 +
 184.135 +    /**
 184.136 +     * Constructs an AttributedString instance with the given text and attributes.
 184.137 +     * @param text The text for this attributed string.
 184.138 +     * @param attributes The attributes that apply to the entire string.
 184.139 +     * @exception NullPointerException if <code>text</code> or
 184.140 +     *            <code>attributes</code> is null.
 184.141 +     * @exception IllegalArgumentException if the text has length 0
 184.142 +     * and the attributes parameter is not an empty Map (attributes
 184.143 +     * cannot be applied to a 0-length range).
 184.144 +     */
 184.145 +    public AttributedString(String text,
 184.146 +                            Map<? extends Attribute, ?> attributes)
 184.147 +    {
 184.148 +        if (text == null || attributes == null) {
 184.149 +            throw new NullPointerException();
 184.150 +        }
 184.151 +        this.text = text;
 184.152 +
 184.153 +        if (text.length() == 0) {
 184.154 +            if (attributes.isEmpty())
 184.155 +                return;
 184.156 +            throw new IllegalArgumentException("Can't add attribute to 0-length text");
 184.157 +        }
 184.158 +
 184.159 +        int attributeCount = attributes.size();
 184.160 +        if (attributeCount > 0) {
 184.161 +            createRunAttributeDataVectors();
 184.162 +            Vector newRunAttributes = new Vector(attributeCount);
 184.163 +            Vector newRunAttributeValues = new Vector(attributeCount);
 184.164 +            runAttributes[0] = newRunAttributes;
 184.165 +            runAttributeValues[0] = newRunAttributeValues;
 184.166 +            Iterator iterator = attributes.entrySet().iterator();
 184.167 +            while (iterator.hasNext()) {
 184.168 +                Map.Entry entry = (Map.Entry) iterator.next();
 184.169 +                newRunAttributes.addElement(entry.getKey());
 184.170 +                newRunAttributeValues.addElement(entry.getValue());
 184.171 +            }
 184.172 +        }
 184.173 +    }
 184.174 +
 184.175 +    /**
 184.176 +     * Constructs an AttributedString instance with the given attributed
 184.177 +     * text represented by AttributedCharacterIterator.
 184.178 +     * @param text The text for this attributed string.
 184.179 +     * @exception NullPointerException if <code>text</code> is null.
 184.180 +     */
 184.181 +    public AttributedString(AttributedCharacterIterator text) {
 184.182 +        // If performance is critical, this constructor should be
 184.183 +        // implemented here rather than invoking the constructor for a
 184.184 +        // subrange. We can avoid some range checking in the loops.
 184.185 +        this(text, text.getBeginIndex(), text.getEndIndex(), null);
 184.186 +    }
 184.187 +
 184.188 +    /**
 184.189 +     * Constructs an AttributedString instance with the subrange of
 184.190 +     * the given attributed text represented by
 184.191 +     * AttributedCharacterIterator. If the given range produces an
 184.192 +     * empty text, all attributes will be discarded.  Note that any
 184.193 +     * attributes wrapped by an Annotation object are discarded for a
 184.194 +     * subrange of the original attribute range.
 184.195 +     *
 184.196 +     * @param text The text for this attributed string.
 184.197 +     * @param beginIndex Index of the first character of the range.
 184.198 +     * @param endIndex Index of the character following the last character
 184.199 +     * of the range.
 184.200 +     * @exception NullPointerException if <code>text</code> is null.
 184.201 +     * @exception IllegalArgumentException if the subrange given by
 184.202 +     * beginIndex and endIndex is out of the text range.
 184.203 +     * @see java.text.Annotation
 184.204 +     */
 184.205 +    public AttributedString(AttributedCharacterIterator text,
 184.206 +                            int beginIndex,
 184.207 +                            int endIndex) {
 184.208 +        this(text, beginIndex, endIndex, null);
 184.209 +    }
 184.210 +
 184.211 +    /**
 184.212 +     * Constructs an AttributedString instance with the subrange of
 184.213 +     * the given attributed text represented by
 184.214 +     * AttributedCharacterIterator.  Only attributes that match the
 184.215 +     * given attributes will be incorporated into the instance. If the
 184.216 +     * given range produces an empty text, all attributes will be
 184.217 +     * discarded. Note that any attributes wrapped by an Annotation
 184.218 +     * object are discarded for a subrange of the original attribute
 184.219 +     * range.
 184.220 +     *
 184.221 +     * @param text The text for this attributed string.
 184.222 +     * @param beginIndex Index of the first character of the range.
 184.223 +     * @param endIndex Index of the character following the last character
 184.224 +     * of the range.
 184.225 +     * @param attributes Specifies attributes to be extracted
 184.226 +     * from the text. If null is specified, all available attributes will
 184.227 +     * be used.
 184.228 +     * @exception NullPointerException if <code>text</code> is null.
 184.229 +     * @exception IllegalArgumentException if the subrange given by
 184.230 +     * beginIndex and endIndex is out of the text range.
 184.231 +     * @see java.text.Annotation
 184.232 +     */
 184.233 +    public AttributedString(AttributedCharacterIterator text,
 184.234 +                            int beginIndex,
 184.235 +                            int endIndex,
 184.236 +                            Attribute[] attributes) {
 184.237 +        if (text == null) {
 184.238 +            throw new NullPointerException();
 184.239 +        }
 184.240 +
 184.241 +        // Validate the given subrange
 184.242 +        int textBeginIndex = text.getBeginIndex();
 184.243 +        int textEndIndex = text.getEndIndex();
 184.244 +        if (beginIndex < textBeginIndex || endIndex > textEndIndex || beginIndex > endIndex)
 184.245 +            throw new IllegalArgumentException("Invalid substring range");
 184.246 +
 184.247 +        // Copy the given string
 184.248 +        StringBuffer textBuffer = new StringBuffer();
 184.249 +        text.setIndex(beginIndex);
 184.250 +        for (char c = text.current(); text.getIndex() < endIndex; c = text.next())
 184.251 +            textBuffer.append(c);
 184.252 +        this.text = textBuffer.toString();
 184.253 +
 184.254 +        if (beginIndex == endIndex)
 184.255 +            return;
 184.256 +
 184.257 +        // Select attribute keys to be taken care of
 184.258 +        HashSet keys = new HashSet();
 184.259 +        if (attributes == null) {
 184.260 +            keys.addAll(text.getAllAttributeKeys());
 184.261 +        } else {
 184.262 +            for (int i = 0; i < attributes.length; i++)
 184.263 +                keys.add(attributes[i]);
 184.264 +            keys.retainAll(text.getAllAttributeKeys());
 184.265 +        }
 184.266 +        if (keys.isEmpty())
 184.267 +            return;
 184.268 +
 184.269 +        // Get and set attribute runs for each attribute name. Need to
 184.270 +        // scan from the top of the text so that we can discard any
 184.271 +        // Annotation that is no longer applied to a subset text segment.
 184.272 +        Iterator itr = keys.iterator();
 184.273 +        while (itr.hasNext()) {
 184.274 +            Attribute attributeKey = (Attribute)itr.next();
 184.275 +            text.setIndex(textBeginIndex);
 184.276 +            while (text.getIndex() < endIndex) {
 184.277 +                int start = text.getRunStart(attributeKey);
 184.278 +                int limit = text.getRunLimit(attributeKey);
 184.279 +                Object value = text.getAttribute(attributeKey);
 184.280 +
 184.281 +                if (value != null) {
 184.282 +                    if (value instanceof Annotation) {
 184.283 +                        if (start >= beginIndex && limit <= endIndex) {
 184.284 +                            addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex);
 184.285 +                        } else {
 184.286 +                            if (limit > endIndex)
 184.287 +                                break;
 184.288 +                        }
 184.289 +                    } else {
 184.290 +                        // if the run is beyond the given (subset) range, we
 184.291 +                        // don't need to process further.
 184.292 +                        if (start >= endIndex)
 184.293 +                            break;
 184.294 +                        if (limit > beginIndex) {
 184.295 +                            // attribute is applied to any subrange
 184.296 +                            if (start < beginIndex)
 184.297 +                                start = beginIndex;
 184.298 +                            if (limit > endIndex)
 184.299 +                                limit = endIndex;
 184.300 +                            if (start != limit) {
 184.301 +                                addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex);
 184.302 +                            }
 184.303 +                        }
 184.304 +                    }
 184.305 +                }
 184.306 +                text.setIndex(limit);
 184.307 +            }
 184.308 +        }
 184.309 +    }
 184.310 +
 184.311 +    /**
 184.312 +     * Adds an attribute to the entire string.
 184.313 +     * @param attribute the attribute key
 184.314 +     * @param value the value of the attribute; may be null
 184.315 +     * @exception NullPointerException if <code>attribute</code> is null.
 184.316 +     * @exception IllegalArgumentException if the AttributedString has length 0
 184.317 +     * (attributes cannot be applied to a 0-length range).
 184.318 +     */
 184.319 +    public void addAttribute(Attribute attribute, Object value) {
 184.320 +
 184.321 +        if (attribute == null) {
 184.322 +            throw new NullPointerException();
 184.323 +        }
 184.324 +
 184.325 +        int len = length();
 184.326 +        if (len == 0) {
 184.327 +            throw new IllegalArgumentException("Can't add attribute to 0-length text");
 184.328 +        }
 184.329 +
 184.330 +        addAttributeImpl(attribute, value, 0, len);
 184.331 +    }
 184.332 +
 184.333 +    /**
 184.334 +     * Adds an attribute to a subrange of the string.
 184.335 +     * @param attribute the attribute key
 184.336 +     * @param value The value of the attribute. May be null.
 184.337 +     * @param beginIndex Index of the first character of the range.
 184.338 +     * @param endIndex Index of the character following the last character of the range.
 184.339 +     * @exception NullPointerException if <code>attribute</code> is null.
 184.340 +     * @exception IllegalArgumentException if beginIndex is less then 0, endIndex is
 184.341 +     * greater than the length of the string, or beginIndex and endIndex together don't
 184.342 +     * define a non-empty subrange of the string.
 184.343 +     */
 184.344 +    public void addAttribute(Attribute attribute, Object value,
 184.345 +            int beginIndex, int endIndex) {
 184.346 +
 184.347 +        if (attribute == null) {
 184.348 +            throw new NullPointerException();
 184.349 +        }
 184.350 +
 184.351 +        if (beginIndex < 0 || endIndex > length() || beginIndex >= endIndex) {
 184.352 +            throw new IllegalArgumentException("Invalid substring range");
 184.353 +        }
 184.354 +
 184.355 +        addAttributeImpl(attribute, value, beginIndex, endIndex);
 184.356 +    }
 184.357 +
 184.358 +    /**
 184.359 +     * Adds a set of attributes to a subrange of the string.
 184.360 +     * @param attributes The attributes to be added to the string.
 184.361 +     * @param beginIndex Index of the first character of the range.
 184.362 +     * @param endIndex Index of the character following the last
 184.363 +     * character of the range.
 184.364 +     * @exception NullPointerException if <code>attributes</code> is null.
 184.365 +     * @exception IllegalArgumentException if beginIndex is less then
 184.366 +     * 0, endIndex is greater than the length of the string, or
 184.367 +     * beginIndex and endIndex together don't define a non-empty
 184.368 +     * subrange of the string and the attributes parameter is not an
 184.369 +     * empty Map.
 184.370 +     */
 184.371 +    public void addAttributes(Map<? extends Attribute, ?> attributes,
 184.372 +                              int beginIndex, int endIndex)
 184.373 +    {
 184.374 +        if (attributes == null) {
 184.375 +            throw new NullPointerException();
 184.376 +        }
 184.377 +
 184.378 +        if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) {
 184.379 +            throw new IllegalArgumentException("Invalid substring range");
 184.380 +        }
 184.381 +        if (beginIndex == endIndex) {
 184.382 +            if (attributes.isEmpty())
 184.383 +                return;
 184.384 +            throw new IllegalArgumentException("Can't add attribute to 0-length text");
 184.385 +        }
 184.386 +
 184.387 +        // make sure we have run attribute data vectors
 184.388 +        if (runCount == 0) {
 184.389 +            createRunAttributeDataVectors();
 184.390 +        }
 184.391 +
 184.392 +        // break up runs if necessary
 184.393 +        int beginRunIndex = ensureRunBreak(beginIndex);
 184.394 +        int endRunIndex = ensureRunBreak(endIndex);
 184.395 +
 184.396 +        Iterator iterator = attributes.entrySet().iterator();
 184.397 +        while (iterator.hasNext()) {
 184.398 +            Map.Entry entry = (Map.Entry) iterator.next();
 184.399 +            addAttributeRunData((Attribute) entry.getKey(), entry.getValue(), beginRunIndex, endRunIndex);
 184.400 +        }
 184.401 +    }
 184.402 +
 184.403 +    private synchronized void addAttributeImpl(Attribute attribute, Object value,
 184.404 +            int beginIndex, int endIndex) {
 184.405 +
 184.406 +        // make sure we have run attribute data vectors
 184.407 +        if (runCount == 0) {
 184.408 +            createRunAttributeDataVectors();
 184.409 +        }
 184.410 +
 184.411 +        // break up runs if necessary
 184.412 +        int beginRunIndex = ensureRunBreak(beginIndex);
 184.413 +        int endRunIndex = ensureRunBreak(endIndex);
 184.414 +
 184.415 +        addAttributeRunData(attribute, value, beginRunIndex, endRunIndex);
 184.416 +    }
 184.417 +
 184.418 +    private final void createRunAttributeDataVectors() {
 184.419 +        // use temporary variables so things remain consistent in case of an exception
 184.420 +        int newRunStarts[] = new int[ARRAY_SIZE_INCREMENT];
 184.421 +        Vector newRunAttributes[] = new Vector[ARRAY_SIZE_INCREMENT];
 184.422 +        Vector newRunAttributeValues[] = new Vector[ARRAY_SIZE_INCREMENT];
 184.423 +        runStarts = newRunStarts;
 184.424 +        runAttributes = newRunAttributes;
 184.425 +        runAttributeValues = newRunAttributeValues;
 184.426 +        runArraySize = ARRAY_SIZE_INCREMENT;
 184.427 +        runCount = 1; // assume initial run starting at index 0
 184.428 +    }
 184.429 +
 184.430 +    // ensure there's a run break at offset, return the index of the run
 184.431 +    private final int ensureRunBreak(int offset) {
 184.432 +        return ensureRunBreak(offset, true);
 184.433 +    }
 184.434 +
 184.435 +    /**
 184.436 +     * Ensures there is a run break at offset, returning the index of
 184.437 +     * the run. If this results in splitting a run, two things can happen:
 184.438 +     * <ul>
 184.439 +     * <li>If copyAttrs is true, the attributes from the existing run
 184.440 +     *     will be placed in both of the newly created runs.
 184.441 +     * <li>If copyAttrs is false, the attributes from the existing run
 184.442 +     * will NOT be copied to the run to the right (>= offset) of the break,
 184.443 +     * but will exist on the run to the left (< offset).
 184.444 +     * </ul>
 184.445 +     */
 184.446 +    private final int ensureRunBreak(int offset, boolean copyAttrs) {
 184.447 +        if (offset == length()) {
 184.448 +            return runCount;
 184.449 +        }
 184.450 +
 184.451 +        // search for the run index where this offset should be
 184.452 +        int runIndex = 0;
 184.453 +        while (runIndex < runCount && runStarts[runIndex] < offset) {
 184.454 +            runIndex++;
 184.455 +        }
 184.456 +
 184.457 +        // if the offset is at a run start already, we're done
 184.458 +        if (runIndex < runCount && runStarts[runIndex] == offset) {
 184.459 +            return runIndex;
 184.460 +        }
 184.461 +
 184.462 +        // we'll have to break up a run
 184.463 +        // first, make sure we have enough space in our arrays
 184.464 +        if (runCount == runArraySize) {
 184.465 +            int newArraySize = runArraySize + ARRAY_SIZE_INCREMENT;
 184.466 +            int newRunStarts[] = new int[newArraySize];
 184.467 +            Vector newRunAttributes[] = new Vector[newArraySize];
 184.468 +            Vector newRunAttributeValues[] = new Vector[newArraySize];
 184.469 +            for (int i = 0; i < runArraySize; i++) {
 184.470 +                newRunStarts[i] = runStarts[i];
 184.471 +                newRunAttributes[i] = runAttributes[i];
 184.472 +                newRunAttributeValues[i] = runAttributeValues[i];
 184.473 +            }
 184.474 +            runStarts = newRunStarts;
 184.475 +            runAttributes = newRunAttributes;
 184.476 +            runAttributeValues = newRunAttributeValues;
 184.477 +            runArraySize = newArraySize;
 184.478 +        }
 184.479 +
 184.480 +        // make copies of the attribute information of the old run that the new one used to be part of
 184.481 +        // use temporary variables so things remain consistent in case of an exception
 184.482 +        Vector newRunAttributes = null;
 184.483 +        Vector newRunAttributeValues = null;
 184.484 +
 184.485 +        if (copyAttrs) {
 184.486 +            Vector oldRunAttributes = runAttributes[runIndex - 1];
 184.487 +            Vector oldRunAttributeValues = runAttributeValues[runIndex - 1];
 184.488 +            if (oldRunAttributes != null) {
 184.489 +                newRunAttributes = (Vector) oldRunAttributes.clone();
 184.490 +            }
 184.491 +            if (oldRunAttributeValues != null) {
 184.492 +                newRunAttributeValues = (Vector) oldRunAttributeValues.clone();
 184.493 +            }
 184.494 +        }
 184.495 +
 184.496 +        // now actually break up the run
 184.497 +        runCount++;
 184.498 +        for (int i = runCount - 1; i > runIndex; i--) {
 184.499 +            runStarts[i] = runStarts[i - 1];
 184.500 +            runAttributes[i] = runAttributes[i - 1];
 184.501 +            runAttributeValues[i] = runAttributeValues[i - 1];
 184.502 +        }
 184.503 +        runStarts[runIndex] = offset;
 184.504 +        runAttributes[runIndex] = newRunAttributes;
 184.505 +        runAttributeValues[runIndex] = newRunAttributeValues;
 184.506 +
 184.507 +        return runIndex;
 184.508 +    }
 184.509 +
 184.510 +    // add the attribute attribute/value to all runs where beginRunIndex <= runIndex < endRunIndex
 184.511 +    private void addAttributeRunData(Attribute attribute, Object value,
 184.512 +            int beginRunIndex, int endRunIndex) {
 184.513 +
 184.514 +        for (int i = beginRunIndex; i < endRunIndex; i++) {
 184.515 +            int keyValueIndex = -1; // index of key and value in our vectors; assume we don't have an entry yet
 184.516 +            if (runAttributes[i] == null) {
 184.517 +                Vector newRunAttributes = new Vector();
 184.518 +                Vector newRunAttributeValues = new Vector();
 184.519 +                runAttributes[i] = newRunAttributes;
 184.520 +                runAttributeValues[i] = newRunAttributeValues;
 184.521 +            } else {
 184.522 +                // check whether we have an entry already
 184.523 +                keyValueIndex = runAttributes[i].indexOf(attribute);
 184.524 +            }
 184.525 +
 184.526 +            if (keyValueIndex == -1) {
 184.527 +                // create new entry
 184.528 +                int oldSize = runAttributes[i].size();
 184.529 +                runAttributes[i].addElement(attribute);
 184.530 +                try {
 184.531 +                    runAttributeValues[i].addElement(value);
 184.532 +                }
 184.533 +                catch (Exception e) {
 184.534 +                    runAttributes[i].setSize(oldSize);
 184.535 +                    runAttributeValues[i].setSize(oldSize);
 184.536 +                }
 184.537 +            } else {
 184.538 +                // update existing entry
 184.539 +                runAttributeValues[i].set(keyValueIndex, value);
 184.540 +            }
 184.541 +        }
 184.542 +    }
 184.543 +
 184.544 +    /**
 184.545 +     * Creates an AttributedCharacterIterator instance that provides access to the entire contents of
 184.546 +     * this string.
 184.547 +     *
 184.548 +     * @return An iterator providing access to the text and its attributes.
 184.549 +     */
 184.550 +    public AttributedCharacterIterator getIterator() {
 184.551 +        return getIterator(null, 0, length());
 184.552 +    }
 184.553 +
 184.554 +    /**
 184.555 +     * Creates an AttributedCharacterIterator instance that provides access to
 184.556 +     * selected contents of this string.
 184.557 +     * Information about attributes not listed in attributes that the
 184.558 +     * implementor may have need not be made accessible through the iterator.
 184.559 +     * If the list is null, all available attribute information should be made
 184.560 +     * accessible.
 184.561 +     *
 184.562 +     * @param attributes a list of attributes that the client is interested in
 184.563 +     * @return an iterator providing access to the entire text and its selected attributes
 184.564 +     */
 184.565 +    public AttributedCharacterIterator getIterator(Attribute[] attributes) {
 184.566 +        return getIterator(attributes, 0, length());
 184.567 +    }
 184.568 +
 184.569 +    /**
 184.570 +     * Creates an AttributedCharacterIterator instance that provides access to
 184.571 +     * selected contents of this string.
 184.572 +     * Information about attributes not listed in attributes that the
 184.573 +     * implementor may have need not be made accessible through the iterator.
 184.574 +     * If the list is null, all available attribute information should be made
 184.575 +     * accessible.
 184.576 +     *
 184.577 +     * @param attributes a list of attributes that the client is interested in
 184.578 +     * @param beginIndex the index of the first character
 184.579 +     * @param endIndex the index of the character following the last character
 184.580 +     * @return an iterator providing access to the text and its attributes
 184.581 +     * @exception IllegalArgumentException if beginIndex is less then 0,
 184.582 +     * endIndex is greater than the length of the string, or beginIndex is
 184.583 +     * greater than endIndex.
 184.584 +     */
 184.585 +    public AttributedCharacterIterator getIterator(Attribute[] attributes, int beginIndex, int endIndex) {
 184.586 +        return new AttributedStringIterator(attributes, beginIndex, endIndex);
 184.587 +    }
 184.588 +
 184.589 +    // all (with the exception of length) reading operations are private,
 184.590 +    // since AttributedString instances are accessed through iterators.
 184.591 +
 184.592 +    // length is package private so that CharacterIteratorFieldDelegate can
 184.593 +    // access it without creating an AttributedCharacterIterator.
 184.594 +    int length() {
 184.595 +        return text.length();
 184.596 +    }
 184.597 +
 184.598 +    private char charAt(int index) {
 184.599 +        return text.charAt(index);
 184.600 +    }
 184.601 +
 184.602 +    private synchronized Object getAttribute(Attribute attribute, int runIndex) {
 184.603 +        Vector currentRunAttributes = runAttributes[runIndex];
 184.604 +        Vector currentRunAttributeValues = runAttributeValues[runIndex];
 184.605 +        if (currentRunAttributes == null) {
 184.606 +            return null;
 184.607 +        }
 184.608 +        int attributeIndex = currentRunAttributes.indexOf(attribute);
 184.609 +        if (attributeIndex != -1) {
 184.610 +            return currentRunAttributeValues.elementAt(attributeIndex);
 184.611 +        }
 184.612 +        else {
 184.613 +            return null;
 184.614 +        }
 184.615 +    }
 184.616 +
 184.617 +    // gets an attribute value, but returns an annotation only if it's range does not extend outside the range beginIndex..endIndex
 184.618 +    private Object getAttributeCheckRange(Attribute attribute, int runIndex, int beginIndex, int endIndex) {
 184.619 +        Object value = getAttribute(attribute, runIndex);
 184.620 +        if (value instanceof Annotation) {
 184.621 +            // need to check whether the annotation's range extends outside the iterator's range
 184.622 +            if (beginIndex > 0) {
 184.623 +                int currIndex = runIndex;
 184.624 +                int runStart = runStarts[currIndex];
 184.625 +                while (runStart >= beginIndex &&
 184.626 +                        valuesMatch(value, getAttribute(attribute, currIndex - 1))) {
 184.627 +                    currIndex--;
 184.628 +                    runStart = runStarts[currIndex];
 184.629 +                }
 184.630 +                if (runStart < beginIndex) {
 184.631 +                    // annotation's range starts before iterator's range
 184.632 +                    return null;
 184.633 +                }
 184.634 +            }
 184.635 +            int textLength = length();
 184.636 +            if (endIndex < textLength) {
 184.637 +                int currIndex = runIndex;
 184.638 +                int runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength;
 184.639 +                while (runLimit <= endIndex &&
 184.640 +                        valuesMatch(value, getAttribute(attribute, currIndex + 1))) {
 184.641 +                    currIndex++;
 184.642 +                    runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength;
 184.643 +                }
 184.644 +                if (runLimit > endIndex) {
 184.645 +                    // annotation's range ends after iterator's range
 184.646 +                    return null;
 184.647 +                }
 184.648 +            }
 184.649 +            // annotation's range is subrange of iterator's range,
 184.650 +            // so we can return the value
 184.651 +        }
 184.652 +        return value;
 184.653 +    }
 184.654 +
 184.655 +    // returns whether all specified attributes have equal values in the runs with the given indices
 184.656 +    private boolean attributeValuesMatch(Set attributes, int runIndex1, int runIndex2) {
 184.657 +        Iterator iterator = attributes.iterator();
 184.658 +        while (iterator.hasNext()) {
 184.659 +            Attribute key = (Attribute) iterator.next();
 184.660 +           if (!valuesMatch(getAttribute(key, runIndex1), getAttribute(key, runIndex2))) {
 184.661 +                return false;
 184.662 +            }
 184.663 +        }
 184.664 +        return true;
 184.665 +    }
 184.666 +
 184.667 +    // returns whether the two objects are either both null or equal
 184.668 +    private final static boolean valuesMatch(Object value1, Object value2) {
 184.669 +        if (value1 == null) {
 184.670 +            return value2 == null;
 184.671 +        } else {
 184.672 +            return value1.equals(value2);
 184.673 +        }
 184.674 +    }
 184.675 +
 184.676 +    /**
 184.677 +     * Appends the contents of the CharacterIterator iterator into the
 184.678 +     * StringBuffer buf.
 184.679 +     */
 184.680 +    private final void appendContents(StringBuffer buf,
 184.681 +                                      CharacterIterator iterator) {
 184.682 +        int index = iterator.getBeginIndex();
 184.683 +        int end = iterator.getEndIndex();
 184.684 +
 184.685 +        while (index < end) {
 184.686 +            iterator.setIndex(index++);
 184.687 +            buf.append(iterator.current());
 184.688 +        }
 184.689 +    }
 184.690 +
 184.691 +    /**
 184.692 +     * Sets the attributes for the range from offset to the next run break
 184.693 +     * (typically the end of the text) to the ones specified in attrs.
 184.694 +     * This is only meant to be called from the constructor!
 184.695 +     */
 184.696 +    private void setAttributes(Map attrs, int offset) {
 184.697 +        if (runCount == 0) {
 184.698 +            createRunAttributeDataVectors();
 184.699 +        }
 184.700 +
 184.701 +        int index = ensureRunBreak(offset, false);
 184.702 +        int size;
 184.703 +
 184.704 +        if (attrs != null && (size = attrs.size()) > 0) {
 184.705 +            Vector runAttrs = new Vector(size);
 184.706 +            Vector runValues = new Vector(size);
 184.707 +            Iterator iterator = attrs.entrySet().iterator();
 184.708 +
 184.709 +            while (iterator.hasNext()) {
 184.710 +                Map.Entry entry = (Map.Entry)iterator.next();
 184.711 +
 184.712 +                runAttrs.add(entry.getKey());
 184.713 +                runValues.add(entry.getValue());
 184.714 +            }
 184.715 +            runAttributes[index] = runAttrs;
 184.716 +            runAttributeValues[index] = runValues;
 184.717 +        }
 184.718 +    }
 184.719 +
 184.720 +    /**
 184.721 +     * Returns true if the attributes specified in last and attrs differ.
 184.722 +     */
 184.723 +    private static boolean mapsDiffer(Map last, Map attrs) {
 184.724 +        if (last == null) {
 184.725 +            return (attrs != null && attrs.size() > 0);
 184.726 +        }
 184.727 +        return (!last.equals(attrs));
 184.728 +    }
 184.729 +
 184.730 +
 184.731 +    // the iterator class associated with this string class
 184.732 +
 184.733 +    final private class AttributedStringIterator implements AttributedCharacterIterator {
 184.734 +
 184.735 +        // note on synchronization:
 184.736 +        // we don't synchronize on the iterator, assuming that an iterator is only used in one thread.
 184.737 +        // we do synchronize access to the AttributedString however, since it's more likely to be shared between threads.
 184.738 +
 184.739 +        // start and end index for our iteration
 184.740 +        private int beginIndex;
 184.741 +        private int endIndex;
 184.742 +
 184.743 +        // attributes that our client is interested in
 184.744 +        private Attribute[] relevantAttributes;
 184.745 +
 184.746 +        // the current index for our iteration
 184.747 +        // invariant: beginIndex <= currentIndex <= endIndex
 184.748 +        private int currentIndex;
 184.749 +
 184.750 +        // information about the run that includes currentIndex
 184.751 +        private int currentRunIndex;
 184.752 +        private int currentRunStart;
 184.753 +        private int currentRunLimit;
 184.754 +
 184.755 +        // constructor
 184.756 +        AttributedStringIterator(Attribute[] attributes, int beginIndex, int endIndex) {
 184.757 +
 184.758 +            if (beginIndex < 0 || beginIndex > endIndex || endIndex > length()) {
 184.759 +                throw new IllegalArgumentException("Invalid substring range");
 184.760 +            }
 184.761 +
 184.762 +            this.beginIndex = beginIndex;
 184.763 +            this.endIndex = endIndex;
 184.764 +            this.currentIndex = beginIndex;
 184.765 +            updateRunInfo();
 184.766 +            if (attributes != null) {
 184.767 +                relevantAttributes = (Attribute[]) attributes.clone();
 184.768 +            }
 184.769 +        }
 184.770 +
 184.771 +        // Object methods. See documentation in that class.
 184.772 +
 184.773 +        public boolean equals(Object obj) {
 184.774 +            if (this == obj) {
 184.775 +                return true;
 184.776 +            }
 184.777 +            if (!(obj instanceof AttributedStringIterator)) {
 184.778 +                return false;
 184.779 +            }
 184.780 +
 184.781 +            AttributedStringIterator that = (AttributedStringIterator) obj;
 184.782 +
 184.783 +            if (AttributedString.this != that.getString())
 184.784 +                return false;
 184.785 +            if (currentIndex != that.currentIndex || beginIndex != that.beginIndex || endIndex != that.endIndex)
 184.786 +                return false;
 184.787 +            return true;
 184.788 +        }
 184.789 +
 184.790 +        public int hashCode() {
 184.791 +            return text.hashCode() ^ currentIndex ^ beginIndex ^ endIndex;
 184.792 +        }
 184.793 +
 184.794 +        public Object clone() {
 184.795 +            try {
 184.796 +                AttributedStringIterator other = (AttributedStringIterator) super.clone();
 184.797 +                return other;
 184.798 +            }
 184.799 +            catch (CloneNotSupportedException e) {
 184.800 +                throw new InternalError();
 184.801 +            }
 184.802 +        }
 184.803 +
 184.804 +        // CharacterIterator methods. See documentation in that interface.
 184.805 +
 184.806 +        public char first() {
 184.807 +            return internalSetIndex(beginIndex);
 184.808 +        }
 184.809 +
 184.810 +        public char last() {
 184.811 +            if (endIndex == beginIndex) {
 184.812 +                return internalSetIndex(endIndex);
 184.813 +            } else {
 184.814 +                return internalSetIndex(endIndex - 1);
 184.815 +            }
 184.816 +        }
 184.817 +
 184.818 +        public char current() {
 184.819 +            if (currentIndex == endIndex) {
 184.820 +                return DONE;
 184.821 +            } else {
 184.822 +                return charAt(currentIndex);
 184.823 +            }
 184.824 +        }
 184.825 +
 184.826 +        public char next() {
 184.827 +            if (currentIndex < endIndex) {
 184.828 +                return internalSetIndex(currentIndex + 1);
 184.829 +            }
 184.830 +            else {
 184.831 +                return DONE;
 184.832 +            }
 184.833 +        }
 184.834 +
 184.835 +        public char previous() {
 184.836 +            if (currentIndex > beginIndex) {
 184.837 +                return internalSetIndex(currentIndex - 1);
 184.838 +            }
 184.839 +            else {
 184.840 +                return DONE;
 184.841 +            }
 184.842 +        }
 184.843 +
 184.844 +        public char setIndex(int position) {
 184.845 +            if (position < beginIndex || position > endIndex)
 184.846 +                throw new IllegalArgumentException("Invalid index");
 184.847 +            return internalSetIndex(position);
 184.848 +        }
 184.849 +
 184.850 +        public int getBeginIndex() {
 184.851 +            return beginIndex;
 184.852 +        }
 184.853 +
 184.854 +        public int getEndIndex() {
 184.855 +            return endIndex;
 184.856 +        }
 184.857 +
 184.858 +        public int getIndex() {
 184.859 +            return currentIndex;
 184.860 +        }
 184.861 +
 184.862 +        // AttributedCharacterIterator methods. See documentation in that interface.
 184.863 +
 184.864 +        public int getRunStart() {
 184.865 +            return currentRunStart;
 184.866 +        }
 184.867 +
 184.868 +        public int getRunStart(Attribute attribute) {
 184.869 +            if (currentRunStart == beginIndex || currentRunIndex == -1) {
 184.870 +                return currentRunStart;
 184.871 +            } else {
 184.872 +                Object value = getAttribute(attribute);
 184.873 +                int runStart = currentRunStart;
 184.874 +                int runIndex = currentRunIndex;
 184.875 +                while (runStart > beginIndex &&
 184.876 +                        valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) {
 184.877 +                    runIndex--;
 184.878 +                    runStart = runStarts[runIndex];
 184.879 +                }
 184.880 +                if (runStart < beginIndex) {
 184.881 +                    runStart = beginIndex;
 184.882 +                }
 184.883 +                return runStart;
 184.884 +            }
 184.885 +        }
 184.886 +
 184.887 +        public int getRunStart(Set<? extends Attribute> attributes) {
 184.888 +            if (currentRunStart == beginIndex || currentRunIndex == -1) {
 184.889 +                return currentRunStart;
 184.890 +            } else {
 184.891 +                int runStart = currentRunStart;
 184.892 +                int runIndex = currentRunIndex;
 184.893 +                while (runStart > beginIndex &&
 184.894 +                        AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex - 1)) {
 184.895 +                    runIndex--;
 184.896 +                    runStart = runStarts[runIndex];
 184.897 +                }
 184.898 +                if (runStart < beginIndex) {
 184.899 +                    runStart = beginIndex;
 184.900 +                }
 184.901 +                return runStart;
 184.902 +            }
 184.903 +        }
 184.904 +
 184.905 +        public int getRunLimit() {
 184.906 +            return currentRunLimit;
 184.907 +        }
 184.908 +
 184.909 +        public int getRunLimit(Attribute attribute) {
 184.910 +            if (currentRunLimit == endIndex || currentRunIndex == -1) {
 184.911 +                return currentRunLimit;
 184.912 +            } else {
 184.913 +                Object value = getAttribute(attribute);
 184.914 +                int runLimit = currentRunLimit;
 184.915 +                int runIndex = currentRunIndex;
 184.916 +                while (runLimit < endIndex &&
 184.917 +                        valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) {
 184.918 +                    runIndex++;
 184.919 +                    runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
 184.920 +                }
 184.921 +                if (runLimit > endIndex) {
 184.922 +                    runLimit = endIndex;
 184.923 +                }
 184.924 +                return runLimit;
 184.925 +            }
 184.926 +        }
 184.927 +
 184.928 +        public int getRunLimit(Set<? extends Attribute> attributes) {
 184.929 +            if (currentRunLimit == endIndex || currentRunIndex == -1) {
 184.930 +                return currentRunLimit;
 184.931 +            } else {
 184.932 +                int runLimit = currentRunLimit;
 184.933 +                int runIndex = currentRunIndex;
 184.934 +                while (runLimit < endIndex &&
 184.935 +                        AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) {
 184.936 +                    runIndex++;
 184.937 +                    runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
 184.938 +                }
 184.939 +                if (runLimit > endIndex) {
 184.940 +                    runLimit = endIndex;
 184.941 +                }
 184.942 +                return runLimit;
 184.943 +            }
 184.944 +        }
 184.945 +
 184.946 +        public Map<Attribute,Object> getAttributes() {
 184.947 +            if (runAttributes == null || currentRunIndex == -1 || runAttributes[currentRunIndex] == null) {
 184.948 +                // ??? would be nice to return null, but current spec doesn't allow it
 184.949 +                // returning Hashtable saves AttributeMap from dealing with emptiness
 184.950 +                return new Hashtable();
 184.951 +            }
 184.952 +            return new AttributeMap(currentRunIndex, beginIndex, endIndex);
 184.953 +        }
 184.954 +
 184.955 +        public Set<Attribute> getAllAttributeKeys() {
 184.956 +            // ??? This should screen out attribute keys that aren't relevant to the client
 184.957 +            if (runAttributes == null) {
 184.958 +                // ??? would be nice to return null, but current spec doesn't allow it
 184.959 +                // returning HashSet saves us from dealing with emptiness
 184.960 +                return new HashSet();
 184.961 +            }
 184.962 +            synchronized (AttributedString.this) {
 184.963 +                // ??? should try to create this only once, then update if necessary,
 184.964 +                // and give callers read-only view
 184.965 +                Set keys = new HashSet();
 184.966 +                int i = 0;
 184.967 +                while (i < runCount) {
 184.968 +                    if (runStarts[i] < endIndex && (i == runCount - 1 || runStarts[i + 1] > beginIndex)) {
 184.969 +                        Vector currentRunAttributes = runAttributes[i];
 184.970 +                        if (currentRunAttributes != null) {
 184.971 +                            int j = currentRunAttributes.size();
 184.972 +                            while (j-- > 0) {
 184.973 +                                keys.add(currentRunAttributes.get(j));
 184.974 +                            }
 184.975 +                        }
 184.976 +                    }
 184.977 +                    i++;
 184.978 +                }
 184.979 +                return keys;
 184.980 +            }
 184.981 +        }
 184.982 +
 184.983 +        public Object getAttribute(Attribute attribute) {
 184.984 +            int runIndex = currentRunIndex;
 184.985 +            if (runIndex < 0) {
 184.986 +                return null;
 184.987 +            }
 184.988 +            return AttributedString.this.getAttributeCheckRange(attribute, runIndex, beginIndex, endIndex);
 184.989 +        }
 184.990 +
 184.991 +        // internally used methods
 184.992 +
 184.993 +        private AttributedString getString() {
 184.994 +            return AttributedString.this;
 184.995 +        }
 184.996 +
 184.997 +        // set the current index, update information about the current run if necessary,
 184.998 +        // return the character at the current index
 184.999 +        private char internalSetIndex(int position) {
184.1000 +            currentIndex = position;
184.1001 +            if (position < currentRunStart || position >= currentRunLimit) {
184.1002 +                updateRunInfo();
184.1003 +            }
184.1004 +            if (currentIndex == endIndex) {
184.1005 +                return DONE;
184.1006 +            } else {
184.1007 +                return charAt(position);
184.1008 +            }
184.1009 +        }
184.1010 +
184.1011 +        // update the information about the current run
184.1012 +        private void updateRunInfo() {
184.1013 +            if (currentIndex == endIndex) {
184.1014 +                currentRunStart = currentRunLimit = endIndex;
184.1015 +                currentRunIndex = -1;
184.1016 +            } else {
184.1017 +                synchronized (AttributedString.this) {
184.1018 +                    int runIndex = -1;
184.1019 +                    while (runIndex < runCount - 1 && runStarts[runIndex + 1] <= currentIndex)
184.1020 +                        runIndex++;
184.1021 +                    currentRunIndex = runIndex;
184.1022 +                    if (runIndex >= 0) {
184.1023 +                        currentRunStart = runStarts[runIndex];
184.1024 +                        if (currentRunStart < beginIndex)
184.1025 +                            currentRunStart = beginIndex;
184.1026 +                    }
184.1027 +                    else {
184.1028 +                        currentRunStart = beginIndex;
184.1029 +                    }
184.1030 +                    if (runIndex < runCount - 1) {
184.1031 +                        currentRunLimit = runStarts[runIndex + 1];
184.1032 +                        if (currentRunLimit > endIndex)
184.1033 +                            currentRunLimit = endIndex;
184.1034 +                    }
184.1035 +                    else {
184.1036 +                        currentRunLimit = endIndex;
184.1037 +                    }
184.1038 +                }
184.1039 +            }
184.1040 +        }
184.1041 +
184.1042 +    }
184.1043 +
184.1044 +    // the map class associated with this string class, giving access to the attributes of one run
184.1045 +
184.1046 +    final private class AttributeMap extends AbstractMap<Attribute,Object> {
184.1047 +
184.1048 +        int runIndex;
184.1049 +        int beginIndex;
184.1050 +        int endIndex;
184.1051 +
184.1052 +        AttributeMap(int runIndex, int beginIndex, int endIndex) {
184.1053 +            this.runIndex = runIndex;
184.1054 +            this.beginIndex = beginIndex;
184.1055 +            this.endIndex = endIndex;
184.1056 +        }
184.1057 +
184.1058 +        public Set entrySet() {
184.1059 +            HashSet set = new HashSet();
184.1060 +            synchronized (AttributedString.this) {
184.1061 +                int size = runAttributes[runIndex].size();
184.1062 +                for (int i = 0; i < size; i++) {
184.1063 +                    Attribute key = (Attribute) runAttributes[runIndex].get(i);
184.1064 +                    Object value = runAttributeValues[runIndex].get(i);
184.1065 +                    if (value instanceof Annotation) {
184.1066 +                        value = AttributedString.this.getAttributeCheckRange(key,
184.1067 +                                                             runIndex, beginIndex, endIndex);
184.1068 +                        if (value == null) {
184.1069 +                            continue;
184.1070 +                        }
184.1071 +                    }
184.1072 +                    Map.Entry entry = new AttributeEntry(key, value);
184.1073 +                    set.add(entry);
184.1074 +                }
184.1075 +            }
184.1076 +            return set;
184.1077 +        }
184.1078 +
184.1079 +        public Object get(Object key) {
184.1080 +            return AttributedString.this.getAttributeCheckRange((Attribute) key, runIndex, beginIndex, endIndex);
184.1081 +        }
184.1082 +    }
184.1083 +}
184.1084 +
184.1085 +class AttributeEntry implements Map.Entry {
184.1086 +
184.1087 +    private Attribute key;
184.1088 +    private Object value;
184.1089 +
184.1090 +    AttributeEntry(Attribute key, Object value) {
184.1091 +        this.key = key;
184.1092 +        this.value = value;
184.1093 +    }
184.1094 +
184.1095 +    public boolean equals(Object o) {
184.1096 +        if (!(o instanceof AttributeEntry)) {
184.1097 +            return false;
184.1098 +        }
184.1099 +        AttributeEntry other = (AttributeEntry) o;
184.1100 +        return other.key.equals(key) &&
184.1101 +            (value == null ? other.value == null : other.value.equals(value));
184.1102 +    }
184.1103 +
184.1104 +    public Object getKey() {
184.1105 +        return key;
184.1106 +    }
184.1107 +
184.1108 +    public Object getValue() {
184.1109 +        return value;
184.1110 +    }
184.1111 +
184.1112 +    public Object setValue(Object newValue) {
184.1113 +        throw new UnsupportedOperationException();
184.1114 +    }
184.1115 +
184.1116 +    public int hashCode() {
184.1117 +        return key.hashCode() ^ (value==null ? 0 : value.hashCode());
184.1118 +    }
184.1119 +
184.1120 +    public String toString() {
184.1121 +        return key.toString()+"="+value.toString();
184.1122 +    }
184.1123 +}
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/rt/emul/compact/src/main/java/java/text/CalendarBuilder.java	Wed Apr 30 15:04:10 2014 +0200
   185.3 @@ -0,0 +1,170 @@
   185.4 +/*
   185.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   185.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   185.7 + *
   185.8 + * This code is free software; you can redistribute it and/or modify it
   185.9 + * under the terms of the GNU General Public License version 2 only, as
  185.10 + * published by the Free Software Foundation.  Oracle designates this
  185.11 + * particular file as subject to the "Classpath" exception as provided
  185.12 + * by Oracle in the LICENSE file that accompanied this code.
  185.13 + *
  185.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  185.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  185.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  185.17 + * version 2 for more details (a copy is included in the LICENSE file that
  185.18 + * accompanied this code).
  185.19 + *
  185.20 + * You should have received a copy of the GNU General Public License version
  185.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  185.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  185.23 + *
  185.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  185.25 + * or visit www.oracle.com if you need additional information or have any
  185.26 + * questions.
  185.27 + */
  185.28 +
  185.29 +package java.text;
  185.30 +
  185.31 +import java.util.Calendar;
  185.32 +import static java.util.Calendar.*;
  185.33 +
  185.34 +/**
  185.35 + * {@code CalendarBuilder} keeps field-value pairs for setting
  185.36 + * the calendar fields of the given {@code Calendar}. It has the
  185.37 + * {@link Calendar#FIELD_COUNT FIELD_COUNT}-th field for the week year
  185.38 + * support. Also {@code ISO_DAY_OF_WEEK} is used to specify
  185.39 + * {@code DAY_OF_WEEK} in the ISO day of week numbering.
  185.40 + *
  185.41 + * <p>{@code CalendarBuilder} retains the semantic of the pseudo
  185.42 + * timestamp for fields. {@code CalendarBuilder} uses a single
  185.43 + * int array combining fields[] and stamp[] of {@code Calendar}.
  185.44 + *
  185.45 + * @author Masayoshi Okutsu
  185.46 + */
  185.47 +class CalendarBuilder {
  185.48 +    /*
  185.49 +     * Pseudo time stamp constants used in java.util.Calendar
  185.50 +     */
  185.51 +    private static final int UNSET = 0;
  185.52 +    private static final int COMPUTED = 1;
  185.53 +    private static final int MINIMUM_USER_STAMP = 2;
  185.54 +
  185.55 +    private static final int MAX_FIELD = FIELD_COUNT + 1;
  185.56 +
  185.57 +    public static final int WEEK_YEAR = FIELD_COUNT;
  185.58 +    public static final int ISO_DAY_OF_WEEK = 1000; // pseudo field index
  185.59 +
  185.60 +    // stamp[] (lower half) and field[] (upper half) combined
  185.61 +    private final int[] field;
  185.62 +    private int nextStamp;
  185.63 +    private int maxFieldIndex;
  185.64 +
  185.65 +    CalendarBuilder() {
  185.66 +        field = new int[MAX_FIELD * 2];
  185.67 +        nextStamp = MINIMUM_USER_STAMP;
  185.68 +        maxFieldIndex = -1;
  185.69 +    }
  185.70 +
  185.71 +    CalendarBuilder set(int index, int value) {
  185.72 +        if (index == ISO_DAY_OF_WEEK) {
  185.73 +            index = DAY_OF_WEEK;
  185.74 +            value = toCalendarDayOfWeek(value);
  185.75 +        }
  185.76 +        field[index] = nextStamp++;
  185.77 +        field[MAX_FIELD + index] = value;
  185.78 +        if (index > maxFieldIndex && index < FIELD_COUNT) {
  185.79 +            maxFieldIndex = index;
  185.80 +        }
  185.81 +        return this;
  185.82 +    }
  185.83 +
  185.84 +    CalendarBuilder addYear(int value) {
  185.85 +        field[MAX_FIELD + YEAR] += value;
  185.86 +        field[MAX_FIELD + WEEK_YEAR] += value;
  185.87 +        return this;
  185.88 +    }
  185.89 +
  185.90 +    boolean isSet(int index) {
  185.91 +        if (index == ISO_DAY_OF_WEEK) {
  185.92 +            index = DAY_OF_WEEK;
  185.93 +        }
  185.94 +        return field[index] > UNSET;
  185.95 +    }
  185.96 +
  185.97 +    Calendar establish(Calendar cal) {
  185.98 +        boolean weekDate = isSet(WEEK_YEAR)
  185.99 +                            && field[WEEK_YEAR] > field[YEAR];
 185.100 +        if (weekDate && !cal.isWeekDateSupported()) {
 185.101 +            // Use YEAR instead
 185.102 +            if (!isSet(YEAR)) {
 185.103 +                set(YEAR, field[MAX_FIELD + WEEK_YEAR]);
 185.104 +            }
 185.105 +            weekDate = false;
 185.106 +        }
 185.107 +
 185.108 +        cal.clear();
 185.109 +        // Set the fields from the min stamp to the max stamp so that
 185.110 +        // the field resolution works in the Calendar.
 185.111 +        for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
 185.112 +            for (int index = 0; index <= maxFieldIndex; index++) {
 185.113 +                if (field[index] == stamp) {
 185.114 +                    cal.set(index, field[MAX_FIELD + index]);
 185.115 +                    break;
 185.116 +                }
 185.117 +            }
 185.118 +        }
 185.119 +
 185.120 +        if (weekDate) {
 185.121 +            int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1;
 185.122 +            int dayOfWeek = isSet(DAY_OF_WEEK) ?
 185.123 +                                field[MAX_FIELD + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
 185.124 +            if (!isValidDayOfWeek(dayOfWeek) && cal.isLenient()) {
 185.125 +                if (dayOfWeek >= 8) {
 185.126 +                    dayOfWeek--;
 185.127 +                    weekOfYear += dayOfWeek / 7;
 185.128 +                    dayOfWeek = (dayOfWeek % 7) + 1;
 185.129 +                } else {
 185.130 +                    while (dayOfWeek <= 0) {
 185.131 +                        dayOfWeek += 7;
 185.132 +                        weekOfYear--;
 185.133 +                    }
 185.134 +                }
 185.135 +                dayOfWeek = toCalendarDayOfWeek(dayOfWeek);
 185.136 +            }
 185.137 +            cal.setWeekDate(field[MAX_FIELD + WEEK_YEAR], weekOfYear, dayOfWeek);
 185.138 +        }
 185.139 +        return cal;
 185.140 +    }
 185.141 +
 185.142 +    public String toString() {
 185.143 +        StringBuilder sb = new StringBuilder();
 185.144 +        sb.append("CalendarBuilder:[");
 185.145 +        for (int i = 0; i < field.length; i++) {
 185.146 +            if (isSet(i)) {
 185.147 +                sb.append(i).append('=').append(field[MAX_FIELD + i]).append(',');
 185.148 +            }
 185.149 +        }
 185.150 +        int lastIndex = sb.length() - 1;
 185.151 +        if (sb.charAt(lastIndex) == ',') {
 185.152 +            sb.setLength(lastIndex);
 185.153 +        }
 185.154 +        sb.append(']');
 185.155 +        return sb.toString();
 185.156 +    }
 185.157 +
 185.158 +    static int toISODayOfWeek(int calendarDayOfWeek) {
 185.159 +        return calendarDayOfWeek == SUNDAY ? 7 : calendarDayOfWeek - 1;
 185.160 +    }
 185.161 +
 185.162 +    static int toCalendarDayOfWeek(int isoDayOfWeek) {
 185.163 +        if (!isValidDayOfWeek(isoDayOfWeek)) {
 185.164 +            // adjust later for lenient mode
 185.165 +            return isoDayOfWeek;
 185.166 +        }
 185.167 +        return isoDayOfWeek == 7 ? SUNDAY : isoDayOfWeek + 1;
 185.168 +    }
 185.169 +
 185.170 +    static boolean isValidDayOfWeek(int dayOfWeek) {
 185.171 +        return dayOfWeek > 0 && dayOfWeek <= 7;
 185.172 +    }
 185.173 +}
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/rt/emul/compact/src/main/java/java/text/CharacterIterator.java	Wed Apr 30 15:04:10 2014 +0200
   186.3 @@ -0,0 +1,193 @@
   186.4 +/*
   186.5 + * Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
   186.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   186.7 + *
   186.8 + * This code is free software; you can redistribute it and/or modify it
   186.9 + * under the terms of the GNU General Public License version 2 only, as
  186.10 + * published by the Free Software Foundation.  Oracle designates this
  186.11 + * particular file as subject to the "Classpath" exception as provided
  186.12 + * by Oracle in the LICENSE file that accompanied this code.
  186.13 + *
  186.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  186.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  186.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  186.17 + * version 2 for more details (a copy is included in the LICENSE file that
  186.18 + * accompanied this code).
  186.19 + *
  186.20 + * You should have received a copy of the GNU General Public License version
  186.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  186.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  186.23 + *
  186.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  186.25 + * or visit www.oracle.com if you need additional information or have any
  186.26 + * questions.
  186.27 + */
  186.28 +
  186.29 +/*
  186.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  186.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  186.32 + *
  186.33 + * The original version of this source code and documentation
  186.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
  186.35 + * subsidiary of IBM. These materials are provided under terms
  186.36 + * of a License Agreement between Taligent and Sun. This technology
  186.37 + * is protected by multiple US and International patents.
  186.38 + *
  186.39 + * This notice and attribution to Taligent may not be removed.
  186.40 + * Taligent is a registered trademark of Taligent, Inc.
  186.41 + *
  186.42 + */
  186.43 +
  186.44 +package java.text;
  186.45 +
  186.46 +
  186.47 +/**
  186.48 + * This interface defines a protocol for bidirectional iteration over text.
  186.49 + * The iterator iterates over a bounded sequence of characters.  Characters
  186.50 + * are indexed with values beginning with the value returned by getBeginIndex() and
  186.51 + * continuing through the value returned by getEndIndex()-1.
  186.52 + * <p>
  186.53 + * Iterators maintain a current character index, whose valid range is from
  186.54 + * getBeginIndex() to getEndIndex(); the value getEndIndex() is included to allow
  186.55 + * handling of zero-length text ranges and for historical reasons.
  186.56 + * The current index can be retrieved by calling getIndex() and set directly
  186.57 + * by calling setIndex(), first(), and last().
  186.58 + * <p>
  186.59 + * The methods previous() and next() are used for iteration. They return DONE if
  186.60 + * they would move outside the range from getBeginIndex() to getEndIndex() -1,
  186.61 + * signaling that the iterator has reached the end of the sequence. DONE is
  186.62 + * also returned by other methods to indicate that the current index is
  186.63 + * outside this range.
  186.64 + *
  186.65 + * <P>Examples:<P>
  186.66 + *
  186.67 + * Traverse the text from start to finish
  186.68 + * <pre>
  186.69 + * public void traverseForward(CharacterIterator iter) {
  186.70 + *     for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
  186.71 + *         processChar(c);
  186.72 + *     }
  186.73 + * }
  186.74 + * </pre>
  186.75 + *
  186.76 + * Traverse the text backwards, from end to start
  186.77 + * <pre>
  186.78 + * public void traverseBackward(CharacterIterator iter) {
  186.79 + *     for(char c = iter.last(); c != CharacterIterator.DONE; c = iter.previous()) {
  186.80 + *         processChar(c);
  186.81 + *     }
  186.82 + * }
  186.83 + * </pre>
  186.84 + *
  186.85 + * Traverse both forward and backward from a given position in the text.
  186.86 + * Calls to notBoundary() in this example represents some
  186.87 + * additional stopping criteria.
  186.88 + * <pre>
  186.89 + * public void traverseOut(CharacterIterator iter, int pos) {
  186.90 + *     for (char c = iter.setIndex(pos);
  186.91 + *              c != CharacterIterator.DONE && notBoundary(c);
  186.92 + *              c = iter.next()) {
  186.93 + *     }
  186.94 + *     int end = iter.getIndex();
  186.95 + *     for (char c = iter.setIndex(pos);
  186.96 + *             c != CharacterIterator.DONE && notBoundary(c);
  186.97 + *             c = iter.previous()) {
  186.98 + *     }
  186.99 + *     int start = iter.getIndex();
 186.100 + *     processSection(start, end);
 186.101 + * }
 186.102 + * </pre>
 186.103 + *
 186.104 + * @see StringCharacterIterator
 186.105 + * @see AttributedCharacterIterator
 186.106 + */
 186.107 +
 186.108 +public interface CharacterIterator extends Cloneable
 186.109 +{
 186.110 +
 186.111 +    /**
 186.112 +     * Constant that is returned when the iterator has reached either the end
 186.113 +     * or the beginning of the text. The value is '\\uFFFF', the "not a
 186.114 +     * character" value which should not occur in any valid Unicode string.
 186.115 +     */
 186.116 +    public static final char DONE = '\uFFFF';
 186.117 +
 186.118 +    /**
 186.119 +     * Sets the position to getBeginIndex() and returns the character at that
 186.120 +     * position.
 186.121 +     * @return the first character in the text, or DONE if the text is empty
 186.122 +     * @see #getBeginIndex()
 186.123 +     */
 186.124 +    public char first();
 186.125 +
 186.126 +    /**
 186.127 +     * Sets the position to getEndIndex()-1 (getEndIndex() if the text is empty)
 186.128 +     * and returns the character at that position.
 186.129 +     * @return the last character in the text, or DONE if the text is empty
 186.130 +     * @see #getEndIndex()
 186.131 +     */
 186.132 +    public char last();
 186.133 +
 186.134 +    /**
 186.135 +     * Gets the character at the current position (as returned by getIndex()).
 186.136 +     * @return the character at the current position or DONE if the current
 186.137 +     * position is off the end of the text.
 186.138 +     * @see #getIndex()
 186.139 +     */
 186.140 +    public char current();
 186.141 +
 186.142 +    /**
 186.143 +     * Increments the iterator's index by one and returns the character
 186.144 +     * at the new index.  If the resulting index is greater or equal
 186.145 +     * to getEndIndex(), the current index is reset to getEndIndex() and
 186.146 +     * a value of DONE is returned.
 186.147 +     * @return the character at the new position or DONE if the new
 186.148 +     * position is off the end of the text range.
 186.149 +     */
 186.150 +    public char next();
 186.151 +
 186.152 +    /**
 186.153 +     * Decrements the iterator's index by one and returns the character
 186.154 +     * at the new index. If the current index is getBeginIndex(), the index
 186.155 +     * remains at getBeginIndex() and a value of DONE is returned.
 186.156 +     * @return the character at the new position or DONE if the current
 186.157 +     * position is equal to getBeginIndex().
 186.158 +     */
 186.159 +    public char previous();
 186.160 +
 186.161 +    /**
 186.162 +     * Sets the position to the specified position in the text and returns that
 186.163 +     * character.
 186.164 +     * @param position the position within the text.  Valid values range from
 186.165 +     * getBeginIndex() to getEndIndex().  An IllegalArgumentException is thrown
 186.166 +     * if an invalid value is supplied.
 186.167 +     * @return the character at the specified position or DONE if the specified position is equal to getEndIndex()
 186.168 +     */
 186.169 +    public char setIndex(int position);
 186.170 +
 186.171 +    /**
 186.172 +     * Returns the start index of the text.
 186.173 +     * @return the index at which the text begins.
 186.174 +     */
 186.175 +    public int getBeginIndex();
 186.176 +
 186.177 +    /**
 186.178 +     * Returns the end index of the text.  This index is the index of the first
 186.179 +     * character following the end of the text.
 186.180 +     * @return the index after the last character in the text
 186.181 +     */
 186.182 +    public int getEndIndex();
 186.183 +
 186.184 +    /**
 186.185 +     * Returns the current index.
 186.186 +     * @return the current index.
 186.187 +     */
 186.188 +    public int getIndex();
 186.189 +
 186.190 +    /**
 186.191 +     * Create a copy of this iterator
 186.192 +     * @return A copy of this
 186.193 +     */
 186.194 +    public Object clone();
 186.195 +
 186.196 +}
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/rt/emul/compact/src/main/java/java/text/CharacterIteratorFieldDelegate.java	Wed Apr 30 15:04:10 2014 +0200
   187.3 @@ -0,0 +1,124 @@
   187.4 +/*
   187.5 + * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
   187.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   187.7 + *
   187.8 + * This code is free software; you can redistribute it and/or modify it
   187.9 + * under the terms of the GNU General Public License version 2 only, as
  187.10 + * published by the Free Software Foundation.  Oracle designates this
  187.11 + * particular file as subject to the "Classpath" exception as provided
  187.12 + * by Oracle in the LICENSE file that accompanied this code.
  187.13 + *
  187.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  187.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  187.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  187.17 + * version 2 for more details (a copy is included in the LICENSE file that
  187.18 + * accompanied this code).
  187.19 + *
  187.20 + * You should have received a copy of the GNU General Public License version
  187.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  187.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  187.23 + *
  187.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  187.25 + * or visit www.oracle.com if you need additional information or have any
  187.26 + * questions.
  187.27 + */
  187.28 +package java.text;
  187.29 +
  187.30 +import java.util.ArrayList;
  187.31 +
  187.32 +/**
  187.33 + * CharacterIteratorFieldDelegate combines the notifications from a Format
  187.34 + * into a resulting <code>AttributedCharacterIterator</code>. The resulting
  187.35 + * <code>AttributedCharacterIterator</code> can be retrieved by way of
  187.36 + * the <code>getIterator</code> method.
  187.37 + *
  187.38 + */
  187.39 +class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
  187.40 +    /**
  187.41 +     * Array of AttributeStrings. Whenever <code>formatted</code> is invoked
  187.42 +     * for a region > size, a new instance of AttributedString is added to
  187.43 +     * attributedStrings. Subsequent invocations of <code>formatted</code>
  187.44 +     * for existing regions result in invoking addAttribute on the existing
  187.45 +     * AttributedStrings.
  187.46 +     */
  187.47 +    private ArrayList attributedStrings;
  187.48 +    /**
  187.49 +     * Running count of the number of characters that have
  187.50 +     * been encountered.
  187.51 +     */
  187.52 +    private int size;
  187.53 +
  187.54 +
  187.55 +    CharacterIteratorFieldDelegate() {
  187.56 +        attributedStrings = new ArrayList();
  187.57 +    }
  187.58 +
  187.59 +    public void formatted(Format.Field attr, Object value, int start, int end,
  187.60 +                          StringBuffer buffer) {
  187.61 +        if (start != end) {
  187.62 +            if (start < size) {
  187.63 +                // Adjust attributes of existing runs
  187.64 +                int index = size;
  187.65 +                int asIndex = attributedStrings.size() - 1;
  187.66 +
  187.67 +                while (start < index) {
  187.68 +                    AttributedString as = (AttributedString)attributedStrings.
  187.69 +                                           get(asIndex--);
  187.70 +                    int newIndex = index - as.length();
  187.71 +                    int aStart = Math.max(0, start - newIndex);
  187.72 +
  187.73 +                    as.addAttribute(attr, value, aStart, Math.min(
  187.74 +                                    end - start, as.length() - aStart) +
  187.75 +                                    aStart);
  187.76 +                    index = newIndex;
  187.77 +                }
  187.78 +            }
  187.79 +            if (size < start) {
  187.80 +                // Pad attributes
  187.81 +                attributedStrings.add(new AttributedString(
  187.82 +                                          buffer.substring(size, start)));
  187.83 +                size = start;
  187.84 +            }
  187.85 +            if (size < end) {
  187.86 +                // Add new string
  187.87 +                int aStart = Math.max(start, size);
  187.88 +                AttributedString string = new AttributedString(
  187.89 +                                   buffer.substring(aStart, end));
  187.90 +
  187.91 +                string.addAttribute(attr, value);
  187.92 +                attributedStrings.add(string);
  187.93 +                size = end;
  187.94 +            }
  187.95 +        }
  187.96 +    }
  187.97 +
  187.98 +    public void formatted(int fieldID, Format.Field attr, Object value,
  187.99 +                          int start, int end, StringBuffer buffer) {
 187.100 +        formatted(attr, value, start, end, buffer);
 187.101 +    }
 187.102 +
 187.103 +    /**
 187.104 +     * Returns an <code>AttributedCharacterIterator</code> that can be used
 187.105 +     * to iterate over the resulting formatted String.
 187.106 +     *
 187.107 +     * @pararm string Result of formatting.
 187.108 +     */
 187.109 +    public AttributedCharacterIterator getIterator(String string) {
 187.110 +        // Add the last AttributedCharacterIterator if necessary
 187.111 +        // assert(size <= string.length());
 187.112 +        if (string.length() > size) {
 187.113 +            attributedStrings.add(new AttributedString(
 187.114 +                                  string.substring(size)));
 187.115 +            size = string.length();
 187.116 +        }
 187.117 +        int iCount = attributedStrings.size();
 187.118 +        AttributedCharacterIterator iterators[] = new
 187.119 +                                    AttributedCharacterIterator[iCount];
 187.120 +
 187.121 +        for (int counter = 0; counter < iCount; counter++) {
 187.122 +            iterators[counter] = ((AttributedString)attributedStrings.
 187.123 +                                  get(counter)).getIterator();
 187.124 +        }
 187.125 +        return new AttributedString(iterators).getIterator();
 187.126 +    }
 187.127 +}
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/rt/emul/compact/src/main/java/java/text/ChoiceFormat.java	Wed Apr 30 15:04:10 2014 +0200
   188.3 @@ -0,0 +1,619 @@
   188.4 +/*
   188.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
   188.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   188.7 + *
   188.8 + * This code is free software; you can redistribute it and/or modify it
   188.9 + * under the terms of the GNU General Public License version 2 only, as
  188.10 + * published by the Free Software Foundation.  Oracle designates this
  188.11 + * particular file as subject to the "Classpath" exception as provided
  188.12 + * by Oracle in the LICENSE file that accompanied this code.
  188.13 + *
  188.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  188.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  188.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  188.17 + * version 2 for more details (a copy is included in the LICENSE file that
  188.18 + * accompanied this code).
  188.19 + *
  188.20 + * You should have received a copy of the GNU General Public License version
  188.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  188.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  188.23 + *
  188.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  188.25 + * or visit www.oracle.com if you need additional information or have any
  188.26 + * questions.
  188.27 + */
  188.28 +
  188.29 +/*
  188.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  188.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  188.32 + *
  188.33 + *   The original version of this source code and documentation is copyrighted
  188.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  188.35 + * materials are provided under terms of a License Agreement between Taligent
  188.36 + * and Sun. This technology is protected by multiple US and International
  188.37 + * patents. This notice and attribution to Taligent may not be removed.
  188.38 + *   Taligent is a registered trademark of Taligent, Inc.
  188.39 + *
  188.40 + */
  188.41 +
  188.42 +package java.text;
  188.43 +
  188.44 +import java.io.InvalidObjectException;
  188.45 +import java.io.IOException;
  188.46 +import java.io.ObjectInputStream;
  188.47 +import java.util.Arrays;
  188.48 +
  188.49 +/**
  188.50 + * A <code>ChoiceFormat</code> allows you to attach a format to a range of numbers.
  188.51 + * It is generally used in a <code>MessageFormat</code> for handling plurals.
  188.52 + * The choice is specified with an ascending list of doubles, where each item
  188.53 + * specifies a half-open interval up to the next item:
  188.54 + * <blockquote>
  188.55 + * <pre>
  188.56 + * X matches j if and only if limit[j] &lt;= X &lt; limit[j+1]
  188.57 + * </pre>
  188.58 + * </blockquote>
  188.59 + * If there is no match, then either the first or last index is used, depending
  188.60 + * on whether the number (X) is too low or too high.  If the limit array is not
  188.61 + * in ascending order, the results of formatting will be incorrect.  ChoiceFormat
  188.62 + * also accepts <code>&#92;u221E</code> as equivalent to infinity(INF).
  188.63 + *
  188.64 + * <p>
  188.65 + * <strong>Note:</strong>
  188.66 + * <code>ChoiceFormat</code> differs from the other <code>Format</code>
  188.67 + * classes in that you create a <code>ChoiceFormat</code> object with a
  188.68 + * constructor (not with a <code>getInstance</code> style factory
  188.69 + * method). The factory methods aren't necessary because <code>ChoiceFormat</code>
  188.70 + * doesn't require any complex setup for a given locale. In fact,
  188.71 + * <code>ChoiceFormat</code> doesn't implement any locale specific behavior.
  188.72 + *
  188.73 + * <p>
  188.74 + * When creating a <code>ChoiceFormat</code>, you must specify an array of formats
  188.75 + * and an array of limits. The length of these arrays must be the same.
  188.76 + * For example,
  188.77 + * <ul>
  188.78 + * <li>
  188.79 + *     <em>limits</em> = {1,2,3,4,5,6,7}<br>
  188.80 + *     <em>formats</em> = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}
  188.81 + * <li>
  188.82 + *     <em>limits</em> = {0, 1, ChoiceFormat.nextDouble(1)}<br>
  188.83 + *     <em>formats</em> = {"no files", "one file", "many files"}<br>
  188.84 + *     (<code>nextDouble</code> can be used to get the next higher double, to
  188.85 + *     make the half-open interval.)
  188.86 + * </ul>
  188.87 + *
  188.88 + * <p>
  188.89 + * Here is a simple example that shows formatting and parsing:
  188.90 + * <blockquote>
  188.91 + * <pre>
  188.92 + * double[] limits = {1,2,3,4,5,6,7};
  188.93 + * String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
  188.94 + * ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
  188.95 + * ParsePosition status = new ParsePosition(0);
  188.96 + * for (double i = 0.0; i &lt;= 8.0; ++i) {
  188.97 + *     status.setIndex(0);
  188.98 + *     System.out.println(i + " -&gt; " + form.format(i) + " -&gt; "
  188.99 + *                              + form.parse(form.format(i),status));
 188.100 + * }
 188.101 + * </pre>
 188.102 + * </blockquote>
 188.103 + * Here is a more complex example, with a pattern format:
 188.104 + * <blockquote>
 188.105 + * <pre>
 188.106 + * double[] filelimits = {0,1,2};
 188.107 + * String[] filepart = {"are no files","is one file","are {2} files"};
 188.108 + * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
 188.109 + * Format[] testFormats = {fileform, null, NumberFormat.getInstance()};
 188.110 + * MessageFormat pattform = new MessageFormat("There {0} on {1}");
 188.111 + * pattform.setFormats(testFormats);
 188.112 + * Object[] testArgs = {null, "ADisk", null};
 188.113 + * for (int i = 0; i &lt; 4; ++i) {
 188.114 + *     testArgs[0] = new Integer(i);
 188.115 + *     testArgs[2] = testArgs[0];
 188.116 + *     System.out.println(pattform.format(testArgs));
 188.117 + * }
 188.118 + * </pre>
 188.119 + * </blockquote>
 188.120 + * <p>
 188.121 + * Specifying a pattern for ChoiceFormat objects is fairly straightforward.
 188.122 + * For example:
 188.123 + * <blockquote>
 188.124 + * <pre>
 188.125 + * ChoiceFormat fmt = new ChoiceFormat(
 188.126 + *      "-1#is negative| 0#is zero or fraction | 1#is one |1.0&lt;is 1+ |2#is two |2&lt;is more than 2.");
 188.127 + * System.out.println("Formatter Pattern : " + fmt.toPattern());
 188.128 + *
 188.129 + * System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
 188.130 + * System.out.println("Format with -1.0 : " + fmt.format(-1.0));
 188.131 + * System.out.println("Format with 0 : " + fmt.format(0));
 188.132 + * System.out.println("Format with 0.9 : " + fmt.format(0.9));
 188.133 + * System.out.println("Format with 1.0 : " + fmt.format(1));
 188.134 + * System.out.println("Format with 1.5 : " + fmt.format(1.5));
 188.135 + * System.out.println("Format with 2 : " + fmt.format(2));
 188.136 + * System.out.println("Format with 2.1 : " + fmt.format(2.1));
 188.137 + * System.out.println("Format with NaN : " + fmt.format(Double.NaN));
 188.138 + * System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
 188.139 + * </pre>
 188.140 + * </blockquote>
 188.141 + * And the output result would be like the following:
 188.142 + * <blockquote>
 188.143 + * <pre>
 188.144 + *   Format with -INF : is negative
 188.145 + *   Format with -1.0 : is negative
 188.146 + *   Format with 0 : is zero or fraction
 188.147 + *   Format with 0.9 : is zero or fraction
 188.148 + *   Format with 1.0 : is one
 188.149 + *   Format with 1.5 : is 1+
 188.150 + *   Format with 2 : is two
 188.151 + *   Format with 2.1 : is more than 2.
 188.152 + *   Format with NaN : is negative
 188.153 + *   Format with +INF : is more than 2.
 188.154 + * </pre>
 188.155 + * </blockquote>
 188.156 + *
 188.157 + * <h4><a name="synchronization">Synchronization</a></h4>
 188.158 + *
 188.159 + * <p>
 188.160 + * Choice formats are not synchronized.
 188.161 + * It is recommended to create separate format instances for each thread.
 188.162 + * If multiple threads access a format concurrently, it must be synchronized
 188.163 + * externally.
 188.164 + *
 188.165 + *
 188.166 + * @see          DecimalFormat
 188.167 + * @see          MessageFormat
 188.168 + * @author       Mark Davis
 188.169 + */
 188.170 +public class ChoiceFormat extends NumberFormat {
 188.171 +
 188.172 +    // Proclaim serial compatibility with 1.1 FCS
 188.173 +    private static final long serialVersionUID = 1795184449645032964L;
 188.174 +
 188.175 +    /**
 188.176 +     * Sets the pattern.
 188.177 +     * @param newPattern See the class description.
 188.178 +     */
 188.179 +    public void applyPattern(String newPattern) {
 188.180 +        StringBuffer[] segments = new StringBuffer[2];
 188.181 +        for (int i = 0; i < segments.length; ++i) {
 188.182 +            segments[i] = new StringBuffer();
 188.183 +        }
 188.184 +        double[] newChoiceLimits = new double[30];
 188.185 +        String[] newChoiceFormats = new String[30];
 188.186 +        int count = 0;
 188.187 +        int part = 0;
 188.188 +        double startValue = 0;
 188.189 +        double oldStartValue = Double.NaN;
 188.190 +        boolean inQuote = false;
 188.191 +        for (int i = 0; i < newPattern.length(); ++i) {
 188.192 +            char ch = newPattern.charAt(i);
 188.193 +            if (ch=='\'') {
 188.194 +                // Check for "''" indicating a literal quote
 188.195 +                if ((i+1)<newPattern.length() && newPattern.charAt(i+1)==ch) {
 188.196 +                    segments[part].append(ch);
 188.197 +                    ++i;
 188.198 +                } else {
 188.199 +                    inQuote = !inQuote;
 188.200 +                }
 188.201 +            } else if (inQuote) {
 188.202 +                segments[part].append(ch);
 188.203 +            } else if (ch == '<' || ch == '#' || ch == '\u2264') {
 188.204 +                if (segments[0].length() == 0) {
 188.205 +                    throw new IllegalArgumentException();
 188.206 +                }
 188.207 +                try {
 188.208 +                    String tempBuffer = segments[0].toString();
 188.209 +                    if (tempBuffer.equals("\u221E")) {
 188.210 +                        startValue = Double.POSITIVE_INFINITY;
 188.211 +                    } else if (tempBuffer.equals("-\u221E")) {
 188.212 +                        startValue = Double.NEGATIVE_INFINITY;
 188.213 +                    } else {
 188.214 +                        startValue = Double.valueOf(segments[0].toString()).doubleValue();
 188.215 +                    }
 188.216 +                } catch (Exception e) {
 188.217 +                    throw new IllegalArgumentException();
 188.218 +                }
 188.219 +                if (ch == '<' && startValue != Double.POSITIVE_INFINITY &&
 188.220 +                        startValue != Double.NEGATIVE_INFINITY) {
 188.221 +                    startValue = nextDouble(startValue);
 188.222 +                }
 188.223 +                if (startValue <= oldStartValue) {
 188.224 +                    throw new IllegalArgumentException();
 188.225 +                }
 188.226 +                segments[0].setLength(0);
 188.227 +                part = 1;
 188.228 +            } else if (ch == '|') {
 188.229 +                if (count == newChoiceLimits.length) {
 188.230 +                    newChoiceLimits = doubleArraySize(newChoiceLimits);
 188.231 +                    newChoiceFormats = doubleArraySize(newChoiceFormats);
 188.232 +                }
 188.233 +                newChoiceLimits[count] = startValue;
 188.234 +                newChoiceFormats[count] = segments[1].toString();
 188.235 +                ++count;
 188.236 +                oldStartValue = startValue;
 188.237 +                segments[1].setLength(0);
 188.238 +                part = 0;
 188.239 +            } else {
 188.240 +                segments[part].append(ch);
 188.241 +            }
 188.242 +        }
 188.243 +        // clean up last one
 188.244 +        if (part == 1) {
 188.245 +            if (count == newChoiceLimits.length) {
 188.246 +                newChoiceLimits = doubleArraySize(newChoiceLimits);
 188.247 +                newChoiceFormats = doubleArraySize(newChoiceFormats);
 188.248 +            }
 188.249 +            newChoiceLimits[count] = startValue;
 188.250 +            newChoiceFormats[count] = segments[1].toString();
 188.251 +            ++count;
 188.252 +        }
 188.253 +        choiceLimits = new double[count];
 188.254 +        System.arraycopy(newChoiceLimits, 0, choiceLimits, 0, count);
 188.255 +        choiceFormats = new String[count];
 188.256 +        System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count);
 188.257 +    }
 188.258 +
 188.259 +    /**
 188.260 +     * Gets the pattern.
 188.261 +     */
 188.262 +    public String toPattern() {
 188.263 +        StringBuffer result = new StringBuffer();
 188.264 +        for (int i = 0; i < choiceLimits.length; ++i) {
 188.265 +            if (i != 0) {
 188.266 +                result.append('|');
 188.267 +            }
 188.268 +            // choose based upon which has less precision
 188.269 +            // approximate that by choosing the closest one to an integer.
 188.270 +            // could do better, but it's not worth it.
 188.271 +            double less = previousDouble(choiceLimits[i]);
 188.272 +            double tryLessOrEqual = Math.abs(Math.IEEEremainder(choiceLimits[i], 1.0d));
 188.273 +            double tryLess = Math.abs(Math.IEEEremainder(less, 1.0d));
 188.274 +
 188.275 +            if (tryLessOrEqual < tryLess) {
 188.276 +                result.append(""+choiceLimits[i]);
 188.277 +                result.append('#');
 188.278 +            } else {
 188.279 +                if (choiceLimits[i] == Double.POSITIVE_INFINITY) {
 188.280 +                    result.append("\u221E");
 188.281 +                } else if (choiceLimits[i] == Double.NEGATIVE_INFINITY) {
 188.282 +                    result.append("-\u221E");
 188.283 +                } else {
 188.284 +                    result.append(""+less);
 188.285 +                }
 188.286 +                result.append('<');
 188.287 +            }
 188.288 +            // Append choiceFormats[i], using quotes if there are special characters.
 188.289 +            // Single quotes themselves must be escaped in either case.
 188.290 +            String text = choiceFormats[i];
 188.291 +            boolean needQuote = text.indexOf('<') >= 0
 188.292 +                || text.indexOf('#') >= 0
 188.293 +                || text.indexOf('\u2264') >= 0
 188.294 +                || text.indexOf('|') >= 0;
 188.295 +            if (needQuote) result.append('\'');
 188.296 +            if (text.indexOf('\'') < 0) result.append(text);
 188.297 +            else {
 188.298 +                for (int j=0; j<text.length(); ++j) {
 188.299 +                    char c = text.charAt(j);
 188.300 +                    result.append(c);
 188.301 +                    if (c == '\'') result.append(c);
 188.302 +                }
 188.303 +            }
 188.304 +            if (needQuote) result.append('\'');
 188.305 +        }
 188.306 +        return result.toString();
 188.307 +    }
 188.308 +
 188.309 +    /**
 188.310 +     * Constructs with limits and corresponding formats based on the pattern.
 188.311 +     * @see #applyPattern
 188.312 +     */
 188.313 +    public ChoiceFormat(String newPattern)  {
 188.314 +        applyPattern(newPattern);
 188.315 +    }
 188.316 +
 188.317 +    /**
 188.318 +     * Constructs with the limits and the corresponding formats.
 188.319 +     * @see #setChoices
 188.320 +     */
 188.321 +    public ChoiceFormat(double[] limits, String[] formats) {
 188.322 +        setChoices(limits, formats);
 188.323 +    }
 188.324 +
 188.325 +    /**
 188.326 +     * Set the choices to be used in formatting.
 188.327 +     * @param limits contains the top value that you want
 188.328 +     * parsed with that format,and should be in ascending sorted order. When
 188.329 +     * formatting X, the choice will be the i, where
 188.330 +     * limit[i] &lt;= X &lt; limit[i+1].
 188.331 +     * If the limit array is not in ascending order, the results of formatting
 188.332 +     * will be incorrect.
 188.333 +     * @param formats are the formats you want to use for each limit.
 188.334 +     * They can be either Format objects or Strings.
 188.335 +     * When formatting with object Y,
 188.336 +     * if the object is a NumberFormat, then ((NumberFormat) Y).format(X)
 188.337 +     * is called. Otherwise Y.toString() is called.
 188.338 +     */
 188.339 +    public void setChoices(double[] limits, String formats[]) {
 188.340 +        if (limits.length != formats.length) {
 188.341 +            throw new IllegalArgumentException(
 188.342 +                "Array and limit arrays must be of the same length.");
 188.343 +        }
 188.344 +        choiceLimits = limits;
 188.345 +        choiceFormats = formats;
 188.346 +    }
 188.347 +
 188.348 +    /**
 188.349 +     * Get the limits passed in the constructor.
 188.350 +     * @return the limits.
 188.351 +     */
 188.352 +    public double[] getLimits() {
 188.353 +        return choiceLimits;
 188.354 +    }
 188.355 +
 188.356 +    /**
 188.357 +     * Get the formats passed in the constructor.
 188.358 +     * @return the formats.
 188.359 +     */
 188.360 +    public Object[] getFormats() {
 188.361 +        return choiceFormats;
 188.362 +    }
 188.363 +
 188.364 +    // Overrides
 188.365 +
 188.366 +    /**
 188.367 +     * Specialization of format. This method really calls
 188.368 +     * <code>format(double, StringBuffer, FieldPosition)</code>
 188.369 +     * thus the range of longs that are supported is only equal to
 188.370 +     * the range that can be stored by double. This will never be
 188.371 +     * a practical limitation.
 188.372 +     */
 188.373 +    public StringBuffer format(long number, StringBuffer toAppendTo,
 188.374 +                               FieldPosition status) {
 188.375 +        return format((double)number, toAppendTo, status);
 188.376 +    }
 188.377 +
 188.378 +    /**
 188.379 +     * Returns pattern with formatted double.
 188.380 +     * @param number number to be formatted & substituted.
 188.381 +     * @param toAppendTo where text is appended.
 188.382 +     * @param status ignore no useful status is returned.
 188.383 +     */
 188.384 +   public StringBuffer format(double number, StringBuffer toAppendTo,
 188.385 +                               FieldPosition status) {
 188.386 +        // find the number
 188.387 +        int i;
 188.388 +        for (i = 0; i < choiceLimits.length; ++i) {
 188.389 +            if (!(number >= choiceLimits[i])) {
 188.390 +                // same as number < choiceLimits, except catchs NaN
 188.391 +                break;
 188.392 +            }
 188.393 +        }
 188.394 +        --i;
 188.395 +        if (i < 0) i = 0;
 188.396 +        // return either a formatted number, or a string
 188.397 +        return toAppendTo.append(choiceFormats[i]);
 188.398 +    }
 188.399 +
 188.400 +    /**
 188.401 +     * Parses a Number from the input text.
 188.402 +     * @param text the source text.
 188.403 +     * @param status an input-output parameter.  On input, the
 188.404 +     * status.index field indicates the first character of the
 188.405 +     * source text that should be parsed.  On exit, if no error
 188.406 +     * occured, status.index is set to the first unparsed character
 188.407 +     * in the source text.  On exit, if an error did occur,
 188.408 +     * status.index is unchanged and status.errorIndex is set to the
 188.409 +     * first index of the character that caused the parse to fail.
 188.410 +     * @return A Number representing the value of the number parsed.
 188.411 +     */
 188.412 +    public Number parse(String text, ParsePosition status) {
 188.413 +        // find the best number (defined as the one with the longest parse)
 188.414 +        int start = status.index;
 188.415 +        int furthest = start;
 188.416 +        double bestNumber = Double.NaN;
 188.417 +        double tempNumber = 0.0;
 188.418 +        for (int i = 0; i < choiceFormats.length; ++i) {
 188.419 +            String tempString = choiceFormats[i];
 188.420 +            if (text.regionMatches(start, tempString, 0, tempString.length())) {
 188.421 +                status.index = start + tempString.length();
 188.422 +                tempNumber = choiceLimits[i];
 188.423 +                if (status.index > furthest) {
 188.424 +                    furthest = status.index;
 188.425 +                    bestNumber = tempNumber;
 188.426 +                    if (furthest == text.length()) break;
 188.427 +                }
 188.428 +            }
 188.429 +        }
 188.430 +        status.index = furthest;
 188.431 +        if (status.index == start) {
 188.432 +            status.errorIndex = furthest;
 188.433 +        }
 188.434 +        return new Double(bestNumber);
 188.435 +    }
 188.436 +
 188.437 +    /**
 188.438 +     * Finds the least double greater than d.
 188.439 +     * If NaN, returns same value.
 188.440 +     * <p>Used to make half-open intervals.
 188.441 +     * @see #previousDouble
 188.442 +     */
 188.443 +    public static final double nextDouble (double d) {
 188.444 +        return nextDouble(d,true);
 188.445 +    }
 188.446 +
 188.447 +    /**
 188.448 +     * Finds the greatest double less than d.
 188.449 +     * If NaN, returns same value.
 188.450 +     * @see #nextDouble
 188.451 +     */
 188.452 +    public static final double previousDouble (double d) {
 188.453 +        return nextDouble(d,false);
 188.454 +    }
 188.455 +
 188.456 +    /**
 188.457 +     * Overrides Cloneable
 188.458 +     */
 188.459 +    public Object clone()
 188.460 +    {
 188.461 +        ChoiceFormat other = (ChoiceFormat) super.clone();
 188.462 +        // for primitives or immutables, shallow clone is enough
 188.463 +        other.choiceLimits = (double[]) choiceLimits.clone();
 188.464 +        other.choiceFormats = (String[]) choiceFormats.clone();
 188.465 +        return other;
 188.466 +    }
 188.467 +
 188.468 +    /**
 188.469 +     * Generates a hash code for the message format object.
 188.470 +     */
 188.471 +    public int hashCode() {
 188.472 +        int result = choiceLimits.length;
 188.473 +        if (choiceFormats.length > 0) {
 188.474 +            // enough for reasonable distribution
 188.475 +            result ^= choiceFormats[choiceFormats.length-1].hashCode();
 188.476 +        }
 188.477 +        return result;
 188.478 +    }
 188.479 +
 188.480 +    /**
 188.481 +     * Equality comparision between two
 188.482 +     */
 188.483 +    public boolean equals(Object obj) {
 188.484 +        if (obj == null) return false;
 188.485 +        if (this == obj)                      // quick check
 188.486 +            return true;
 188.487 +        if (getClass() != obj.getClass())
 188.488 +            return false;
 188.489 +        ChoiceFormat other = (ChoiceFormat) obj;
 188.490 +        return (Arrays.equals(choiceLimits, other.choiceLimits)
 188.491 +             && Arrays.equals(choiceFormats, other.choiceFormats));
 188.492 +    }
 188.493 +
 188.494 +    /**
 188.495 +     * After reading an object from the input stream, do a simple verification
 188.496 +     * to maintain class invariants.
 188.497 +     * @throws InvalidObjectException if the objects read from the stream is invalid.
 188.498 +     */
 188.499 +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
 188.500 +        in.defaultReadObject();
 188.501 +        if (choiceLimits.length != choiceFormats.length) {
 188.502 +            throw new InvalidObjectException(
 188.503 +                    "limits and format arrays of different length.");
 188.504 +        }
 188.505 +    }
 188.506 +
 188.507 +    // ===============privates===========================
 188.508 +
 188.509 +    /**
 188.510 +     * A list of lower bounds for the choices.  The formatter will return
 188.511 +     * <code>choiceFormats[i]</code> if the number being formatted is greater than or equal to
 188.512 +     * <code>choiceLimits[i]</code> and less than <code>choiceLimits[i+1]</code>.
 188.513 +     * @serial
 188.514 +     */
 188.515 +    private double[] choiceLimits;
 188.516 +
 188.517 +    /**
 188.518 +     * A list of choice strings.  The formatter will return
 188.519 +     * <code>choiceFormats[i]</code> if the number being formatted is greater than or equal to
 188.520 +     * <code>choiceLimits[i]</code> and less than <code>choiceLimits[i+1]</code>.
 188.521 +     * @serial
 188.522 +     */
 188.523 +    private String[] choiceFormats;
 188.524 +
 188.525 +    /*
 188.526 +    static final long SIGN          = 0x8000000000000000L;
 188.527 +    static final long EXPONENT      = 0x7FF0000000000000L;
 188.528 +    static final long SIGNIFICAND   = 0x000FFFFFFFFFFFFFL;
 188.529 +
 188.530 +    private static double nextDouble (double d, boolean positive) {
 188.531 +        if (Double.isNaN(d) || Double.isInfinite(d)) {
 188.532 +                return d;
 188.533 +            }
 188.534 +        long bits = Double.doubleToLongBits(d);
 188.535 +        long significand = bits & SIGNIFICAND;
 188.536 +        if (bits < 0) {
 188.537 +            significand |= (SIGN | EXPONENT);
 188.538 +        }
 188.539 +        long exponent = bits & EXPONENT;
 188.540 +        if (positive) {
 188.541 +            significand += 1;
 188.542 +            // FIXME fix overflow & underflow
 188.543 +        } else {
 188.544 +            significand -= 1;
 188.545 +            // FIXME fix overflow & underflow
 188.546 +        }
 188.547 +        bits = exponent | (significand & ~EXPONENT);
 188.548 +        return Double.longBitsToDouble(bits);
 188.549 +    }
 188.550 +    */
 188.551 +
 188.552 +    static final long SIGN                = 0x8000000000000000L;
 188.553 +    static final long EXPONENT            = 0x7FF0000000000000L;
 188.554 +    static final long POSITIVEINFINITY    = 0x7FF0000000000000L;
 188.555 +
 188.556 +    /**
 188.557 +     * Finds the least double greater than d (if positive == true),
 188.558 +     * or the greatest double less than d (if positive == false).
 188.559 +     * If NaN, returns same value.
 188.560 +     *
 188.561 +     * Does not affect floating-point flags,
 188.562 +     * provided these member functions do not:
 188.563 +     *          Double.longBitsToDouble(long)
 188.564 +     *          Double.doubleToLongBits(double)
 188.565 +     *          Double.isNaN(double)
 188.566 +     */
 188.567 +    public static double nextDouble (double d, boolean positive) {
 188.568 +
 188.569 +        /* filter out NaN's */
 188.570 +        if (Double.isNaN(d)) {
 188.571 +            return d;
 188.572 +        }
 188.573 +
 188.574 +        /* zero's are also a special case */
 188.575 +        if (d == 0.0) {
 188.576 +            double smallestPositiveDouble = Double.longBitsToDouble(1L);
 188.577 +            if (positive) {
 188.578 +                return smallestPositiveDouble;
 188.579 +            } else {
 188.580 +                return -smallestPositiveDouble;
 188.581 +            }
 188.582 +        }
 188.583 +
 188.584 +        /* if entering here, d is a nonzero value */
 188.585 +
 188.586 +        /* hold all bits in a long for later use */
 188.587 +        long bits = Double.doubleToLongBits(d);
 188.588 +
 188.589 +        /* strip off the sign bit */
 188.590 +        long magnitude = bits & ~SIGN;
 188.591 +
 188.592 +        /* if next double away from zero, increase magnitude */
 188.593 +        if ((bits > 0) == positive) {
 188.594 +            if (magnitude != POSITIVEINFINITY) {
 188.595 +                magnitude += 1;
 188.596 +            }
 188.597 +        }
 188.598 +        /* else decrease magnitude */
 188.599 +        else {
 188.600 +            magnitude -= 1;
 188.601 +        }
 188.602 +
 188.603 +        /* restore sign bit and return */
 188.604 +        long signbit = bits & SIGN;
 188.605 +        return Double.longBitsToDouble (magnitude | signbit);
 188.606 +    }
 188.607 +
 188.608 +    private static double[] doubleArraySize(double[] array) {
 188.609 +        int oldSize = array.length;
 188.610 +        double[] newArray = new double[oldSize * 2];
 188.611 +        System.arraycopy(array, 0, newArray, 0, oldSize);
 188.612 +        return newArray;
 188.613 +    }
 188.614 +
 188.615 +    private String[] doubleArraySize(String[] array) {
 188.616 +        int oldSize = array.length;
 188.617 +        String[] newArray = new String[oldSize * 2];
 188.618 +        System.arraycopy(array, 0, newArray, 0, oldSize);
 188.619 +        return newArray;
 188.620 +    }
 188.621 +
 188.622 +}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/rt/emul/compact/src/main/java/java/text/DateFormat.java	Wed Apr 30 15:04:10 2014 +0200
   189.3 @@ -0,0 +1,1025 @@
   189.4 +/*
   189.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   189.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   189.7 + *
   189.8 + * This code is free software; you can redistribute it and/or modify it
   189.9 + * under the terms of the GNU General Public License version 2 only, as
  189.10 + * published by the Free Software Foundation.  Oracle designates this
  189.11 + * particular file as subject to the "Classpath" exception as provided
  189.12 + * by Oracle in the LICENSE file that accompanied this code.
  189.13 + *
  189.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  189.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  189.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  189.17 + * version 2 for more details (a copy is included in the LICENSE file that
  189.18 + * accompanied this code).
  189.19 + *
  189.20 + * You should have received a copy of the GNU General Public License version
  189.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  189.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  189.23 + *
  189.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  189.25 + * or visit www.oracle.com if you need additional information or have any
  189.26 + * questions.
  189.27 + */
  189.28 +
  189.29 +/*
  189.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  189.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  189.32 + *
  189.33 + *   The original version of this source code and documentation is copyrighted
  189.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  189.35 + * materials are provided under terms of a License Agreement between Taligent
  189.36 + * and Sun. This technology is protected by multiple US and International
  189.37 + * patents. This notice and attribution to Taligent may not be removed.
  189.38 + *   Taligent is a registered trademark of Taligent, Inc.
  189.39 + *
  189.40 + */
  189.41 +
  189.42 +package java.text;
  189.43 +
  189.44 +import java.io.InvalidObjectException;
  189.45 +import java.util.Calendar;
  189.46 +import java.util.Date;
  189.47 +import java.util.HashMap;
  189.48 +import java.util.Locale;
  189.49 +import java.util.Map;
  189.50 +import java.util.MissingResourceException;
  189.51 +import java.util.TimeZone;
  189.52 +
  189.53 +/**
  189.54 + * {@code DateFormat} is an abstract class for date/time formatting subclasses which
  189.55 + * formats and parses dates or time in a language-independent manner.
  189.56 + * The date/time formatting subclass, such as {@link SimpleDateFormat}, allows for
  189.57 + * formatting (i.e., date -> text), parsing (text -> date), and
  189.58 + * normalization.  The date is represented as a <code>Date</code> object or
  189.59 + * as the milliseconds since January 1, 1970, 00:00:00 GMT.
  189.60 + *
  189.61 + * <p>{@code DateFormat} provides many class methods for obtaining default date/time
  189.62 + * formatters based on the default or a given locale and a number of formatting
  189.63 + * styles. The formatting styles include {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, and {@link #SHORT}. More
  189.64 + * detail and examples of using these styles are provided in the method
  189.65 + * descriptions.
  189.66 + *
  189.67 + * <p>{@code DateFormat} helps you to format and parse dates for any locale.
  189.68 + * Your code can be completely independent of the locale conventions for
  189.69 + * months, days of the week, or even the calendar format: lunar vs. solar.
  189.70 + *
  189.71 + * <p>To format a date for the current Locale, use one of the
  189.72 + * static factory methods:
  189.73 + * <pre>
  189.74 + *  myString = DateFormat.getDateInstance().format(myDate);
  189.75 + * </pre>
  189.76 + * <p>If you are formatting multiple dates, it is
  189.77 + * more efficient to get the format and use it multiple times so that
  189.78 + * the system doesn't have to fetch the information about the local
  189.79 + * language and country conventions multiple times.
  189.80 + * <pre>
  189.81 + *  DateFormat df = DateFormat.getDateInstance();
  189.82 + *  for (int i = 0; i < myDate.length; ++i) {
  189.83 + *    output.println(df.format(myDate[i]) + "; ");
  189.84 + *  }
  189.85 + * </pre>
  189.86 + * <p>To format a date for a different Locale, specify it in the
  189.87 + * call to {@link #getDateInstance(int, Locale) getDateInstance()}.
  189.88 + * <pre>
  189.89 + *  DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
  189.90 + * </pre>
  189.91 + * <p>You can use a DateFormat to parse also.
  189.92 + * <pre>
  189.93 + *  myDate = df.parse(myString);
  189.94 + * </pre>
  189.95 + * <p>Use {@code getDateInstance} to get the normal date format for that country.
  189.96 + * There are other static factory methods available.
  189.97 + * Use {@code getTimeInstance} to get the time format for that country.
  189.98 + * Use {@code getDateTimeInstance} to get a date and time format. You can pass in
  189.99 + * different options to these factory methods to control the length of the
 189.100 + * result; from {@link #SHORT} to {@link #MEDIUM} to {@link #LONG} to {@link #FULL}. The exact result depends
 189.101 + * on the locale, but generally:
 189.102 + * <ul><li>{@link #SHORT} is completely numeric, such as {@code 12.13.52} or {@code 3:30pm}
 189.103 + * <li>{@link #MEDIUM} is longer, such as {@code Jan 12, 1952}
 189.104 + * <li>{@link #LONG} is longer, such as {@code January 12, 1952} or {@code 3:30:32pm}
 189.105 + * <li>{@link #FULL} is pretty completely specified, such as
 189.106 + * {@code Tuesday, April 12, 1952 AD or 3:30:42pm PST}.
 189.107 + * </ul>
 189.108 + *
 189.109 + * <p>You can also set the time zone on the format if you wish.
 189.110 + * If you want even more control over the format or parsing,
 189.111 + * (or want to give your users more control),
 189.112 + * you can try casting the {@code DateFormat} you get from the factory methods
 189.113 + * to a {@link SimpleDateFormat}. This will work for the majority
 189.114 + * of countries; just remember to put it in a {@code try} block in case you
 189.115 + * encounter an unusual one.
 189.116 + *
 189.117 + * <p>You can also use forms of the parse and format methods with
 189.118 + * {@link ParsePosition} and {@link FieldPosition} to
 189.119 + * allow you to
 189.120 + * <ul><li>progressively parse through pieces of a string.
 189.121 + * <li>align any particular field, or find out where it is for selection
 189.122 + * on the screen.
 189.123 + * </ul>
 189.124 + *
 189.125 + * <h4><a name="synchronization">Synchronization</a></h4>
 189.126 + *
 189.127 + * <p>
 189.128 + * Date formats are not synchronized.
 189.129 + * It is recommended to create separate format instances for each thread.
 189.130 + * If multiple threads access a format concurrently, it must be synchronized
 189.131 + * externally.
 189.132 + *
 189.133 + * @see          Format
 189.134 + * @see          NumberFormat
 189.135 + * @see          SimpleDateFormat
 189.136 + * @see          java.util.Calendar
 189.137 + * @see          java.util.GregorianCalendar
 189.138 + * @see          java.util.TimeZone
 189.139 + * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
 189.140 + */
 189.141 +public abstract class DateFormat extends Format {
 189.142 +
 189.143 +    /**
 189.144 +     * The {@link Calendar} instance used for calculating the date-time fields
 189.145 +     * and the instant of time. This field is used for both formatting and
 189.146 +     * parsing.
 189.147 +     *
 189.148 +     * <p>Subclasses should initialize this field to a {@link Calendar}
 189.149 +     * appropriate for the {@link Locale} associated with this
 189.150 +     * <code>DateFormat</code>.
 189.151 +     * @serial
 189.152 +     */
 189.153 +    protected Calendar calendar;
 189.154 +
 189.155 +    /**
 189.156 +     * The number formatter that <code>DateFormat</code> uses to format numbers
 189.157 +     * in dates and times.  Subclasses should initialize this to a number format
 189.158 +     * appropriate for the locale associated with this <code>DateFormat</code>.
 189.159 +     * @serial
 189.160 +     */
 189.161 +    protected NumberFormat numberFormat;
 189.162 +
 189.163 +    /**
 189.164 +     * Useful constant for ERA field alignment.
 189.165 +     * Used in FieldPosition of date/time formatting.
 189.166 +     */
 189.167 +    public final static int ERA_FIELD = 0;
 189.168 +    /**
 189.169 +     * Useful constant for YEAR field alignment.
 189.170 +     * Used in FieldPosition of date/time formatting.
 189.171 +     */
 189.172 +    public final static int YEAR_FIELD = 1;
 189.173 +    /**
 189.174 +     * Useful constant for MONTH field alignment.
 189.175 +     * Used in FieldPosition of date/time formatting.
 189.176 +     */
 189.177 +    public final static int MONTH_FIELD = 2;
 189.178 +    /**
 189.179 +     * Useful constant for DATE field alignment.
 189.180 +     * Used in FieldPosition of date/time formatting.
 189.181 +     */
 189.182 +    public final static int DATE_FIELD = 3;
 189.183 +    /**
 189.184 +     * Useful constant for one-based HOUR_OF_DAY field alignment.
 189.185 +     * Used in FieldPosition of date/time formatting.
 189.186 +     * HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
 189.187 +     * For example, 23:59 + 01:00 results in 24:59.
 189.188 +     */
 189.189 +    public final static int HOUR_OF_DAY1_FIELD = 4;
 189.190 +    /**
 189.191 +     * Useful constant for zero-based HOUR_OF_DAY field alignment.
 189.192 +     * Used in FieldPosition of date/time formatting.
 189.193 +     * HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
 189.194 +     * For example, 23:59 + 01:00 results in 00:59.
 189.195 +     */
 189.196 +    public final static int HOUR_OF_DAY0_FIELD = 5;
 189.197 +    /**
 189.198 +     * Useful constant for MINUTE field alignment.
 189.199 +     * Used in FieldPosition of date/time formatting.
 189.200 +     */
 189.201 +    public final static int MINUTE_FIELD = 6;
 189.202 +    /**
 189.203 +     * Useful constant for SECOND field alignment.
 189.204 +     * Used in FieldPosition of date/time formatting.
 189.205 +     */
 189.206 +    public final static int SECOND_FIELD = 7;
 189.207 +    /**
 189.208 +     * Useful constant for MILLISECOND field alignment.
 189.209 +     * Used in FieldPosition of date/time formatting.
 189.210 +     */
 189.211 +    public final static int MILLISECOND_FIELD = 8;
 189.212 +    /**
 189.213 +     * Useful constant for DAY_OF_WEEK field alignment.
 189.214 +     * Used in FieldPosition of date/time formatting.
 189.215 +     */
 189.216 +    public final static int DAY_OF_WEEK_FIELD = 9;
 189.217 +    /**
 189.218 +     * Useful constant for DAY_OF_YEAR field alignment.
 189.219 +     * Used in FieldPosition of date/time formatting.
 189.220 +     */
 189.221 +    public final static int DAY_OF_YEAR_FIELD = 10;
 189.222 +    /**
 189.223 +     * Useful constant for DAY_OF_WEEK_IN_MONTH field alignment.
 189.224 +     * Used in FieldPosition of date/time formatting.
 189.225 +     */
 189.226 +    public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
 189.227 +    /**
 189.228 +     * Useful constant for WEEK_OF_YEAR field alignment.
 189.229 +     * Used in FieldPosition of date/time formatting.
 189.230 +     */
 189.231 +    public final static int WEEK_OF_YEAR_FIELD = 12;
 189.232 +    /**
 189.233 +     * Useful constant for WEEK_OF_MONTH field alignment.
 189.234 +     * Used in FieldPosition of date/time formatting.
 189.235 +     */
 189.236 +    public final static int WEEK_OF_MONTH_FIELD = 13;
 189.237 +    /**
 189.238 +     * Useful constant for AM_PM field alignment.
 189.239 +     * Used in FieldPosition of date/time formatting.
 189.240 +     */
 189.241 +    public final static int AM_PM_FIELD = 14;
 189.242 +    /**
 189.243 +     * Useful constant for one-based HOUR field alignment.
 189.244 +     * Used in FieldPosition of date/time formatting.
 189.245 +     * HOUR1_FIELD is used for the one-based 12-hour clock.
 189.246 +     * For example, 11:30 PM + 1 hour results in 12:30 AM.
 189.247 +     */
 189.248 +    public final static int HOUR1_FIELD = 15;
 189.249 +    /**
 189.250 +     * Useful constant for zero-based HOUR field alignment.
 189.251 +     * Used in FieldPosition of date/time formatting.
 189.252 +     * HOUR0_FIELD is used for the zero-based 12-hour clock.
 189.253 +     * For example, 11:30 PM + 1 hour results in 00:30 AM.
 189.254 +     */
 189.255 +    public final static int HOUR0_FIELD = 16;
 189.256 +    /**
 189.257 +     * Useful constant for TIMEZONE field alignment.
 189.258 +     * Used in FieldPosition of date/time formatting.
 189.259 +     */
 189.260 +    public final static int TIMEZONE_FIELD = 17;
 189.261 +
 189.262 +    // Proclaim serial compatibility with 1.1 FCS
 189.263 +    private static final long serialVersionUID = 7218322306649953788L;
 189.264 +
 189.265 +    /**
 189.266 +     * Overrides Format.
 189.267 +     * Formats a time object into a time string. Examples of time objects
 189.268 +     * are a time value expressed in milliseconds and a Date object.
 189.269 +     * @param obj must be a Number or a Date.
 189.270 +     * @param toAppendTo the string buffer for the returning time string.
 189.271 +     * @return the string buffer passed in as toAppendTo, with formatted text appended.
 189.272 +     * @param fieldPosition keeps track of the position of the field
 189.273 +     * within the returned string.
 189.274 +     * On input: an alignment field,
 189.275 +     * if desired. On output: the offsets of the alignment field. For
 189.276 +     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
 189.277 +     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
 189.278 +     * begin index and end index of fieldPosition will be set to
 189.279 +     * 0 and 4, respectively.
 189.280 +     * Notice that if the same time field appears
 189.281 +     * more than once in a pattern, the fieldPosition will be set for the first
 189.282 +     * occurrence of that time field. For instance, formatting a Date to
 189.283 +     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
 189.284 +     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
 189.285 +     * the begin index and end index of fieldPosition will be set to
 189.286 +     * 5 and 8, respectively, for the first occurrence of the timezone
 189.287 +     * pattern character 'z'.
 189.288 +     * @see java.text.Format
 189.289 +     */
 189.290 +    public final StringBuffer format(Object obj, StringBuffer toAppendTo,
 189.291 +                                     FieldPosition fieldPosition)
 189.292 +    {
 189.293 +        if (obj instanceof Date)
 189.294 +            return format( (Date)obj, toAppendTo, fieldPosition );
 189.295 +        else if (obj instanceof Number)
 189.296 +            return format( new Date(((Number)obj).longValue()),
 189.297 +                          toAppendTo, fieldPosition );
 189.298 +        else
 189.299 +            throw new IllegalArgumentException("Cannot format given Object as a Date");
 189.300 +    }
 189.301 +
 189.302 +    /**
 189.303 +     * Formats a Date into a date/time string.
 189.304 +     * @param date a Date to be formatted into a date/time string.
 189.305 +     * @param toAppendTo the string buffer for the returning date/time string.
 189.306 +     * @param fieldPosition keeps track of the position of the field
 189.307 +     * within the returned string.
 189.308 +     * On input: an alignment field,
 189.309 +     * if desired. On output: the offsets of the alignment field. For
 189.310 +     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
 189.311 +     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
 189.312 +     * begin index and end index of fieldPosition will be set to
 189.313 +     * 0 and 4, respectively.
 189.314 +     * Notice that if the same time field appears
 189.315 +     * more than once in a pattern, the fieldPosition will be set for the first
 189.316 +     * occurrence of that time field. For instance, formatting a Date to
 189.317 +     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
 189.318 +     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
 189.319 +     * the begin index and end index of fieldPosition will be set to
 189.320 +     * 5 and 8, respectively, for the first occurrence of the timezone
 189.321 +     * pattern character 'z'.
 189.322 +     * @return the string buffer passed in as toAppendTo, with formatted text appended.
 189.323 +     */
 189.324 +    public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
 189.325 +                                        FieldPosition fieldPosition);
 189.326 +
 189.327 +    /**
 189.328 +     * Formats a Date into a date/time string.
 189.329 +     * @param date the time value to be formatted into a time string.
 189.330 +     * @return the formatted time string.
 189.331 +     */
 189.332 +    public final String format(Date date)
 189.333 +    {
 189.334 +        return format(date, new StringBuffer(),
 189.335 +                      DontCareFieldPosition.INSTANCE).toString();
 189.336 +    }
 189.337 +
 189.338 +    /**
 189.339 +     * Parses text from the beginning of the given string to produce a date.
 189.340 +     * The method may not use the entire text of the given string.
 189.341 +     * <p>
 189.342 +     * See the {@link #parse(String, ParsePosition)} method for more information
 189.343 +     * on date parsing.
 189.344 +     *
 189.345 +     * @param source A <code>String</code> whose beginning should be parsed.
 189.346 +     * @return A <code>Date</code> parsed from the string.
 189.347 +     * @exception ParseException if the beginning of the specified string
 189.348 +     *            cannot be parsed.
 189.349 +     */
 189.350 +    public Date parse(String source) throws ParseException
 189.351 +    {
 189.352 +        ParsePosition pos = new ParsePosition(0);
 189.353 +        Date result = parse(source, pos);
 189.354 +        if (pos.index == 0)
 189.355 +            throw new ParseException("Unparseable date: \"" + source + "\"" ,
 189.356 +                pos.errorIndex);
 189.357 +        return result;
 189.358 +    }
 189.359 +
 189.360 +    /**
 189.361 +     * Parse a date/time string according to the given parse position.  For
 189.362 +     * example, a time text {@code "07/10/96 4:5 PM, PDT"} will be parsed into a {@code Date}
 189.363 +     * that is equivalent to {@code Date(837039900000L)}.
 189.364 +     *
 189.365 +     * <p> By default, parsing is lenient: If the input is not in the form used
 189.366 +     * by this object's format method but can still be parsed as a date, then
 189.367 +     * the parse succeeds.  Clients may insist on strict adherence to the
 189.368 +     * format by calling {@link #setLenient(boolean) setLenient(false)}.
 189.369 +     *
 189.370 +     * <p>This parsing operation uses the {@link #calendar} to produce
 189.371 +     * a {@code Date}. As a result, the {@code calendar}'s date-time
 189.372 +     * fields and the {@code TimeZone} value may have been
 189.373 +     * overwritten, depending on subclass implementations. Any {@code
 189.374 +     * TimeZone} value that has previously been set by a call to
 189.375 +     * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
 189.376 +     * to be restored for further operations.
 189.377 +     *
 189.378 +     * @param source  The date/time string to be parsed
 189.379 +     *
 189.380 +     * @param pos   On input, the position at which to start parsing; on
 189.381 +     *              output, the position at which parsing terminated, or the
 189.382 +     *              start position if the parse failed.
 189.383 +     *
 189.384 +     * @return      A {@code Date}, or {@code null} if the input could not be parsed
 189.385 +     */
 189.386 +    public abstract Date parse(String source, ParsePosition pos);
 189.387 +
 189.388 +    /**
 189.389 +     * Parses text from a string to produce a <code>Date</code>.
 189.390 +     * <p>
 189.391 +     * The method attempts to parse text starting at the index given by
 189.392 +     * <code>pos</code>.
 189.393 +     * If parsing succeeds, then the index of <code>pos</code> is updated
 189.394 +     * to the index after the last character used (parsing does not necessarily
 189.395 +     * use all characters up to the end of the string), and the parsed
 189.396 +     * date is returned. The updated <code>pos</code> can be used to
 189.397 +     * indicate the starting point for the next call to this method.
 189.398 +     * If an error occurs, then the index of <code>pos</code> is not
 189.399 +     * changed, the error index of <code>pos</code> is set to the index of
 189.400 +     * the character where the error occurred, and null is returned.
 189.401 +     * <p>
 189.402 +     * See the {@link #parse(String, ParsePosition)} method for more information
 189.403 +     * on date parsing.
 189.404 +     *
 189.405 +     * @param source A <code>String</code>, part of which should be parsed.
 189.406 +     * @param pos A <code>ParsePosition</code> object with index and error
 189.407 +     *            index information as described above.
 189.408 +     * @return A <code>Date</code> parsed from the string. In case of
 189.409 +     *         error, returns null.
 189.410 +     * @exception NullPointerException if <code>pos</code> is null.
 189.411 +     */
 189.412 +    public Object parseObject(String source, ParsePosition pos) {
 189.413 +        return parse(source, pos);
 189.414 +    }
 189.415 +
 189.416 +    /**
 189.417 +     * Constant for full style pattern.
 189.418 +     */
 189.419 +    public static final int FULL = 0;
 189.420 +    /**
 189.421 +     * Constant for long style pattern.
 189.422 +     */
 189.423 +    public static final int LONG = 1;
 189.424 +    /**
 189.425 +     * Constant for medium style pattern.
 189.426 +     */
 189.427 +    public static final int MEDIUM = 2;
 189.428 +    /**
 189.429 +     * Constant for short style pattern.
 189.430 +     */
 189.431 +    public static final int SHORT = 3;
 189.432 +    /**
 189.433 +     * Constant for default style pattern.  Its value is MEDIUM.
 189.434 +     */
 189.435 +    public static final int DEFAULT = MEDIUM;
 189.436 +
 189.437 +    /**
 189.438 +     * Gets the time formatter with the default formatting style
 189.439 +     * for the default locale.
 189.440 +     * @return a time formatter.
 189.441 +     */
 189.442 +    public final static DateFormat getTimeInstance()
 189.443 +    {
 189.444 +        return get(DEFAULT, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
 189.445 +    }
 189.446 +
 189.447 +    /**
 189.448 +     * Gets the time formatter with the given formatting style
 189.449 +     * for the default locale.
 189.450 +     * @param style the given formatting style. For example,
 189.451 +     * SHORT for "h:mm a" in the US locale.
 189.452 +     * @return a time formatter.
 189.453 +     */
 189.454 +    public final static DateFormat getTimeInstance(int style)
 189.455 +    {
 189.456 +        return get(style, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
 189.457 +    }
 189.458 +
 189.459 +    /**
 189.460 +     * Gets the time formatter with the given formatting style
 189.461 +     * for the given locale.
 189.462 +     * @param style the given formatting style. For example,
 189.463 +     * SHORT for "h:mm a" in the US locale.
 189.464 +     * @param aLocale the given locale.
 189.465 +     * @return a time formatter.
 189.466 +     */
 189.467 +    public final static DateFormat getTimeInstance(int style,
 189.468 +                                                 Locale aLocale)
 189.469 +    {
 189.470 +        return get(style, 0, 1, aLocale);
 189.471 +    }
 189.472 +
 189.473 +    /**
 189.474 +     * Gets the date formatter with the default formatting style
 189.475 +     * for the default locale.
 189.476 +     * @return a date formatter.
 189.477 +     */
 189.478 +    public final static DateFormat getDateInstance()
 189.479 +    {
 189.480 +        return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
 189.481 +    }
 189.482 +
 189.483 +    /**
 189.484 +     * Gets the date formatter with the given formatting style
 189.485 +     * for the default locale.
 189.486 +     * @param style the given formatting style. For example,
 189.487 +     * SHORT for "M/d/yy" in the US locale.
 189.488 +     * @return a date formatter.
 189.489 +     */
 189.490 +    public final static DateFormat getDateInstance(int style)
 189.491 +    {
 189.492 +        return get(0, style, 2, Locale.getDefault(Locale.Category.FORMAT));
 189.493 +    }
 189.494 +
 189.495 +    /**
 189.496 +     * Gets the date formatter with the given formatting style
 189.497 +     * for the given locale.
 189.498 +     * @param style the given formatting style. For example,
 189.499 +     * SHORT for "M/d/yy" in the US locale.
 189.500 +     * @param aLocale the given locale.
 189.501 +     * @return a date formatter.
 189.502 +     */
 189.503 +    public final static DateFormat getDateInstance(int style,
 189.504 +                                                 Locale aLocale)
 189.505 +    {
 189.506 +        return get(0, style, 2, aLocale);
 189.507 +    }
 189.508 +
 189.509 +    /**
 189.510 +     * Gets the date/time formatter with the default formatting style
 189.511 +     * for the default locale.
 189.512 +     * @return a date/time formatter.
 189.513 +     */
 189.514 +    public final static DateFormat getDateTimeInstance()
 189.515 +    {
 189.516 +        return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
 189.517 +    }
 189.518 +
 189.519 +    /**
 189.520 +     * Gets the date/time formatter with the given date and time
 189.521 +     * formatting styles for the default locale.
 189.522 +     * @param dateStyle the given date formatting style. For example,
 189.523 +     * SHORT for "M/d/yy" in the US locale.
 189.524 +     * @param timeStyle the given time formatting style. For example,
 189.525 +     * SHORT for "h:mm a" in the US locale.
 189.526 +     * @return a date/time formatter.
 189.527 +     */
 189.528 +    public final static DateFormat getDateTimeInstance(int dateStyle,
 189.529 +                                                       int timeStyle)
 189.530 +    {
 189.531 +        return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
 189.532 +    }
 189.533 +
 189.534 +    /**
 189.535 +     * Gets the date/time formatter with the given formatting styles
 189.536 +     * for the given locale.
 189.537 +     * @param dateStyle the given date formatting style.
 189.538 +     * @param timeStyle the given time formatting style.
 189.539 +     * @param aLocale the given locale.
 189.540 +     * @return a date/time formatter.
 189.541 +     */
 189.542 +    public final static DateFormat
 189.543 +        getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
 189.544 +    {
 189.545 +        return get(timeStyle, dateStyle, 3, aLocale);
 189.546 +    }
 189.547 +
 189.548 +    /**
 189.549 +     * Get a default date/time formatter that uses the SHORT style for both the
 189.550 +     * date and the time.
 189.551 +     */
 189.552 +    public final static DateFormat getInstance() {
 189.553 +        return getDateTimeInstance(SHORT, SHORT);
 189.554 +    }
 189.555 +
 189.556 +    /**
 189.557 +     * Returns an array of all locales for which the
 189.558 +     * <code>get*Instance</code> methods of this class can return
 189.559 +     * localized instances.
 189.560 +     * The returned array represents the union of locales supported by the Java
 189.561 +     * runtime and by installed
 189.562 +     * {@link java.text.spi.DateFormatProvider DateFormatProvider} implementations.
 189.563 +     * It must contain at least a <code>Locale</code> instance equal to
 189.564 +     * {@link java.util.Locale#US Locale.US}.
 189.565 +     *
 189.566 +     * @return An array of locales for which localized
 189.567 +     *         <code>DateFormat</code> instances are available.
 189.568 +     */
 189.569 +    public static Locale[] getAvailableLocales()
 189.570 +    {
 189.571 +        return new Locale[] { Locale.US };
 189.572 +    }
 189.573 +
 189.574 +    /**
 189.575 +     * Set the calendar to be used by this date format.  Initially, the default
 189.576 +     * calendar for the specified or default locale is used.
 189.577 +     *
 189.578 +     * <p>Any {@link java.util.TimeZone TimeZone} and {@linkplain
 189.579 +     * #isLenient() leniency} values that have previously been set are
 189.580 +     * overwritten by {@code newCalendar}'s values.
 189.581 +     *
 189.582 +     * @param newCalendar the new {@code Calendar} to be used by the date format
 189.583 +     */
 189.584 +    public void setCalendar(Calendar newCalendar)
 189.585 +    {
 189.586 +        this.calendar = newCalendar;
 189.587 +    }
 189.588 +
 189.589 +    /**
 189.590 +     * Gets the calendar associated with this date/time formatter.
 189.591 +     *
 189.592 +     * @return the calendar associated with this date/time formatter.
 189.593 +     */
 189.594 +    public Calendar getCalendar()
 189.595 +    {
 189.596 +        return calendar;
 189.597 +    }
 189.598 +
 189.599 +    /**
 189.600 +     * Allows you to set the number formatter.
 189.601 +     * @param newNumberFormat the given new NumberFormat.
 189.602 +     */
 189.603 +    public void setNumberFormat(NumberFormat newNumberFormat)
 189.604 +    {
 189.605 +        this.numberFormat = newNumberFormat;
 189.606 +    }
 189.607 +
 189.608 +    /**
 189.609 +     * Gets the number formatter which this date/time formatter uses to
 189.610 +     * format and parse a time.
 189.611 +     * @return the number formatter which this date/time formatter uses.
 189.612 +     */
 189.613 +    public NumberFormat getNumberFormat()
 189.614 +    {
 189.615 +        return numberFormat;
 189.616 +    }
 189.617 +
 189.618 +    /**
 189.619 +     * Sets the time zone for the calendar of this {@code DateFormat} object.
 189.620 +     * This method is equivalent to the following call.
 189.621 +     * <blockquote><pre>
 189.622 +     *  getCalendar().setTimeZone(zone)
 189.623 +     * </pre></blockquote>
 189.624 +     *
 189.625 +     * <p>The {@code TimeZone} set by this method is overwritten by a
 189.626 +     * {@link #setCalendar(java.util.Calendar) setCalendar} call.
 189.627 +     *
 189.628 +     * <p>The {@code TimeZone} set by this method may be overwritten as
 189.629 +     * a result of a call to the parse method.
 189.630 +     *
 189.631 +     * @param zone the given new time zone.
 189.632 +     */
 189.633 +    public void setTimeZone(TimeZone zone)
 189.634 +    {
 189.635 +        calendar.setTimeZone(zone);
 189.636 +    }
 189.637 +
 189.638 +    /**
 189.639 +     * Gets the time zone.
 189.640 +     * This method is equivalent to the following call.
 189.641 +     * <blockquote><pre>
 189.642 +     *  getCalendar().getTimeZone()
 189.643 +     * </pre></blockquote>
 189.644 +     *
 189.645 +     * @return the time zone associated with the calendar of DateFormat.
 189.646 +     */
 189.647 +    public TimeZone getTimeZone()
 189.648 +    {
 189.649 +        return calendar.getTimeZone();
 189.650 +    }
 189.651 +
 189.652 +    /**
 189.653 +     * Specify whether or not date/time parsing is to be lenient.  With
 189.654 +     * lenient parsing, the parser may use heuristics to interpret inputs that
 189.655 +     * do not precisely match this object's format.  With strict parsing,
 189.656 +     * inputs must match this object's format.
 189.657 +     *
 189.658 +     * <p>This method is equivalent to the following call.
 189.659 +     * <blockquote><pre>
 189.660 +     *  getCalendar().setLenient(lenient)
 189.661 +     * </pre></blockquote>
 189.662 +     *
 189.663 +     * <p>This leniency value is overwritten by a call to {@link
 189.664 +     * #setCalendar(java.util.Calendar) setCalendar()}.
 189.665 +     *
 189.666 +     * @param lenient when {@code true}, parsing is lenient
 189.667 +     * @see java.util.Calendar#setLenient(boolean)
 189.668 +     */
 189.669 +    public void setLenient(boolean lenient)
 189.670 +    {
 189.671 +        calendar.setLenient(lenient);
 189.672 +    }
 189.673 +
 189.674 +    /**
 189.675 +     * Tell whether date/time parsing is to be lenient.
 189.676 +     * This method is equivalent to the following call.
 189.677 +     * <blockquote><pre>
 189.678 +     *  getCalendar().isLenient()
 189.679 +     * </pre></blockquote>
 189.680 +     *
 189.681 +     * @return {@code true} if the {@link #calendar} is lenient;
 189.682 +     *         {@code false} otherwise.
 189.683 +     * @see java.util.Calendar#isLenient()
 189.684 +     */
 189.685 +    public boolean isLenient()
 189.686 +    {
 189.687 +        return calendar.isLenient();
 189.688 +    }
 189.689 +
 189.690 +    /**
 189.691 +     * Overrides hashCode
 189.692 +     */
 189.693 +    public int hashCode() {
 189.694 +        return numberFormat.hashCode();
 189.695 +        // just enough fields for a reasonable distribution
 189.696 +    }
 189.697 +
 189.698 +    /**
 189.699 +     * Overrides equals
 189.700 +     */
 189.701 +    public boolean equals(Object obj) {
 189.702 +        if (this == obj) return true;
 189.703 +        if (obj == null || getClass() != obj.getClass()) return false;
 189.704 +        DateFormat other = (DateFormat) obj;
 189.705 +        return (// calendar.equivalentTo(other.calendar) // THIS API DOESN'T EXIST YET!
 189.706 +                calendar.getFirstDayOfWeek() == other.calendar.getFirstDayOfWeek() &&
 189.707 +                calendar.getMinimalDaysInFirstWeek() == other.calendar.getMinimalDaysInFirstWeek() &&
 189.708 +                calendar.isLenient() == other.calendar.isLenient() &&
 189.709 +                calendar.getTimeZone().equals(other.calendar.getTimeZone()) &&
 189.710 +                numberFormat.equals(other.numberFormat));
 189.711 +    }
 189.712 +
 189.713 +    /**
 189.714 +     * Overrides Cloneable
 189.715 +     */
 189.716 +    public Object clone()
 189.717 +    {
 189.718 +        DateFormat other = (DateFormat) super.clone();
 189.719 +        other.calendar = (Calendar) calendar.clone();
 189.720 +        other.numberFormat = (NumberFormat) numberFormat.clone();
 189.721 +        return other;
 189.722 +    }
 189.723 +
 189.724 +    /**
 189.725 +     * Creates a DateFormat with the given time and/or date style in the given
 189.726 +     * locale.
 189.727 +     * @param timeStyle a value from 0 to 3 indicating the time format,
 189.728 +     * ignored if flags is 2
 189.729 +     * @param dateStyle a value from 0 to 3 indicating the time format,
 189.730 +     * ignored if flags is 1
 189.731 +     * @param flags either 1 for a time format, 2 for a date format,
 189.732 +     * or 3 for a date/time format
 189.733 +     * @param loc the locale for the format
 189.734 +     */
 189.735 +    private static DateFormat get(int timeStyle, int dateStyle,
 189.736 +                                  int flags, Locale loc) {
 189.737 +        if ((flags & 1) != 0) {
 189.738 +            if (timeStyle < 0 || timeStyle > 3) {
 189.739 +                throw new IllegalArgumentException("Illegal time style " + timeStyle);
 189.740 +            }
 189.741 +        } else {
 189.742 +            timeStyle = -1;
 189.743 +        }
 189.744 +        if ((flags & 2) != 0) {
 189.745 +            if (dateStyle < 0 || dateStyle > 3) {
 189.746 +                throw new IllegalArgumentException("Illegal date style " + dateStyle);
 189.747 +            }
 189.748 +        } else {
 189.749 +            dateStyle = -1;
 189.750 +        }
 189.751 +        try {
 189.752 +            // Check whether a provider can provide an implementation that's closer
 189.753 +            // to the requested locale than what the Java runtime itself can provide.
 189.754 +            /*
 189.755 +            LocaleServiceProviderPool pool =
 189.756 +                LocaleServiceProviderPool.getPool(DateFormatProvider.class);
 189.757 +            if (pool.hasProviders()) {
 189.758 +                DateFormat providersInstance = pool.getLocalizedObject(
 189.759 +                                                    DateFormatGetter.INSTANCE,
 189.760 +                                                    loc,
 189.761 +                                                    timeStyle,
 189.762 +                                                    dateStyle,
 189.763 +                                                    flags);
 189.764 +                if (providersInstance != null) {
 189.765 +                    return providersInstance;
 189.766 +                }
 189.767 +            }
 189.768 +            */
 189.769 +
 189.770 +            return new SimpleDateFormat(timeStyle, dateStyle, loc);
 189.771 +        } catch (MissingResourceException e) {
 189.772 +            return new SimpleDateFormat("M/d/yy h:mm a");
 189.773 +        }
 189.774 +    }
 189.775 +
 189.776 +    /**
 189.777 +     * Create a new date format.
 189.778 +     */
 189.779 +    protected DateFormat() {}
 189.780 +
 189.781 +    /**
 189.782 +     * Defines constants that are used as attribute keys in the
 189.783 +     * <code>AttributedCharacterIterator</code> returned
 189.784 +     * from <code>DateFormat.formatToCharacterIterator</code> and as
 189.785 +     * field identifiers in <code>FieldPosition</code>.
 189.786 +     * <p>
 189.787 +     * The class also provides two methods to map
 189.788 +     * between its constants and the corresponding Calendar constants.
 189.789 +     *
 189.790 +     * @since 1.4
 189.791 +     * @see java.util.Calendar
 189.792 +     */
 189.793 +    public static class Field extends Format.Field {
 189.794 +
 189.795 +        // Proclaim serial compatibility with 1.4 FCS
 189.796 +        private static final long serialVersionUID = 7441350119349544720L;
 189.797 +
 189.798 +        // table of all instances in this class, used by readResolve
 189.799 +        private static final Map instanceMap = new HashMap(18);
 189.800 +        // Maps from Calendar constant (such as Calendar.ERA) to Field
 189.801 +        // constant (such as Field.ERA).
 189.802 +        private static final Field[] calendarToFieldMapping =
 189.803 +                                             new Field[Calendar.FIELD_COUNT];
 189.804 +
 189.805 +        /** Calendar field. */
 189.806 +        private int calendarField;
 189.807 +
 189.808 +        /**
 189.809 +         * Returns the <code>Field</code> constant that corresponds to
 189.810 +         * the <code>Calendar</code> constant <code>calendarField</code>.
 189.811 +         * If there is no direct mapping between the <code>Calendar</code>
 189.812 +         * constant and a <code>Field</code>, null is returned.
 189.813 +         *
 189.814 +         * @throws IllegalArgumentException if <code>calendarField</code> is
 189.815 +         *         not the value of a <code>Calendar</code> field constant.
 189.816 +         * @param calendarField Calendar field constant
 189.817 +         * @return Field instance representing calendarField.
 189.818 +         * @see java.util.Calendar
 189.819 +         */
 189.820 +        public static Field ofCalendarField(int calendarField) {
 189.821 +            if (calendarField < 0 || calendarField >=
 189.822 +                        calendarToFieldMapping.length) {
 189.823 +                throw new IllegalArgumentException("Unknown Calendar constant "
 189.824 +                                                   + calendarField);
 189.825 +            }
 189.826 +            return calendarToFieldMapping[calendarField];
 189.827 +        }
 189.828 +
 189.829 +        /**
 189.830 +         * Creates a <code>Field</code>.
 189.831 +         *
 189.832 +         * @param name the name of the <code>Field</code>
 189.833 +         * @param calendarField the <code>Calendar</code> constant this
 189.834 +         *        <code>Field</code> corresponds to; any value, even one
 189.835 +         *        outside the range of legal <code>Calendar</code> values may
 189.836 +         *        be used, but <code>-1</code> should be used for values
 189.837 +         *        that don't correspond to legal <code>Calendar</code> values
 189.838 +         */
 189.839 +        protected Field(String name, int calendarField) {
 189.840 +            super(name);
 189.841 +            this.calendarField = calendarField;
 189.842 +            if (this.getClass() == DateFormat.Field.class) {
 189.843 +                instanceMap.put(name, this);
 189.844 +                if (calendarField >= 0) {
 189.845 +                    // assert(calendarField < Calendar.FIELD_COUNT);
 189.846 +                    calendarToFieldMapping[calendarField] = this;
 189.847 +                }
 189.848 +            }
 189.849 +        }
 189.850 +
 189.851 +        /**
 189.852 +         * Returns the <code>Calendar</code> field associated with this
 189.853 +         * attribute. For example, if this represents the hours field of
 189.854 +         * a <code>Calendar</code>, this would return
 189.855 +         * <code>Calendar.HOUR</code>. If there is no corresponding
 189.856 +         * <code>Calendar</code> constant, this will return -1.
 189.857 +         *
 189.858 +         * @return Calendar constant for this field
 189.859 +         * @see java.util.Calendar
 189.860 +         */
 189.861 +        public int getCalendarField() {
 189.862 +            return calendarField;
 189.863 +        }
 189.864 +
 189.865 +        /**
 189.866 +         * Resolves instances being deserialized to the predefined constants.
 189.867 +         *
 189.868 +         * @throws InvalidObjectException if the constant could not be
 189.869 +         *         resolved.
 189.870 +         * @return resolved DateFormat.Field constant
 189.871 +         */
 189.872 +        protected Object readResolve() throws InvalidObjectException {
 189.873 +            if (this.getClass() != DateFormat.Field.class) {
 189.874 +                throw new InvalidObjectException("subclass didn't correctly implement readResolve");
 189.875 +            }
 189.876 +
 189.877 +            Object instance = instanceMap.get(getName());
 189.878 +            if (instance != null) {
 189.879 +                return instance;
 189.880 +            } else {
 189.881 +                throw new InvalidObjectException("unknown attribute name");
 189.882 +            }
 189.883 +        }
 189.884 +
 189.885 +        //
 189.886 +        // The constants
 189.887 +        //
 189.888 +
 189.889 +        /**
 189.890 +         * Constant identifying the era field.
 189.891 +         */
 189.892 +        public final static Field ERA = new Field("era", Calendar.ERA);
 189.893 +
 189.894 +        /**
 189.895 +         * Constant identifying the year field.
 189.896 +         */
 189.897 +        public final static Field YEAR = new Field("year", Calendar.YEAR);
 189.898 +
 189.899 +        /**
 189.900 +         * Constant identifying the month field.
 189.901 +         */
 189.902 +        public final static Field MONTH = new Field("month", Calendar.MONTH);
 189.903 +
 189.904 +        /**
 189.905 +         * Constant identifying the day of month field.
 189.906 +         */
 189.907 +        public final static Field DAY_OF_MONTH = new
 189.908 +                            Field("day of month", Calendar.DAY_OF_MONTH);
 189.909 +
 189.910 +        /**
 189.911 +         * Constant identifying the hour of day field, where the legal values
 189.912 +         * are 1 to 24.
 189.913 +         */
 189.914 +        public final static Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
 189.915 +
 189.916 +        /**
 189.917 +         * Constant identifying the hour of day field, where the legal values
 189.918 +         * are 0 to 23.
 189.919 +         */
 189.920 +        public final static Field HOUR_OF_DAY0 = new
 189.921 +               Field("hour of day", Calendar.HOUR_OF_DAY);
 189.922 +
 189.923 +        /**
 189.924 +         * Constant identifying the minute field.
 189.925 +         */
 189.926 +        public final static Field MINUTE =new Field("minute", Calendar.MINUTE);
 189.927 +
 189.928 +        /**
 189.929 +         * Constant identifying the second field.
 189.930 +         */
 189.931 +        public final static Field SECOND =new Field("second", Calendar.SECOND);
 189.932 +
 189.933 +        /**
 189.934 +         * Constant identifying the millisecond field.
 189.935 +         */
 189.936 +        public final static Field MILLISECOND = new
 189.937 +                Field("millisecond", Calendar.MILLISECOND);
 189.938 +
 189.939 +        /**
 189.940 +         * Constant identifying the day of week field.
 189.941 +         */
 189.942 +        public final static Field DAY_OF_WEEK = new
 189.943 +                Field("day of week", Calendar.DAY_OF_WEEK);
 189.944 +
 189.945 +        /**
 189.946 +         * Constant identifying the day of year field.
 189.947 +         */
 189.948 +        public final static Field DAY_OF_YEAR = new
 189.949 +                Field("day of year", Calendar.DAY_OF_YEAR);
 189.950 +
 189.951 +        /**
 189.952 +         * Constant identifying the day of week field.
 189.953 +         */
 189.954 +        public final static Field DAY_OF_WEEK_IN_MONTH =
 189.955 +                     new Field("day of week in month",
 189.956 +                                            Calendar.DAY_OF_WEEK_IN_MONTH);
 189.957 +
 189.958 +        /**
 189.959 +         * Constant identifying the week of year field.
 189.960 +         */
 189.961 +        public final static Field WEEK_OF_YEAR = new
 189.962 +              Field("week of year", Calendar.WEEK_OF_YEAR);
 189.963 +
 189.964 +        /**
 189.965 +         * Constant identifying the week of month field.
 189.966 +         */
 189.967 +        public final static Field WEEK_OF_MONTH = new
 189.968 +            Field("week of month", Calendar.WEEK_OF_MONTH);
 189.969 +
 189.970 +        /**
 189.971 +         * Constant identifying the time of day indicator
 189.972 +         * (e.g. "a.m." or "p.m.") field.
 189.973 +         */
 189.974 +        public final static Field AM_PM = new
 189.975 +                            Field("am pm", Calendar.AM_PM);
 189.976 +
 189.977 +        /**
 189.978 +         * Constant identifying the hour field, where the legal values are
 189.979 +         * 1 to 12.
 189.980 +         */
 189.981 +        public final static Field HOUR1 = new Field("hour 1", -1);
 189.982 +
 189.983 +        /**
 189.984 +         * Constant identifying the hour field, where the legal values are
 189.985 +         * 0 to 11.
 189.986 +         */
 189.987 +        public final static Field HOUR0 = new
 189.988 +                            Field("hour", Calendar.HOUR);
 189.989 +
 189.990 +        /**
 189.991 +         * Constant identifying the time zone field.
 189.992 +         */
 189.993 +        public final static Field TIME_ZONE = new Field("time zone", -1);
 189.994 +    }
 189.995 +
 189.996 +    /**
 189.997 +     * Obtains a DateFormat instance from a DateFormatProvider
 189.998 +     * implementation.
 189.999 +    private static class DateFormatGetter
189.1000 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatProvider, DateFormat> {
189.1001 +        private static final DateFormatGetter INSTANCE = new DateFormatGetter();
189.1002 +
189.1003 +        public DateFormat getObject(DateFormatProvider dateFormatProvider,
189.1004 +                                Locale locale,
189.1005 +                                String key,
189.1006 +                                Object... params) {
189.1007 +            assert params.length == 3;
189.1008 +
189.1009 +            int timeStyle = (Integer)params[0];
189.1010 +            int dateStyle = (Integer)params[1];
189.1011 +            int flags = (Integer)params[2];
189.1012 +
189.1013 +            switch (flags) {
189.1014 +            case 1:
189.1015 +                return dateFormatProvider.getTimeInstance(timeStyle, locale);
189.1016 +            case 2:
189.1017 +                return dateFormatProvider.getDateInstance(dateStyle, locale);
189.1018 +            case 3:
189.1019 +                return dateFormatProvider.getDateTimeInstance(dateStyle, timeStyle, locale);
189.1020 +            default:
189.1021 +                assert false : "should not happen";
189.1022 +            }
189.1023 +
189.1024 +            return null;
189.1025 +        }
189.1026 +    }
189.1027 +     */
189.1028 +}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/rt/emul/compact/src/main/java/java/text/DateFormatSymbols.java	Wed Apr 30 15:04:10 2014 +0200
   190.3 @@ -0,0 +1,786 @@
   190.4 +/*
   190.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   190.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   190.7 + *
   190.8 + * This code is free software; you can redistribute it and/or modify it
   190.9 + * under the terms of the GNU General Public License version 2 only, as
  190.10 + * published by the Free Software Foundation.  Oracle designates this
  190.11 + * particular file as subject to the "Classpath" exception as provided
  190.12 + * by Oracle in the LICENSE file that accompanied this code.
  190.13 + *
  190.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  190.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  190.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  190.17 + * version 2 for more details (a copy is included in the LICENSE file that
  190.18 + * accompanied this code).
  190.19 + *
  190.20 + * You should have received a copy of the GNU General Public License version
  190.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  190.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  190.23 + *
  190.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  190.25 + * or visit www.oracle.com if you need additional information or have any
  190.26 + * questions.
  190.27 + */
  190.28 +
  190.29 +/*
  190.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  190.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  190.32 + *
  190.33 + *   The original version of this source code and documentation is copyrighted
  190.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  190.35 + * materials are provided under terms of a License Agreement between Taligent
  190.36 + * and Sun. This technology is protected by multiple US and International
  190.37 + * patents. This notice and attribution to Taligent may not be removed.
  190.38 + *   Taligent is a registered trademark of Taligent, Inc.
  190.39 + *
  190.40 + */
  190.41 +
  190.42 +package java.text;
  190.43 +
  190.44 +import java.io.IOException;
  190.45 +import java.io.ObjectOutputStream;
  190.46 +import java.io.Serializable;
  190.47 +import java.lang.ref.SoftReference;
  190.48 +import java.util.Arrays;
  190.49 +import java.util.Locale;
  190.50 +import java.util.ResourceBundle;
  190.51 +import java.util.concurrent.ConcurrentHashMap;
  190.52 +import java.util.concurrent.ConcurrentMap;
  190.53 +
  190.54 +/**
  190.55 + * <code>DateFormatSymbols</code> is a public class for encapsulating
  190.56 + * localizable date-time formatting data, such as the names of the
  190.57 + * months, the names of the days of the week, and the time zone data.
  190.58 + * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
  190.59 + * <code>DateFormatSymbols</code> to encapsulate this information.
  190.60 + *
  190.61 + * <p>
  190.62 + * Typically you shouldn't use <code>DateFormatSymbols</code> directly.
  190.63 + * Rather, you are encouraged to create a date-time formatter with the
  190.64 + * <code>DateFormat</code> class's factory methods: <code>getTimeInstance</code>,
  190.65 + * <code>getDateInstance</code>, or <code>getDateTimeInstance</code>.
  190.66 + * These methods automatically create a <code>DateFormatSymbols</code> for
  190.67 + * the formatter so that you don't have to. After the
  190.68 + * formatter is created, you may modify its format pattern using the
  190.69 + * <code>setPattern</code> method. For more information about
  190.70 + * creating formatters using <code>DateFormat</code>'s factory methods,
  190.71 + * see {@link DateFormat}.
  190.72 + *
  190.73 + * <p>
  190.74 + * If you decide to create a date-time formatter with a specific
  190.75 + * format pattern for a specific locale, you can do so with:
  190.76 + * <blockquote>
  190.77 + * <pre>
  190.78 + * new SimpleDateFormat(aPattern, DateFormatSymbols.getInstance(aLocale)).
  190.79 + * </pre>
  190.80 + * </blockquote>
  190.81 + *
  190.82 + * <p>
  190.83 + * <code>DateFormatSymbols</code> objects are cloneable. When you obtain
  190.84 + * a <code>DateFormatSymbols</code> object, feel free to modify the
  190.85 + * date-time formatting data. For instance, you can replace the localized
  190.86 + * date-time format pattern characters with the ones that you feel easy
  190.87 + * to remember. Or you can change the representative cities
  190.88 + * to your favorite ones.
  190.89 + *
  190.90 + * <p>
  190.91 + * New <code>DateFormatSymbols</code> subclasses may be added to support
  190.92 + * <code>SimpleDateFormat</code> for date-time formatting for additional locales.
  190.93 +
  190.94 + * @see          DateFormat
  190.95 + * @see          SimpleDateFormat
  190.96 + * @see          java.util.SimpleTimeZone
  190.97 + * @author       Chen-Lieh Huang
  190.98 + */
  190.99 +public class DateFormatSymbols implements Serializable, Cloneable {
 190.100 +
 190.101 +    /**
 190.102 +     * Construct a DateFormatSymbols object by loading format data from
 190.103 +     * resources for the default locale. This constructor can only
 190.104 +     * construct instances for the locales supported by the Java
 190.105 +     * runtime environment, not for those supported by installed
 190.106 +     * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
 190.107 +     * implementations. For full locale coverage, use the
 190.108 +     * {@link #getInstance(Locale) getInstance} method.
 190.109 +     *
 190.110 +     * @see #getInstance()
 190.111 +     * @exception  java.util.MissingResourceException
 190.112 +     *             if the resources for the default locale cannot be
 190.113 +     *             found or cannot be loaded.
 190.114 +     */
 190.115 +    public DateFormatSymbols()
 190.116 +    {
 190.117 +        initializeData(Locale.getDefault(Locale.Category.FORMAT));
 190.118 +    }
 190.119 +
 190.120 +    /**
 190.121 +     * Construct a DateFormatSymbols object by loading format data from
 190.122 +     * resources for the given locale. This constructor can only
 190.123 +     * construct instances for the locales supported by the Java
 190.124 +     * runtime environment, not for those supported by installed
 190.125 +     * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
 190.126 +     * implementations. For full locale coverage, use the
 190.127 +     * {@link #getInstance(Locale) getInstance} method.
 190.128 +     *
 190.129 +     * @see #getInstance(Locale)
 190.130 +     * @exception  java.util.MissingResourceException
 190.131 +     *             if the resources for the specified locale cannot be
 190.132 +     *             found or cannot be loaded.
 190.133 +     */
 190.134 +    public DateFormatSymbols(Locale locale)
 190.135 +    {
 190.136 +        initializeData(locale);
 190.137 +    }
 190.138 +
 190.139 +    /**
 190.140 +     * Era strings. For example: "AD" and "BC".  An array of 2 strings,
 190.141 +     * indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
 190.142 +     * @serial
 190.143 +     */
 190.144 +    String eras[] = null;
 190.145 +
 190.146 +    /**
 190.147 +     * Month strings. For example: "January", "February", etc.  An array
 190.148 +     * of 13 strings (some calendars have 13 months), indexed by
 190.149 +     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
 190.150 +     * @serial
 190.151 +     */
 190.152 +    String months[] = null;
 190.153 +
 190.154 +    /**
 190.155 +     * Short month strings. For example: "Jan", "Feb", etc.  An array of
 190.156 +     * 13 strings (some calendars have 13 months), indexed by
 190.157 +     * <code>Calendar.JANUARY</code>, <code>Calendar.FEBRUARY</code>, etc.
 190.158 +
 190.159 +     * @serial
 190.160 +     */
 190.161 +    String shortMonths[] = null;
 190.162 +
 190.163 +    /**
 190.164 +     * Weekday strings. For example: "Sunday", "Monday", etc.  An array
 190.165 +     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
 190.166 +     * <code>Calendar.MONDAY</code>, etc.
 190.167 +     * The element <code>weekdays[0]</code> is ignored.
 190.168 +     * @serial
 190.169 +     */
 190.170 +    String weekdays[] = null;
 190.171 +
 190.172 +    /**
 190.173 +     * Short weekday strings. For example: "Sun", "Mon", etc.  An array
 190.174 +     * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
 190.175 +     * <code>Calendar.MONDAY</code>, etc.
 190.176 +     * The element <code>shortWeekdays[0]</code> is ignored.
 190.177 +     * @serial
 190.178 +     */
 190.179 +    String shortWeekdays[] = null;
 190.180 +
 190.181 +    /**
 190.182 +     * AM and PM strings. For example: "AM" and "PM".  An array of
 190.183 +     * 2 strings, indexed by <code>Calendar.AM</code> and
 190.184 +     * <code>Calendar.PM</code>.
 190.185 +     * @serial
 190.186 +     */
 190.187 +    String ampms[] = null;
 190.188 +
 190.189 +    /**
 190.190 +     * Localized names of time zones in this locale.  This is a
 190.191 +     * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
 190.192 +     * where <em>m</em> is at least 5.  Each of the <em>n</em> rows is an
 190.193 +     * entry containing the localized names for a single <code>TimeZone</code>.
 190.194 +     * Each such row contains (with <code>i</code> ranging from
 190.195 +     * 0..<em>n</em>-1):
 190.196 +     * <ul>
 190.197 +     * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
 190.198 +     * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
 190.199 +     * time</li>
 190.200 +     * <li><code>zoneStrings[i][2]</code> - short name of zone in
 190.201 +     * standard time</li>
 190.202 +     * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
 190.203 +     * saving time</li>
 190.204 +     * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
 190.205 +     * saving time</li>
 190.206 +     * </ul>
 190.207 +     * The zone ID is <em>not</em> localized; it's one of the valid IDs of
 190.208 +     * the {@link java.util.TimeZone TimeZone} class that are not
 190.209 +     * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
 190.210 +     * All other entries are localized names.
 190.211 +     * @see java.util.TimeZone
 190.212 +     * @serial
 190.213 +     */
 190.214 +    String zoneStrings[][] = null;
 190.215 +
 190.216 +    /**
 190.217 +     * Indicates that zoneStrings is set externally with setZoneStrings() method.
 190.218 +     */
 190.219 +    transient boolean isZoneStringsSet = false;
 190.220 +
 190.221 +    /**
 190.222 +     * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
 190.223 +     * All locales use the same these unlocalized pattern characters.
 190.224 +     */
 190.225 +    static final String  patternChars = "GyMdkHmsSEDFwWahKzZYuX";
 190.226 +
 190.227 +    static final int PATTERN_ERA                  =  0; // G
 190.228 +    static final int PATTERN_YEAR                 =  1; // y
 190.229 +    static final int PATTERN_MONTH                =  2; // M
 190.230 +    static final int PATTERN_DAY_OF_MONTH         =  3; // d
 190.231 +    static final int PATTERN_HOUR_OF_DAY1         =  4; // k
 190.232 +    static final int PATTERN_HOUR_OF_DAY0         =  5; // H
 190.233 +    static final int PATTERN_MINUTE               =  6; // m
 190.234 +    static final int PATTERN_SECOND               =  7; // s
 190.235 +    static final int PATTERN_MILLISECOND          =  8; // S
 190.236 +    static final int PATTERN_DAY_OF_WEEK          =  9; // E
 190.237 +    static final int PATTERN_DAY_OF_YEAR          = 10; // D
 190.238 +    static final int PATTERN_DAY_OF_WEEK_IN_MONTH = 11; // F
 190.239 +    static final int PATTERN_WEEK_OF_YEAR         = 12; // w
 190.240 +    static final int PATTERN_WEEK_OF_MONTH        = 13; // W
 190.241 +    static final int PATTERN_AM_PM                = 14; // a
 190.242 +    static final int PATTERN_HOUR1                = 15; // h
 190.243 +    static final int PATTERN_HOUR0                = 16; // K
 190.244 +    static final int PATTERN_ZONE_NAME            = 17; // z
 190.245 +    static final int PATTERN_ZONE_VALUE           = 18; // Z
 190.246 +    static final int PATTERN_WEEK_YEAR            = 19; // Y
 190.247 +    static final int PATTERN_ISO_DAY_OF_WEEK      = 20; // u
 190.248 +    static final int PATTERN_ISO_ZONE             = 21; // X
 190.249 +
 190.250 +    /**
 190.251 +     * Localized date-time pattern characters. For example, a locale may
 190.252 +     * wish to use 'u' rather than 'y' to represent years in its date format
 190.253 +     * pattern strings.
 190.254 +     * This string must be exactly 18 characters long, with the index of
 190.255 +     * the characters described by <code>DateFormat.ERA_FIELD</code>,
 190.256 +     * <code>DateFormat.YEAR_FIELD</code>, etc.  Thus, if the string were
 190.257 +     * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
 190.258 +     * @serial
 190.259 +     */
 190.260 +    String  localPatternChars = null;
 190.261 +
 190.262 +    /**
 190.263 +     * The locale which is used for initializing this DateFormatSymbols object.
 190.264 +     *
 190.265 +     * @since 1.6
 190.266 +     * @serial
 190.267 +     */
 190.268 +    Locale locale = null;
 190.269 +
 190.270 +    /* use serialVersionUID from JDK 1.1.4 for interoperability */
 190.271 +    static final long serialVersionUID = -5987973545549424702L;
 190.272 +
 190.273 +    /**
 190.274 +     * Returns an array of all locales for which the
 190.275 +     * <code>getInstance</code> methods of this class can return
 190.276 +     * localized instances.
 190.277 +     * The returned array represents the union of locales supported by the
 190.278 +     * Java runtime and by installed
 190.279 +     * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
 190.280 +     * implementations.  It must contain at least a <code>Locale</code>
 190.281 +     * instance equal to {@link java.util.Locale#US Locale.US}.
 190.282 +     *
 190.283 +     * @return An array of locales for which localized
 190.284 +     *         <code>DateFormatSymbols</code> instances are available.
 190.285 +     * @since 1.6
 190.286 +     */
 190.287 +    public static Locale[] getAvailableLocales() {
 190.288 +        return new Locale[] { Locale.US };
 190.289 +//        LocaleServiceProviderPool pool=
 190.290 +//            LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
 190.291 +//        return pool.getAvailableLocales();
 190.292 +    }
 190.293 +
 190.294 +    /**
 190.295 +     * Gets the <code>DateFormatSymbols</code> instance for the default
 190.296 +     * locale.  This method provides access to <code>DateFormatSymbols</code>
 190.297 +     * instances for locales supported by the Java runtime itself as well
 190.298 +     * as for those supported by installed
 190.299 +     * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
 190.300 +     * implementations.
 190.301 +     * @return a <code>DateFormatSymbols</code> instance.
 190.302 +     * @since 1.6
 190.303 +     */
 190.304 +    public static final DateFormatSymbols getInstance() {
 190.305 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT));
 190.306 +    }
 190.307 +
 190.308 +    /**
 190.309 +     * Gets the <code>DateFormatSymbols</code> instance for the specified
 190.310 +     * locale.  This method provides access to <code>DateFormatSymbols</code>
 190.311 +     * instances for locales supported by the Java runtime itself as well
 190.312 +     * as for those supported by installed
 190.313 +     * {@link java.text.spi.DateFormatSymbolsProvider DateFormatSymbolsProvider}
 190.314 +     * implementations.
 190.315 +     * @param locale the given locale.
 190.316 +     * @return a <code>DateFormatSymbols</code> instance.
 190.317 +     * @exception NullPointerException if <code>locale</code> is null
 190.318 +     * @since 1.6
 190.319 +     */
 190.320 +    public static final DateFormatSymbols getInstance(Locale locale) {
 190.321 +        DateFormatSymbols dfs = getProviderInstance(locale);
 190.322 +        if (dfs != null) {
 190.323 +            return dfs;
 190.324 +        }
 190.325 +        return (DateFormatSymbols) getCachedInstance(locale).clone();
 190.326 +    }
 190.327 +
 190.328 +    /**
 190.329 +     * Returns a DateFormatSymbols provided by a provider or found in
 190.330 +     * the cache. Note that this method returns a cached instance,
 190.331 +     * not its clone. Therefore, the instance should never be given to
 190.332 +     * an application.
 190.333 +     */
 190.334 +    static final DateFormatSymbols getInstanceRef(Locale locale) {
 190.335 +        DateFormatSymbols dfs = getProviderInstance(locale);
 190.336 +        if (dfs != null) {
 190.337 +            return dfs;
 190.338 +        }
 190.339 +        return getCachedInstance(locale);
 190.340 +    }
 190.341 +
 190.342 +    private static DateFormatSymbols getProviderInstance(Locale locale) {
 190.343 +        DateFormatSymbols providersInstance = null;
 190.344 +
 190.345 +        // Check whether a provider can provide an implementation that's closer
 190.346 +        // to the requested locale than what the Java runtime itself can provide.
 190.347 +//        LocaleServiceProviderPool pool =
 190.348 +//            LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
 190.349 +//        if (pool.hasProviders()) {
 190.350 +//            providersInstance = pool.getLocalizedObject(
 190.351 +//                                    DateFormatSymbolsGetter.INSTANCE, locale);
 190.352 +//        }
 190.353 +        return providersInstance;
 190.354 +    }
 190.355 +
 190.356 +    /**
 190.357 +     * Returns a cached DateFormatSymbols if it's found in the
 190.358 +     * cache. Otherwise, this method returns a newly cached instance
 190.359 +     * for the given locale.
 190.360 +     */
 190.361 +    private static DateFormatSymbols getCachedInstance(Locale locale) {
 190.362 +        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
 190.363 +        DateFormatSymbols dfs = null;
 190.364 +        if (ref == null || (dfs = ref.get()) == null) {
 190.365 +            dfs = new DateFormatSymbols(locale);
 190.366 +            ref = new SoftReference<DateFormatSymbols>(dfs);
 190.367 +            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
 190.368 +            if (x != null) {
 190.369 +                DateFormatSymbols y = x.get();
 190.370 +                if (y != null) {
 190.371 +                    dfs = y;
 190.372 +                } else {
 190.373 +                    // Replace the empty SoftReference with ref.
 190.374 +                    cachedInstances.put(locale, ref);
 190.375 +                }
 190.376 +            }
 190.377 +        }
 190.378 +        return dfs;
 190.379 +    }
 190.380 +
 190.381 +    /**
 190.382 +     * Gets era strings. For example: "AD" and "BC".
 190.383 +     * @return the era strings.
 190.384 +     */
 190.385 +    public String[] getEras() {
 190.386 +        return Arrays.copyOf(eras, eras.length);
 190.387 +    }
 190.388 +
 190.389 +    /**
 190.390 +     * Sets era strings. For example: "AD" and "BC".
 190.391 +     * @param newEras the new era strings.
 190.392 +     */
 190.393 +    public void setEras(String[] newEras) {
 190.394 +        eras = Arrays.copyOf(newEras, newEras.length);
 190.395 +    }
 190.396 +
 190.397 +    /**
 190.398 +     * Gets month strings. For example: "January", "February", etc.
 190.399 +     * @return the month strings.
 190.400 +     */
 190.401 +    public String[] getMonths() {
 190.402 +        return Arrays.copyOf(months, months.length);
 190.403 +    }
 190.404 +
 190.405 +    /**
 190.406 +     * Sets month strings. For example: "January", "February", etc.
 190.407 +     * @param newMonths the new month strings.
 190.408 +     */
 190.409 +    public void setMonths(String[] newMonths) {
 190.410 +        months = Arrays.copyOf(newMonths, newMonths.length);
 190.411 +    }
 190.412 +
 190.413 +    /**
 190.414 +     * Gets short month strings. For example: "Jan", "Feb", etc.
 190.415 +     * @return the short month strings.
 190.416 +     */
 190.417 +    public String[] getShortMonths() {
 190.418 +        return Arrays.copyOf(shortMonths, shortMonths.length);
 190.419 +    }
 190.420 +
 190.421 +    /**
 190.422 +     * Sets short month strings. For example: "Jan", "Feb", etc.
 190.423 +     * @param newShortMonths the new short month strings.
 190.424 +     */
 190.425 +    public void setShortMonths(String[] newShortMonths) {
 190.426 +        shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
 190.427 +    }
 190.428 +
 190.429 +    /**
 190.430 +     * Gets weekday strings. For example: "Sunday", "Monday", etc.
 190.431 +     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
 190.432 +     * <code>Calendar.MONDAY</code>, etc. to index the result array.
 190.433 +     */
 190.434 +    public String[] getWeekdays() {
 190.435 +        return Arrays.copyOf(weekdays, weekdays.length);
 190.436 +    }
 190.437 +
 190.438 +    /**
 190.439 +     * Sets weekday strings. For example: "Sunday", "Monday", etc.
 190.440 +     * @param newWeekdays the new weekday strings. The array should
 190.441 +     * be indexed by <code>Calendar.SUNDAY</code>,
 190.442 +     * <code>Calendar.MONDAY</code>, etc.
 190.443 +     */
 190.444 +    public void setWeekdays(String[] newWeekdays) {
 190.445 +        weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
 190.446 +    }
 190.447 +
 190.448 +    /**
 190.449 +     * Gets short weekday strings. For example: "Sun", "Mon", etc.
 190.450 +     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
 190.451 +     * <code>Calendar.MONDAY</code>, etc. to index the result array.
 190.452 +     */
 190.453 +    public String[] getShortWeekdays() {
 190.454 +        return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
 190.455 +    }
 190.456 +
 190.457 +    /**
 190.458 +     * Sets short weekday strings. For example: "Sun", "Mon", etc.
 190.459 +     * @param newShortWeekdays the new short weekday strings. The array should
 190.460 +     * be indexed by <code>Calendar.SUNDAY</code>,
 190.461 +     * <code>Calendar.MONDAY</code>, etc.
 190.462 +     */
 190.463 +    public void setShortWeekdays(String[] newShortWeekdays) {
 190.464 +        shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
 190.465 +    }
 190.466 +
 190.467 +    /**
 190.468 +     * Gets ampm strings. For example: "AM" and "PM".
 190.469 +     * @return the ampm strings.
 190.470 +     */
 190.471 +    public String[] getAmPmStrings() {
 190.472 +        return Arrays.copyOf(ampms, ampms.length);
 190.473 +    }
 190.474 +
 190.475 +    /**
 190.476 +     * Sets ampm strings. For example: "AM" and "PM".
 190.477 +     * @param newAmpms the new ampm strings.
 190.478 +     */
 190.479 +    public void setAmPmStrings(String[] newAmpms) {
 190.480 +        ampms = Arrays.copyOf(newAmpms, newAmpms.length);
 190.481 +    }
 190.482 +
 190.483 +    /**
 190.484 +     * Gets time zone strings.  Use of this method is discouraged; use
 190.485 +     * {@link java.util.TimeZone#getDisplayName() TimeZone.getDisplayName()}
 190.486 +     * instead.
 190.487 +     * <p>
 190.488 +     * The value returned is a
 190.489 +     * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
 190.490 +     * where <em>m</em> is at least 5.  Each of the <em>n</em> rows is an
 190.491 +     * entry containing the localized names for a single <code>TimeZone</code>.
 190.492 +     * Each such row contains (with <code>i</code> ranging from
 190.493 +     * 0..<em>n</em>-1):
 190.494 +     * <ul>
 190.495 +     * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
 190.496 +     * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
 190.497 +     * time</li>
 190.498 +     * <li><code>zoneStrings[i][2]</code> - short name of zone in
 190.499 +     * standard time</li>
 190.500 +     * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
 190.501 +     * saving time</li>
 190.502 +     * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
 190.503 +     * saving time</li>
 190.504 +     * </ul>
 190.505 +     * The zone ID is <em>not</em> localized; it's one of the valid IDs of
 190.506 +     * the {@link java.util.TimeZone TimeZone} class that are not
 190.507 +     * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
 190.508 +     * All other entries are localized names.  If a zone does not implement
 190.509 +     * daylight saving time, the daylight saving time names should not be used.
 190.510 +     * <p>
 190.511 +     * If {@link #setZoneStrings(String[][]) setZoneStrings} has been called
 190.512 +     * on this <code>DateFormatSymbols</code> instance, then the strings
 190.513 +     * provided by that call are returned. Otherwise, the returned array
 190.514 +     * contains names provided by the Java runtime and by installed
 190.515 +     * {@link java.util.spi.TimeZoneNameProvider TimeZoneNameProvider}
 190.516 +     * implementations.
 190.517 +     *
 190.518 +     * @return the time zone strings.
 190.519 +     * @see #setZoneStrings(String[][])
 190.520 +     */
 190.521 +    public String[][] getZoneStrings() {
 190.522 +        return getZoneStringsImpl(true);
 190.523 +    }
 190.524 +
 190.525 +    /**
 190.526 +     * Sets time zone strings.  The argument must be a
 190.527 +     * two-dimensional array of strings of size <em>n</em> by <em>m</em>,
 190.528 +     * where <em>m</em> is at least 5.  Each of the <em>n</em> rows is an
 190.529 +     * entry containing the localized names for a single <code>TimeZone</code>.
 190.530 +     * Each such row contains (with <code>i</code> ranging from
 190.531 +     * 0..<em>n</em>-1):
 190.532 +     * <ul>
 190.533 +     * <li><code>zoneStrings[i][0]</code> - time zone ID</li>
 190.534 +     * <li><code>zoneStrings[i][1]</code> - long name of zone in standard
 190.535 +     * time</li>
 190.536 +     * <li><code>zoneStrings[i][2]</code> - short name of zone in
 190.537 +     * standard time</li>
 190.538 +     * <li><code>zoneStrings[i][3]</code> - long name of zone in daylight
 190.539 +     * saving time</li>
 190.540 +     * <li><code>zoneStrings[i][4]</code> - short name of zone in daylight
 190.541 +     * saving time</li>
 190.542 +     * </ul>
 190.543 +     * The zone ID is <em>not</em> localized; it's one of the valid IDs of
 190.544 +     * the {@link java.util.TimeZone TimeZone} class that are not
 190.545 +     * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
 190.546 +     * All other entries are localized names.
 190.547 +     *
 190.548 +     * @param newZoneStrings the new time zone strings.
 190.549 +     * @exception IllegalArgumentException if the length of any row in
 190.550 +     *    <code>newZoneStrings</code> is less than 5
 190.551 +     * @exception NullPointerException if <code>newZoneStrings</code> is null
 190.552 +     * @see #getZoneStrings()
 190.553 +     */
 190.554 +    public void setZoneStrings(String[][] newZoneStrings) {
 190.555 +        String[][] aCopy = new String[newZoneStrings.length][];
 190.556 +        for (int i = 0; i < newZoneStrings.length; ++i) {
 190.557 +            int len = newZoneStrings[i].length;
 190.558 +            if (len < 5) {
 190.559 +                throw new IllegalArgumentException();
 190.560 +            }
 190.561 +            aCopy[i] = Arrays.copyOf(newZoneStrings[i], len);
 190.562 +        }
 190.563 +        zoneStrings = aCopy;
 190.564 +        isZoneStringsSet = true;
 190.565 +    }
 190.566 +
 190.567 +    /**
 190.568 +     * Gets localized date-time pattern characters. For example: 'u', 't', etc.
 190.569 +     * @return the localized date-time pattern characters.
 190.570 +     */
 190.571 +    public String getLocalPatternChars() {
 190.572 +        return localPatternChars;
 190.573 +    }
 190.574 +
 190.575 +    /**
 190.576 +     * Sets localized date-time pattern characters. For example: 'u', 't', etc.
 190.577 +     * @param newLocalPatternChars the new localized date-time
 190.578 +     * pattern characters.
 190.579 +     */
 190.580 +    public void setLocalPatternChars(String newLocalPatternChars) {
 190.581 +        // Call toString() to throw an NPE in case the argument is null
 190.582 +        localPatternChars = newLocalPatternChars.toString();
 190.583 +    }
 190.584 +
 190.585 +    /**
 190.586 +     * Overrides Cloneable
 190.587 +     */
 190.588 +    public Object clone()
 190.589 +    {
 190.590 +        try
 190.591 +        {
 190.592 +            DateFormatSymbols other = (DateFormatSymbols)super.clone();
 190.593 +            copyMembers(this, other);
 190.594 +            return other;
 190.595 +        } catch (CloneNotSupportedException e) {
 190.596 +            throw new InternalError();
 190.597 +        }
 190.598 +    }
 190.599 +
 190.600 +    /**
 190.601 +     * Override hashCode.
 190.602 +     * Generates a hash code for the DateFormatSymbols object.
 190.603 +     */
 190.604 +    public int hashCode() {
 190.605 +        int hashcode = 0;
 190.606 +        String[][] zoneStrings = getZoneStringsWrapper();
 190.607 +        for (int index = 0; index < zoneStrings[0].length; ++index)
 190.608 +            hashcode ^= zoneStrings[0][index].hashCode();
 190.609 +        return hashcode;
 190.610 +    }
 190.611 +
 190.612 +    /**
 190.613 +     * Override equals
 190.614 +     */
 190.615 +    public boolean equals(Object obj)
 190.616 +    {
 190.617 +        if (this == obj) return true;
 190.618 +        if (obj == null || getClass() != obj.getClass()) return false;
 190.619 +        DateFormatSymbols that = (DateFormatSymbols) obj;
 190.620 +        return (Arrays.equals(eras, that.eras)
 190.621 +                && Arrays.equals(months, that.months)
 190.622 +                && Arrays.equals(shortMonths, that.shortMonths)
 190.623 +                && Arrays.equals(weekdays, that.weekdays)
 190.624 +                && Arrays.equals(shortWeekdays, that.shortWeekdays)
 190.625 +                && Arrays.equals(ampms, that.ampms)
 190.626 +                && Arrays.deepEquals(getZoneStringsWrapper(), that.getZoneStringsWrapper())
 190.627 +                && ((localPatternChars != null
 190.628 +                  && localPatternChars.equals(that.localPatternChars))
 190.629 +                 || (localPatternChars == null
 190.630 +                  && that.localPatternChars == null)));
 190.631 +    }
 190.632 +
 190.633 +    // =======================privates===============================
 190.634 +
 190.635 +    /**
 190.636 +     * Useful constant for defining time zone offsets.
 190.637 +     */
 190.638 +    static final int millisPerHour = 60*60*1000;
 190.639 +
 190.640 +    /**
 190.641 +     * Cache to hold DateFormatSymbols instances per Locale.
 190.642 +     */
 190.643 +    private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
 190.644 +        = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
 190.645 +
 190.646 +    private void initializeData(Locale desiredLocale) {
 190.647 +        locale = desiredLocale;
 190.648 +
 190.649 +        // Copy values of a cached instance if any.
 190.650 +        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
 190.651 +        DateFormatSymbols dfs;
 190.652 +        if (ref != null && (dfs = ref.get()) != null) {
 190.653 +            copyMembers(dfs, this);
 190.654 +            return;
 190.655 +        }
 190.656 +
 190.657 +        // Initialize the fields from the ResourceBundle for locale.
 190.658 +//        ResourceBundle resource = LocaleData.getDateFormatData(locale);
 190.659 +//
 190.660 +//        eras = resource.getStringArray("Eras");
 190.661 +//        months = resource.getStringArray("MonthNames");
 190.662 +//        shortMonths = resource.getStringArray("MonthAbbreviations");
 190.663 +//        ampms = resource.getStringArray("AmPmMarkers");
 190.664 +//        localPatternChars = resource.getString("DateTimePatternChars");
 190.665 +//
 190.666 +//        // Day of week names are stored in a 1-based array.
 190.667 +//        weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
 190.668 +//        shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
 190.669 +    }
 190.670 +
 190.671 +    private static String[] toOneBasedArray(String[] src) {
 190.672 +        int len = src.length;
 190.673 +        String[] dst = new String[len + 1];
 190.674 +        dst[0] = "";
 190.675 +        for (int i = 0; i < len; i++) {
 190.676 +            dst[i + 1] = src[i];
 190.677 +        }
 190.678 +        return dst;
 190.679 +    }
 190.680 +
 190.681 +    /**
 190.682 +     * Package private: used by SimpleDateFormat
 190.683 +     * Gets the index for the given time zone ID to obtain the time zone
 190.684 +     * strings for formatting. The time zone ID is just for programmatic
 190.685 +     * lookup. NOT LOCALIZED!!!
 190.686 +     * @param ID the given time zone ID.
 190.687 +     * @return the index of the given time zone ID.  Returns -1 if
 190.688 +     * the given time zone ID can't be located in the DateFormatSymbols object.
 190.689 +     * @see java.util.SimpleTimeZone
 190.690 +     */
 190.691 +    final int getZoneIndex(String ID)
 190.692 +    {
 190.693 +        String[][] zoneStrings = getZoneStringsWrapper();
 190.694 +        for (int index=0; index<zoneStrings.length; index++)
 190.695 +        {
 190.696 +            if (ID.equals(zoneStrings[index][0])) return index;
 190.697 +        }
 190.698 +
 190.699 +        return -1;
 190.700 +    }
 190.701 +
 190.702 +    /**
 190.703 +     * Wrapper method to the getZoneStrings(), which is called from inside
 190.704 +     * the java.text package and not to mutate the returned arrays, so that
 190.705 +     * it does not need to create a defensive copy.
 190.706 +     */
 190.707 +    final String[][] getZoneStringsWrapper() {
 190.708 +        if (isSubclassObject()) {
 190.709 +            return getZoneStrings();
 190.710 +        } else {
 190.711 +            return getZoneStringsImpl(false);
 190.712 +        }
 190.713 +    }
 190.714 +
 190.715 +    private final String[][] getZoneStringsImpl(boolean needsCopy) {
 190.716 +        if (zoneStrings == null) {
 190.717 +//            zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
 190.718 +        }
 190.719 +
 190.720 +        if (!needsCopy) {
 190.721 +            return zoneStrings;
 190.722 +        }
 190.723 +
 190.724 +        int len = zoneStrings.length;
 190.725 +        String[][] aCopy = new String[len][];
 190.726 +        for (int i = 0; i < len; i++) {
 190.727 +            aCopy[i] = Arrays.copyOf(zoneStrings[i], zoneStrings[i].length);
 190.728 +        }
 190.729 +        return aCopy;
 190.730 +    }
 190.731 +
 190.732 +    private final boolean isSubclassObject() {
 190.733 +        return !getClass().getName().equals("java.text.DateFormatSymbols");
 190.734 +    }
 190.735 +
 190.736 +    /**
 190.737 +     * Clones all the data members from the source DateFormatSymbols to
 190.738 +     * the target DateFormatSymbols. This is only for subclasses.
 190.739 +     * @param src the source DateFormatSymbols.
 190.740 +     * @param dst the target DateFormatSymbols.
 190.741 +     */
 190.742 +    private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
 190.743 +    {
 190.744 +        dst.eras = Arrays.copyOf(src.eras, src.eras.length);
 190.745 +        dst.months = Arrays.copyOf(src.months, src.months.length);
 190.746 +        dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
 190.747 +        dst.weekdays = Arrays.copyOf(src.weekdays, src.weekdays.length);
 190.748 +        dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length);
 190.749 +        dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length);
 190.750 +        if (src.zoneStrings != null) {
 190.751 +            dst.zoneStrings = src.getZoneStringsImpl(true);
 190.752 +        } else {
 190.753 +            dst.zoneStrings = null;
 190.754 +        }
 190.755 +        dst.localPatternChars = src.localPatternChars;
 190.756 +    }
 190.757 +
 190.758 +    /**
 190.759 +     * Write out the default serializable data, after ensuring the
 190.760 +     * <code>zoneStrings</code> field is initialized in order to make
 190.761 +     * sure the backward compatibility.
 190.762 +     *
 190.763 +     * @since 1.6
 190.764 +    private void writeObject(ObjectOutputStream stream) throws IOException {
 190.765 +        if (zoneStrings == null) {
 190.766 +            zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
 190.767 +        }
 190.768 +        stream.defaultWriteObject();
 190.769 +    }
 190.770 +
 190.771 +    /**
 190.772 +     * Obtains a DateFormatSymbols instance from a DateFormatSymbolsProvider
 190.773 +     * implementation.
 190.774 +    private static class DateFormatSymbolsGetter
 190.775 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatSymbolsProvider,
 190.776 +                                                                   DateFormatSymbols> {
 190.777 +        private static final DateFormatSymbolsGetter INSTANCE =
 190.778 +            new DateFormatSymbolsGetter();
 190.779 +
 190.780 +        public DateFormatSymbols getObject(DateFormatSymbolsProvider dateFormatSymbolsProvider,
 190.781 +                                Locale locale,
 190.782 +                                String key,
 190.783 +                                Object... params) {
 190.784 +            assert params.length == 0;
 190.785 +            return dateFormatSymbolsProvider.getInstance(locale);
 190.786 +        }
 190.787 +    }
 190.788 +     */
 190.789 +}
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/rt/emul/compact/src/main/java/java/text/DecimalFormat.java	Wed Apr 30 15:04:10 2014 +0200
   191.3 @@ -0,0 +1,3277 @@
   191.4 +/*
   191.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   191.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   191.7 + *
   191.8 + * This code is free software; you can redistribute it and/or modify it
   191.9 + * under the terms of the GNU General Public License version 2 only, as
  191.10 + * published by the Free Software Foundation.  Oracle designates this
  191.11 + * particular file as subject to the "Classpath" exception as provided
  191.12 + * by Oracle in the LICENSE file that accompanied this code.
  191.13 + *
  191.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  191.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  191.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  191.17 + * version 2 for more details (a copy is included in the LICENSE file that
  191.18 + * accompanied this code).
  191.19 + *
  191.20 + * You should have received a copy of the GNU General Public License version
  191.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  191.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  191.23 + *
  191.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  191.25 + * or visit www.oracle.com if you need additional information or have any
  191.26 + * questions.
  191.27 + */
  191.28 +
  191.29 +/*
  191.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  191.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  191.32 + *
  191.33 + *   The original version of this source code and documentation is copyrighted
  191.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  191.35 + * materials are provided under terms of a License Agreement between Taligent
  191.36 + * and Sun. This technology is protected by multiple US and International
  191.37 + * patents. This notice and attribution to Taligent may not be removed.
  191.38 + *   Taligent is a registered trademark of Taligent, Inc.
  191.39 + *
  191.40 + */
  191.41 +
  191.42 +package java.text;
  191.43 +
  191.44 +import java.io.InvalidObjectException;
  191.45 +import java.io.IOException;
  191.46 +import java.io.ObjectInputStream;
  191.47 +import java.math.BigDecimal;
  191.48 +import java.math.BigInteger;
  191.49 +import java.math.RoundingMode;
  191.50 +import java.util.ArrayList;
  191.51 +import java.util.Currency;
  191.52 +import java.util.Locale;
  191.53 +import java.util.ResourceBundle;
  191.54 +import java.util.concurrent.ConcurrentHashMap;
  191.55 +import java.util.concurrent.ConcurrentMap;
  191.56 +import java.util.concurrent.atomic.AtomicInteger;
  191.57 +import java.util.concurrent.atomic.AtomicLong;
  191.58 +
  191.59 +/**
  191.60 + * <code>DecimalFormat</code> is a concrete subclass of
  191.61 + * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
  191.62 + * features designed to make it possible to parse and format numbers in any
  191.63 + * locale, including support for Western, Arabic, and Indic digits.  It also
  191.64 + * supports different kinds of numbers, including integers (123), fixed-point
  191.65 + * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
  191.66 + * currency amounts ($123).  All of these can be localized.
  191.67 + *
  191.68 + * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
  191.69 + * default locale, call one of <code>NumberFormat</code>'s factory methods, such
  191.70 + * as <code>getInstance()</code>.  In general, do not call the
  191.71 + * <code>DecimalFormat</code> constructors directly, since the
  191.72 + * <code>NumberFormat</code> factory methods may return subclasses other than
  191.73 + * <code>DecimalFormat</code>. If you need to customize the format object, do
  191.74 + * something like this:
  191.75 + *
  191.76 + * <blockquote><pre>
  191.77 + * NumberFormat f = NumberFormat.getInstance(loc);
  191.78 + * if (f instanceof DecimalFormat) {
  191.79 + *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
  191.80 + * }
  191.81 + * </pre></blockquote>
  191.82 + *
  191.83 + * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
  191.84 + * <em>symbols</em>.  The pattern may be set directly using
  191.85 + * <code>applyPattern()</code>, or indirectly using the API methods.  The
  191.86 + * symbols are stored in a <code>DecimalFormatSymbols</code> object.  When using
  191.87 + * the <code>NumberFormat</code> factory methods, the pattern and symbols are
  191.88 + * read from localized <code>ResourceBundle</code>s.
  191.89 + *
  191.90 + * <h4>Patterns</h4>
  191.91 + *
  191.92 + * <code>DecimalFormat</code> patterns have the following syntax:
  191.93 + * <blockquote><pre>
  191.94 + * <i>Pattern:</i>
  191.95 + *         <i>PositivePattern</i>
  191.96 + *         <i>PositivePattern</i> ; <i>NegativePattern</i>
  191.97 + * <i>PositivePattern:</i>
  191.98 + *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
  191.99 + * <i>NegativePattern:</i>
 191.100 + *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
 191.101 + * <i>Prefix:</i>
 191.102 + *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
 191.103 + * <i>Suffix:</i>
 191.104 + *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
 191.105 + * <i>Number:</i>
 191.106 + *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
 191.107 + *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
 191.108 + * <i>Integer:</i>
 191.109 + *         <i>MinimumInteger</i>
 191.110 + *         #
 191.111 + *         # <i>Integer</i>
 191.112 + *         # , <i>Integer</i>
 191.113 + * <i>MinimumInteger:</i>
 191.114 + *         0
 191.115 + *         0 <i>MinimumInteger</i>
 191.116 + *         0 , <i>MinimumInteger</i>
 191.117 + * <i>Fraction:</i>
 191.118 + *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
 191.119 + * <i>MinimumFraction:</i>
 191.120 + *         0 <i>MinimumFraction<sub>opt</sub></i>
 191.121 + * <i>OptionalFraction:</i>
 191.122 + *         # <i>OptionalFraction<sub>opt</sub></i>
 191.123 + * <i>Exponent:</i>
 191.124 + *         E <i>MinimumExponent</i>
 191.125 + * <i>MinimumExponent:</i>
 191.126 + *         0 <i>MinimumExponent<sub>opt</sub></i>
 191.127 + * </pre></blockquote>
 191.128 + *
 191.129 + * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
 191.130 + * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>.  Each
 191.131 + * subpattern has a prefix, numeric part, and suffix. The negative subpattern
 191.132 + * is optional; if absent, then the positive subpattern prefixed with the
 191.133 + * localized minus sign (<code>'-'</code> in most locales) is used as the
 191.134 + * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
 191.135 + * <code>"0.00;-0.00"</code>.  If there is an explicit negative subpattern, it
 191.136 + * serves only to specify the negative prefix and suffix; the number of digits,
 191.137 + * minimal digits, and other characteristics are all the same as the positive
 191.138 + * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
 191.139 + * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
 191.140 + *
 191.141 + * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
 191.142 + * thousands separators, decimal separators, etc. may be set to arbitrary
 191.143 + * values, and they will appear properly during formatting.  However, care must
 191.144 + * be taken that the symbols and strings do not conflict, or parsing will be
 191.145 + * unreliable.  For example, either the positive and negative prefixes or the
 191.146 + * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
 191.147 + * to distinguish positive from negative values.  (If they are identical, then
 191.148 + * <code>DecimalFormat</code> will behave as if no negative subpattern was
 191.149 + * specified.)  Another example is that the decimal separator and thousands
 191.150 + * separator should be distinct characters, or parsing will be impossible.
 191.151 + *
 191.152 + * <p>The grouping separator is commonly used for thousands, but in some
 191.153 + * countries it separates ten-thousands. The grouping size is a constant number
 191.154 + * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
 191.155 + * 1,0000,0000.  If you supply a pattern with multiple grouping characters, the
 191.156 + * interval between the last one and the end of the integer is the one that is
 191.157 + * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
 191.158 + * <code>"##,####,####"</code>.
 191.159 + *
 191.160 + * <h4>Special Pattern Characters</h4>
 191.161 + *
 191.162 + * <p>Many characters in a pattern are taken literally; they are matched during
 191.163 + * parsing and output unchanged during formatting.  Special characters, on the
 191.164 + * other hand, stand for other characters, strings, or classes of characters.
 191.165 + * They must be quoted, unless noted otherwise, if they are to appear in the
 191.166 + * prefix or suffix as literals.
 191.167 + *
 191.168 + * <p>The characters listed here are used in non-localized patterns.  Localized
 191.169 + * patterns use the corresponding characters taken from this formatter's
 191.170 + * <code>DecimalFormatSymbols</code> object instead, and these characters lose
 191.171 + * their special status.  Two exceptions are the currency sign and quote, which
 191.172 + * are not localized.
 191.173 + *
 191.174 + * <blockquote>
 191.175 + * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
 191.176 + *  location, localized, and meaning.">
 191.177 + *     <tr bgcolor="#ccccff">
 191.178 + *          <th align=left>Symbol
 191.179 + *          <th align=left>Location
 191.180 + *          <th align=left>Localized?
 191.181 + *          <th align=left>Meaning
 191.182 + *     <tr valign=top>
 191.183 + *          <td><code>0</code>
 191.184 + *          <td>Number
 191.185 + *          <td>Yes
 191.186 + *          <td>Digit
 191.187 + *     <tr valign=top bgcolor="#eeeeff">
 191.188 + *          <td><code>#</code>
 191.189 + *          <td>Number
 191.190 + *          <td>Yes
 191.191 + *          <td>Digit, zero shows as absent
 191.192 + *     <tr valign=top>
 191.193 + *          <td><code>.</code>
 191.194 + *          <td>Number
 191.195 + *          <td>Yes
 191.196 + *          <td>Decimal separator or monetary decimal separator
 191.197 + *     <tr valign=top bgcolor="#eeeeff">
 191.198 + *          <td><code>-</code>
 191.199 + *          <td>Number
 191.200 + *          <td>Yes
 191.201 + *          <td>Minus sign
 191.202 + *     <tr valign=top>
 191.203 + *          <td><code>,</code>
 191.204 + *          <td>Number
 191.205 + *          <td>Yes
 191.206 + *          <td>Grouping separator
 191.207 + *     <tr valign=top bgcolor="#eeeeff">
 191.208 + *          <td><code>E</code>
 191.209 + *          <td>Number
 191.210 + *          <td>Yes
 191.211 + *          <td>Separates mantissa and exponent in scientific notation.
 191.212 + *              <em>Need not be quoted in prefix or suffix.</em>
 191.213 + *     <tr valign=top>
 191.214 + *          <td><code>;</code>
 191.215 + *          <td>Subpattern boundary
 191.216 + *          <td>Yes
 191.217 + *          <td>Separates positive and negative subpatterns
 191.218 + *     <tr valign=top bgcolor="#eeeeff">
 191.219 + *          <td><code>%</code>
 191.220 + *          <td>Prefix or suffix
 191.221 + *          <td>Yes
 191.222 + *          <td>Multiply by 100 and show as percentage
 191.223 + *     <tr valign=top>
 191.224 + *          <td><code>&#92;u2030</code>
 191.225 + *          <td>Prefix or suffix
 191.226 + *          <td>Yes
 191.227 + *          <td>Multiply by 1000 and show as per mille value
 191.228 + *     <tr valign=top bgcolor="#eeeeff">
 191.229 + *          <td><code>&#164;</code> (<code>&#92;u00A4</code>)
 191.230 + *          <td>Prefix or suffix
 191.231 + *          <td>No
 191.232 + *          <td>Currency sign, replaced by currency symbol.  If
 191.233 + *              doubled, replaced by international currency symbol.
 191.234 + *              If present in a pattern, the monetary decimal separator
 191.235 + *              is used instead of the decimal separator.
 191.236 + *     <tr valign=top>
 191.237 + *          <td><code>'</code>
 191.238 + *          <td>Prefix or suffix
 191.239 + *          <td>No
 191.240 + *          <td>Used to quote special characters in a prefix or suffix,
 191.241 + *              for example, <code>"'#'#"</code> formats 123 to
 191.242 + *              <code>"#123"</code>.  To create a single quote
 191.243 + *              itself, use two in a row: <code>"# o''clock"</code>.
 191.244 + * </table>
 191.245 + * </blockquote>
 191.246 + *
 191.247 + * <h4>Scientific Notation</h4>
 191.248 + *
 191.249 + * <p>Numbers in scientific notation are expressed as the product of a mantissa
 191.250 + * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3.  The
 191.251 + * mantissa is often in the range 1.0 <= x < 10.0, but it need not be.
 191.252 + * <code>DecimalFormat</code> can be instructed to format and parse scientific
 191.253 + * notation <em>only via a pattern</em>; there is currently no factory method
 191.254 + * that creates a scientific notation format.  In a pattern, the exponent
 191.255 + * character immediately followed by one or more digit characters indicates
 191.256 + * scientific notation.  Example: <code>"0.###E0"</code> formats the number
 191.257 + * 1234 as <code>"1.234E3"</code>.
 191.258 + *
 191.259 + * <ul>
 191.260 + * <li>The number of digit characters after the exponent character gives the
 191.261 + * minimum exponent digit count.  There is no maximum.  Negative exponents are
 191.262 + * formatted using the localized minus sign, <em>not</em> the prefix and suffix
 191.263 + * from the pattern.  This allows patterns such as <code>"0.###E0 m/s"</code>.
 191.264 + *
 191.265 + * <li>The minimum and maximum number of integer digits are interpreted
 191.266 + * together:
 191.267 + *
 191.268 + * <ul>
 191.269 + * <li>If the maximum number of integer digits is greater than their minimum number
 191.270 + * and greater than 1, it forces the exponent to be a multiple of the maximum
 191.271 + * number of integer digits, and the minimum number of integer digits to be
 191.272 + * interpreted as 1.  The most common use of this is to generate
 191.273 + * <em>engineering notation</em>, in which the exponent is a multiple of three,
 191.274 + * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
 191.275 + * formats to <code>"12.345E3"</code>, and 123456 formats to
 191.276 + * <code>"123.456E3"</code>.
 191.277 + *
 191.278 + * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
 191.279 + * exponent.  Example: 0.00123 formatted with <code>"00.###E0"</code> yields
 191.280 + * <code>"12.3E-4"</code>.
 191.281 + * </ul>
 191.282 + *
 191.283 + * <li>The number of significant digits in the mantissa is the sum of the
 191.284 + * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
 191.285 + * unaffected by the maximum integer digits.  For example, 12345 formatted with
 191.286 + * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
 191.287 + * the significant digits count to zero.  The number of significant digits
 191.288 + * does not affect parsing.
 191.289 + *
 191.290 + * <li>Exponential patterns may not contain grouping separators.
 191.291 + * </ul>
 191.292 + *
 191.293 + * <h4>Rounding</h4>
 191.294 + *
 191.295 + * <code>DecimalFormat</code> provides rounding modes defined in
 191.296 + * {@link java.math.RoundingMode} for formatting.  By default, it uses
 191.297 + * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
 191.298 + *
 191.299 + * <h4>Digits</h4>
 191.300 + *
 191.301 + * For formatting, <code>DecimalFormat</code> uses the ten consecutive
 191.302 + * characters starting with the localized zero digit defined in the
 191.303 + * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
 191.304 + * digits as well as all Unicode decimal digits, as defined by
 191.305 + * {@link Character#digit Character.digit}, are recognized.
 191.306 + *
 191.307 + * <h4>Special Values</h4>
 191.308 + *
 191.309 + * <p><code>NaN</code> is formatted as a string, which typically has a single character
 191.310 + * <code>&#92;uFFFD</code>.  This string is determined by the
 191.311 + * <code>DecimalFormatSymbols</code> object.  This is the only value for which
 191.312 + * the prefixes and suffixes are not used.
 191.313 + *
 191.314 + * <p>Infinity is formatted as a string, which typically has a single character
 191.315 + * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
 191.316 + * applied.  The infinity string is determined by the
 191.317 + * <code>DecimalFormatSymbols</code> object.
 191.318 + *
 191.319 + * <p>Negative zero (<code>"-0"</code>) parses to
 191.320 + * <ul>
 191.321 + * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
 191.322 + * true,
 191.323 + * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
 191.324 + *     and <code>isParseIntegerOnly()</code> is true,
 191.325 + * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
 191.326 + * and <code>isParseIntegerOnly()</code> are false.
 191.327 + * </ul>
 191.328 + *
 191.329 + * <h4><a name="synchronization">Synchronization</a></h4>
 191.330 + *
 191.331 + * <p>
 191.332 + * Decimal formats are generally not synchronized.
 191.333 + * It is recommended to create separate format instances for each thread.
 191.334 + * If multiple threads access a format concurrently, it must be synchronized
 191.335 + * externally.
 191.336 + *
 191.337 + * <h4>Example</h4>
 191.338 + *
 191.339 + * <blockquote><pre>
 191.340 + * <strong>// Print out a number using the localized number, integer, currency,
 191.341 + * // and percent format for each locale</strong>
 191.342 + * Locale[] locales = NumberFormat.getAvailableLocales();
 191.343 + * double myNumber = -1234.56;
 191.344 + * NumberFormat form;
 191.345 + * for (int j=0; j<4; ++j) {
 191.346 + *     System.out.println("FORMAT");
 191.347 + *     for (int i = 0; i < locales.length; ++i) {
 191.348 + *         if (locales[i].getCountry().length() == 0) {
 191.349 + *            continue; // Skip language-only locales
 191.350 + *         }
 191.351 + *         System.out.print(locales[i].getDisplayName());
 191.352 + *         switch (j) {
 191.353 + *         case 0:
 191.354 + *             form = NumberFormat.getInstance(locales[i]); break;
 191.355 + *         case 1:
 191.356 + *             form = NumberFormat.getIntegerInstance(locales[i]); break;
 191.357 + *         case 2:
 191.358 + *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
 191.359 + *         default:
 191.360 + *             form = NumberFormat.getPercentInstance(locales[i]); break;
 191.361 + *         }
 191.362 + *         if (form instanceof DecimalFormat) {
 191.363 + *             System.out.print(": " + ((DecimalFormat) form).toPattern());
 191.364 + *         }
 191.365 + *         System.out.print(" -> " + form.format(myNumber));
 191.366 + *         try {
 191.367 + *             System.out.println(" -> " + form.parse(form.format(myNumber)));
 191.368 + *         } catch (ParseException e) {}
 191.369 + *     }
 191.370 + * }
 191.371 + * </pre></blockquote>
 191.372 + *
 191.373 + * @see          <a href="http://java.sun.com/docs/books/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
 191.374 + * @see          NumberFormat
 191.375 + * @see          DecimalFormatSymbols
 191.376 + * @see          ParsePosition
 191.377 + * @author       Mark Davis
 191.378 + * @author       Alan Liu
 191.379 + */
 191.380 +public class DecimalFormat extends NumberFormat {
 191.381 +
 191.382 +    /**
 191.383 +     * Creates a DecimalFormat using the default pattern and symbols
 191.384 +     * for the default locale. This is a convenient way to obtain a
 191.385 +     * DecimalFormat when internationalization is not the main concern.
 191.386 +     * <p>
 191.387 +     * To obtain standard formats for a given locale, use the factory methods
 191.388 +     * on NumberFormat such as getNumberInstance. These factories will
 191.389 +     * return the most appropriate sub-class of NumberFormat for a given
 191.390 +     * locale.
 191.391 +     *
 191.392 +     * @see java.text.NumberFormat#getInstance
 191.393 +     * @see java.text.NumberFormat#getNumberInstance
 191.394 +     * @see java.text.NumberFormat#getCurrencyInstance
 191.395 +     * @see java.text.NumberFormat#getPercentInstance
 191.396 +     */
 191.397 +    public DecimalFormat() {
 191.398 +        Locale def = Locale.getDefault(Locale.Category.FORMAT);
 191.399 +        // try to get the pattern from the cache
 191.400 +        String pattern = cachedLocaleData.get(def);
 191.401 +        if (pattern == null) {  /* cache miss */
 191.402 +            // Get the pattern for the default locale.
 191.403 +//            ResourceBundle rb = LocaleData.getNumberFormatData(def);
 191.404 +//            String[] all = rb.getStringArray("NumberPatterns");
 191.405 +//            pattern = all[0];
 191.406 +//            /* update cache */
 191.407 +//            cachedLocaleData.putIfAbsent(def, pattern);
 191.408 +        }
 191.409 +
 191.410 +        // Always applyPattern after the symbols are set
 191.411 +        this.symbols = new DecimalFormatSymbols(def);
 191.412 +        applyPattern(pattern, false);
 191.413 +    }
 191.414 +
 191.415 +
 191.416 +    /**
 191.417 +     * Creates a DecimalFormat using the given pattern and the symbols
 191.418 +     * for the default locale. This is a convenient way to obtain a
 191.419 +     * DecimalFormat when internationalization is not the main concern.
 191.420 +     * <p>
 191.421 +     * To obtain standard formats for a given locale, use the factory methods
 191.422 +     * on NumberFormat such as getNumberInstance. These factories will
 191.423 +     * return the most appropriate sub-class of NumberFormat for a given
 191.424 +     * locale.
 191.425 +     *
 191.426 +     * @param pattern A non-localized pattern string.
 191.427 +     * @exception NullPointerException if <code>pattern</code> is null
 191.428 +     * @exception IllegalArgumentException if the given pattern is invalid.
 191.429 +     * @see java.text.NumberFormat#getInstance
 191.430 +     * @see java.text.NumberFormat#getNumberInstance
 191.431 +     * @see java.text.NumberFormat#getCurrencyInstance
 191.432 +     * @see java.text.NumberFormat#getPercentInstance
 191.433 +     */
 191.434 +    public DecimalFormat(String pattern) {
 191.435 +        // Always applyPattern after the symbols are set
 191.436 +        this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
 191.437 +        applyPattern(pattern, false);
 191.438 +    }
 191.439 +
 191.440 +
 191.441 +    /**
 191.442 +     * Creates a DecimalFormat using the given pattern and symbols.
 191.443 +     * Use this constructor when you need to completely customize the
 191.444 +     * behavior of the format.
 191.445 +     * <p>
 191.446 +     * To obtain standard formats for a given
 191.447 +     * locale, use the factory methods on NumberFormat such as
 191.448 +     * getInstance or getCurrencyInstance. If you need only minor adjustments
 191.449 +     * to a standard format, you can modify the format returned by
 191.450 +     * a NumberFormat factory method.
 191.451 +     *
 191.452 +     * @param pattern a non-localized pattern string
 191.453 +     * @param symbols the set of symbols to be used
 191.454 +     * @exception NullPointerException if any of the given arguments is null
 191.455 +     * @exception IllegalArgumentException if the given pattern is invalid
 191.456 +     * @see java.text.NumberFormat#getInstance
 191.457 +     * @see java.text.NumberFormat#getNumberInstance
 191.458 +     * @see java.text.NumberFormat#getCurrencyInstance
 191.459 +     * @see java.text.NumberFormat#getPercentInstance
 191.460 +     * @see java.text.DecimalFormatSymbols
 191.461 +     */
 191.462 +    public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
 191.463 +        // Always applyPattern after the symbols are set
 191.464 +        this.symbols = (DecimalFormatSymbols)symbols.clone();
 191.465 +        applyPattern(pattern, false);
 191.466 +    }
 191.467 +
 191.468 +
 191.469 +    // Overrides
 191.470 +    /**
 191.471 +     * Formats a number and appends the resulting text to the given string
 191.472 +     * buffer.
 191.473 +     * The number can be of any subclass of {@link java.lang.Number}.
 191.474 +     * <p>
 191.475 +     * This implementation uses the maximum precision permitted.
 191.476 +     * @param number     the number to format
 191.477 +     * @param toAppendTo the <code>StringBuffer</code> to which the formatted
 191.478 +     *                   text is to be appended
 191.479 +     * @param pos        On input: an alignment field, if desired.
 191.480 +     *                   On output: the offsets of the alignment field.
 191.481 +     * @return           the value passed in as <code>toAppendTo</code>
 191.482 +     * @exception        IllegalArgumentException if <code>number</code> is
 191.483 +     *                   null or not an instance of <code>Number</code>.
 191.484 +     * @exception        NullPointerException if <code>toAppendTo</code> or
 191.485 +     *                   <code>pos</code> is null
 191.486 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.487 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.488 +     * @see              java.text.FieldPosition
 191.489 +     */
 191.490 +    public final StringBuffer format(Object number,
 191.491 +                                     StringBuffer toAppendTo,
 191.492 +                                     FieldPosition pos) {
 191.493 +        if (number instanceof Long || number instanceof Integer ||
 191.494 +                   number instanceof Short || number instanceof Byte ||
 191.495 +                   number instanceof AtomicInteger ||
 191.496 +                   number instanceof AtomicLong ||
 191.497 +                   (number instanceof BigInteger &&
 191.498 +                    ((BigInteger)number).bitLength () < 64)) {
 191.499 +            return format(((Number)number).longValue(), toAppendTo, pos);
 191.500 +        } else if (number instanceof BigDecimal) {
 191.501 +            return format((BigDecimal)number, toAppendTo, pos);
 191.502 +        } else if (number instanceof BigInteger) {
 191.503 +            return format((BigInteger)number, toAppendTo, pos);
 191.504 +        } else if (number instanceof Number) {
 191.505 +            return format(((Number)number).doubleValue(), toAppendTo, pos);
 191.506 +        } else {
 191.507 +            throw new IllegalArgumentException("Cannot format given Object as a Number");
 191.508 +        }
 191.509 +    }
 191.510 +
 191.511 +    /**
 191.512 +     * Formats a double to produce a string.
 191.513 +     * @param number    The double to format
 191.514 +     * @param result    where the text is to be appended
 191.515 +     * @param fieldPosition    On input: an alignment field, if desired.
 191.516 +     * On output: the offsets of the alignment field.
 191.517 +     * @exception ArithmeticException if rounding is needed with rounding
 191.518 +     *            mode being set to RoundingMode.UNNECESSARY
 191.519 +     * @return The formatted number string
 191.520 +     * @see java.text.FieldPosition
 191.521 +     */
 191.522 +    public StringBuffer format(double number, StringBuffer result,
 191.523 +                               FieldPosition fieldPosition) {
 191.524 +        fieldPosition.setBeginIndex(0);
 191.525 +        fieldPosition.setEndIndex(0);
 191.526 +
 191.527 +        return format(number, result, fieldPosition.getFieldDelegate());
 191.528 +    }
 191.529 +
 191.530 +    /**
 191.531 +     * Formats a double to produce a string.
 191.532 +     * @param number    The double to format
 191.533 +     * @param result    where the text is to be appended
 191.534 +     * @param delegate notified of locations of sub fields
 191.535 +     * @exception       ArithmeticException if rounding is needed with rounding
 191.536 +     *                  mode being set to RoundingMode.UNNECESSARY
 191.537 +     * @return The formatted number string
 191.538 +     */
 191.539 +    private StringBuffer format(double number, StringBuffer result,
 191.540 +                                FieldDelegate delegate) {
 191.541 +        if (Double.isNaN(number) ||
 191.542 +           (Double.isInfinite(number) && multiplier == 0)) {
 191.543 +            int iFieldStart = result.length();
 191.544 +            result.append(symbols.getNaN());
 191.545 +            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
 191.546 +                               iFieldStart, result.length(), result);
 191.547 +            return result;
 191.548 +        }
 191.549 +
 191.550 +        /* Detecting whether a double is negative is easy with the exception of
 191.551 +         * the value -0.0.  This is a double which has a zero mantissa (and
 191.552 +         * exponent), but a negative sign bit.  It is semantically distinct from
 191.553 +         * a zero with a positive sign bit, and this distinction is important
 191.554 +         * to certain kinds of computations.  However, it's a little tricky to
 191.555 +         * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0).  How then, you may
 191.556 +         * ask, does it behave distinctly from +0.0?  Well, 1/(-0.0) ==
 191.557 +         * -Infinity.  Proper detection of -0.0 is needed to deal with the
 191.558 +         * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
 191.559 +         */
 191.560 +        boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);
 191.561 +
 191.562 +        if (multiplier != 1) {
 191.563 +            number *= multiplier;
 191.564 +        }
 191.565 +
 191.566 +        if (Double.isInfinite(number)) {
 191.567 +            if (isNegative) {
 191.568 +                append(result, negativePrefix, delegate,
 191.569 +                       getNegativePrefixFieldPositions(), Field.SIGN);
 191.570 +            } else {
 191.571 +                append(result, positivePrefix, delegate,
 191.572 +                       getPositivePrefixFieldPositions(), Field.SIGN);
 191.573 +            }
 191.574 +
 191.575 +            int iFieldStart = result.length();
 191.576 +            result.append(symbols.getInfinity());
 191.577 +            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
 191.578 +                               iFieldStart, result.length(), result);
 191.579 +
 191.580 +            if (isNegative) {
 191.581 +                append(result, negativeSuffix, delegate,
 191.582 +                       getNegativeSuffixFieldPositions(), Field.SIGN);
 191.583 +            } else {
 191.584 +                append(result, positiveSuffix, delegate,
 191.585 +                       getPositiveSuffixFieldPositions(), Field.SIGN);
 191.586 +            }
 191.587 +
 191.588 +            return result;
 191.589 +        }
 191.590 +
 191.591 +        if (isNegative) {
 191.592 +            number = -number;
 191.593 +        }
 191.594 +
 191.595 +        // at this point we are guaranteed a nonnegative finite number.
 191.596 +        assert(number >= 0 && !Double.isInfinite(number));
 191.597 +
 191.598 +        synchronized(digitList) {
 191.599 +            int maxIntDigits = super.getMaximumIntegerDigits();
 191.600 +            int minIntDigits = super.getMinimumIntegerDigits();
 191.601 +            int maxFraDigits = super.getMaximumFractionDigits();
 191.602 +            int minFraDigits = super.getMinimumFractionDigits();
 191.603 +
 191.604 +            digitList.set(isNegative, number, useExponentialNotation ?
 191.605 +                          maxIntDigits + maxFraDigits : maxFraDigits,
 191.606 +                          !useExponentialNotation);
 191.607 +            return subformat(result, delegate, isNegative, false,
 191.608 +                       maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
 191.609 +        }
 191.610 +    }
 191.611 +
 191.612 +    /**
 191.613 +     * Format a long to produce a string.
 191.614 +     * @param number    The long to format
 191.615 +     * @param result    where the text is to be appended
 191.616 +     * @param fieldPosition    On input: an alignment field, if desired.
 191.617 +     * On output: the offsets of the alignment field.
 191.618 +     * @exception       ArithmeticException if rounding is needed with rounding
 191.619 +     *                  mode being set to RoundingMode.UNNECESSARY
 191.620 +     * @return The formatted number string
 191.621 +     * @see java.text.FieldPosition
 191.622 +     */
 191.623 +    public StringBuffer format(long number, StringBuffer result,
 191.624 +                               FieldPosition fieldPosition) {
 191.625 +        fieldPosition.setBeginIndex(0);
 191.626 +        fieldPosition.setEndIndex(0);
 191.627 +
 191.628 +        return format(number, result, fieldPosition.getFieldDelegate());
 191.629 +    }
 191.630 +
 191.631 +    /**
 191.632 +     * Format a long to produce a string.
 191.633 +     * @param number    The long to format
 191.634 +     * @param result    where the text is to be appended
 191.635 +     * @param delegate notified of locations of sub fields
 191.636 +     * @return The formatted number string
 191.637 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.638 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.639 +     * @see java.text.FieldPosition
 191.640 +     */
 191.641 +    private StringBuffer format(long number, StringBuffer result,
 191.642 +                               FieldDelegate delegate) {
 191.643 +        boolean isNegative = (number < 0);
 191.644 +        if (isNegative) {
 191.645 +            number = -number;
 191.646 +        }
 191.647 +
 191.648 +        // In general, long values always represent real finite numbers, so
 191.649 +        // we don't have to check for +/- Infinity or NaN.  However, there
 191.650 +        // is one case we have to be careful of:  The multiplier can push
 191.651 +        // a number near MIN_VALUE or MAX_VALUE outside the legal range.  We
 191.652 +        // check for this before multiplying, and if it happens we use
 191.653 +        // BigInteger instead.
 191.654 +        boolean useBigInteger = false;
 191.655 +        if (number < 0) { // This can only happen if number == Long.MIN_VALUE.
 191.656 +            if (multiplier != 0) {
 191.657 +                useBigInteger = true;
 191.658 +            }
 191.659 +        } else if (multiplier != 1 && multiplier != 0) {
 191.660 +            long cutoff = Long.MAX_VALUE / multiplier;
 191.661 +            if (cutoff < 0) {
 191.662 +                cutoff = -cutoff;
 191.663 +            }
 191.664 +            useBigInteger = (number > cutoff);
 191.665 +        }
 191.666 +
 191.667 +        if (useBigInteger) {
 191.668 +            if (isNegative) {
 191.669 +                number = -number;
 191.670 +            }
 191.671 +            BigInteger bigIntegerValue = BigInteger.valueOf(number);
 191.672 +            return format(bigIntegerValue, result, delegate, true);
 191.673 +        }
 191.674 +
 191.675 +        number *= multiplier;
 191.676 +        if (number == 0) {
 191.677 +            isNegative = false;
 191.678 +        } else {
 191.679 +            if (multiplier < 0) {
 191.680 +                number = -number;
 191.681 +                isNegative = !isNegative;
 191.682 +            }
 191.683 +        }
 191.684 +
 191.685 +        synchronized(digitList) {
 191.686 +            int maxIntDigits = super.getMaximumIntegerDigits();
 191.687 +            int minIntDigits = super.getMinimumIntegerDigits();
 191.688 +            int maxFraDigits = super.getMaximumFractionDigits();
 191.689 +            int minFraDigits = super.getMinimumFractionDigits();
 191.690 +
 191.691 +            digitList.set(isNegative, number,
 191.692 +                     useExponentialNotation ? maxIntDigits + maxFraDigits : 0);
 191.693 +
 191.694 +            return subformat(result, delegate, isNegative, true,
 191.695 +                       maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
 191.696 +        }
 191.697 +    }
 191.698 +
 191.699 +    /**
 191.700 +     * Formats a BigDecimal to produce a string.
 191.701 +     * @param number    The BigDecimal to format
 191.702 +     * @param result    where the text is to be appended
 191.703 +     * @param fieldPosition    On input: an alignment field, if desired.
 191.704 +     * On output: the offsets of the alignment field.
 191.705 +     * @return The formatted number string
 191.706 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.707 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.708 +     * @see java.text.FieldPosition
 191.709 +     */
 191.710 +    private StringBuffer format(BigDecimal number, StringBuffer result,
 191.711 +                                FieldPosition fieldPosition) {
 191.712 +        fieldPosition.setBeginIndex(0);
 191.713 +        fieldPosition.setEndIndex(0);
 191.714 +        return format(number, result, fieldPosition.getFieldDelegate());
 191.715 +    }
 191.716 +
 191.717 +    /**
 191.718 +     * Formats a BigDecimal to produce a string.
 191.719 +     * @param number    The BigDecimal to format
 191.720 +     * @param result    where the text is to be appended
 191.721 +     * @param delegate notified of locations of sub fields
 191.722 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.723 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.724 +     * @return The formatted number string
 191.725 +     */
 191.726 +    private StringBuffer format(BigDecimal number, StringBuffer result,
 191.727 +                                FieldDelegate delegate) {
 191.728 +        if (multiplier != 1) {
 191.729 +            number = number.multiply(getBigDecimalMultiplier());
 191.730 +        }
 191.731 +        boolean isNegative = number.signum() == -1;
 191.732 +        if (isNegative) {
 191.733 +            number = number.negate();
 191.734 +        }
 191.735 +
 191.736 +        synchronized(digitList) {
 191.737 +            int maxIntDigits = getMaximumIntegerDigits();
 191.738 +            int minIntDigits = getMinimumIntegerDigits();
 191.739 +            int maxFraDigits = getMaximumFractionDigits();
 191.740 +            int minFraDigits = getMinimumFractionDigits();
 191.741 +            int maximumDigits = maxIntDigits + maxFraDigits;
 191.742 +
 191.743 +            digitList.set(isNegative, number, useExponentialNotation ?
 191.744 +                ((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :
 191.745 +                maxFraDigits, !useExponentialNotation);
 191.746 +
 191.747 +            return subformat(result, delegate, isNegative, false,
 191.748 +                maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
 191.749 +        }
 191.750 +    }
 191.751 +
 191.752 +    /**
 191.753 +     * Format a BigInteger to produce a string.
 191.754 +     * @param number    The BigInteger to format
 191.755 +     * @param result    where the text is to be appended
 191.756 +     * @param fieldPosition    On input: an alignment field, if desired.
 191.757 +     * On output: the offsets of the alignment field.
 191.758 +     * @return The formatted number string
 191.759 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.760 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.761 +     * @see java.text.FieldPosition
 191.762 +     */
 191.763 +    private StringBuffer format(BigInteger number, StringBuffer result,
 191.764 +                               FieldPosition fieldPosition) {
 191.765 +        fieldPosition.setBeginIndex(0);
 191.766 +        fieldPosition.setEndIndex(0);
 191.767 +
 191.768 +        return format(number, result, fieldPosition.getFieldDelegate(), false);
 191.769 +    }
 191.770 +
 191.771 +    /**
 191.772 +     * Format a BigInteger to produce a string.
 191.773 +     * @param number    The BigInteger to format
 191.774 +     * @param result    where the text is to be appended
 191.775 +     * @param delegate notified of locations of sub fields
 191.776 +     * @return The formatted number string
 191.777 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.778 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.779 +     * @see java.text.FieldPosition
 191.780 +     */
 191.781 +    private StringBuffer format(BigInteger number, StringBuffer result,
 191.782 +                               FieldDelegate delegate, boolean formatLong) {
 191.783 +        if (multiplier != 1) {
 191.784 +            number = number.multiply(getBigIntegerMultiplier());
 191.785 +        }
 191.786 +        boolean isNegative = number.signum() == -1;
 191.787 +        if (isNegative) {
 191.788 +            number = number.negate();
 191.789 +        }
 191.790 +
 191.791 +        synchronized(digitList) {
 191.792 +            int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;
 191.793 +            if (formatLong) {
 191.794 +                maxIntDigits = super.getMaximumIntegerDigits();
 191.795 +                minIntDigits = super.getMinimumIntegerDigits();
 191.796 +                maxFraDigits = super.getMaximumFractionDigits();
 191.797 +                minFraDigits = super.getMinimumFractionDigits();
 191.798 +                maximumDigits = maxIntDigits + maxFraDigits;
 191.799 +            } else {
 191.800 +                maxIntDigits = getMaximumIntegerDigits();
 191.801 +                minIntDigits = getMinimumIntegerDigits();
 191.802 +                maxFraDigits = getMaximumFractionDigits();
 191.803 +                minFraDigits = getMinimumFractionDigits();
 191.804 +                maximumDigits = maxIntDigits + maxFraDigits;
 191.805 +                if (maximumDigits < 0) {
 191.806 +                    maximumDigits = Integer.MAX_VALUE;
 191.807 +                }
 191.808 +            }
 191.809 +
 191.810 +            digitList.set(isNegative, number,
 191.811 +                          useExponentialNotation ? maximumDigits : 0);
 191.812 +
 191.813 +            return subformat(result, delegate, isNegative, true,
 191.814 +                maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
 191.815 +        }
 191.816 +    }
 191.817 +
 191.818 +    /**
 191.819 +     * Formats an Object producing an <code>AttributedCharacterIterator</code>.
 191.820 +     * You can use the returned <code>AttributedCharacterIterator</code>
 191.821 +     * to build the resulting String, as well as to determine information
 191.822 +     * about the resulting String.
 191.823 +     * <p>
 191.824 +     * Each attribute key of the AttributedCharacterIterator will be of type
 191.825 +     * <code>NumberFormat.Field</code>, with the attribute value being the
 191.826 +     * same as the attribute key.
 191.827 +     *
 191.828 +     * @exception NullPointerException if obj is null.
 191.829 +     * @exception IllegalArgumentException when the Format cannot format the
 191.830 +     *            given object.
 191.831 +     * @exception        ArithmeticException if rounding is needed with rounding
 191.832 +     *                   mode being set to RoundingMode.UNNECESSARY
 191.833 +     * @param obj The object to format
 191.834 +     * @return AttributedCharacterIterator describing the formatted value.
 191.835 +     * @since 1.4
 191.836 +     */
 191.837 +    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
 191.838 +        CharacterIteratorFieldDelegate delegate =
 191.839 +                         new CharacterIteratorFieldDelegate();
 191.840 +        StringBuffer sb = new StringBuffer();
 191.841 +
 191.842 +        if (obj instanceof Double || obj instanceof Float) {
 191.843 +            format(((Number)obj).doubleValue(), sb, delegate);
 191.844 +        } else if (obj instanceof Long || obj instanceof Integer ||
 191.845 +                   obj instanceof Short || obj instanceof Byte ||
 191.846 +                   obj instanceof AtomicInteger || obj instanceof AtomicLong) {
 191.847 +            format(((Number)obj).longValue(), sb, delegate);
 191.848 +        } else if (obj instanceof BigDecimal) {
 191.849 +            format((BigDecimal)obj, sb, delegate);
 191.850 +        } else if (obj instanceof BigInteger) {
 191.851 +            format((BigInteger)obj, sb, delegate, false);
 191.852 +        } else if (obj == null) {
 191.853 +            throw new NullPointerException(
 191.854 +                "formatToCharacterIterator must be passed non-null object");
 191.855 +        } else {
 191.856 +            throw new IllegalArgumentException(
 191.857 +                "Cannot format given Object as a Number");
 191.858 +        }
 191.859 +        return delegate.getIterator(sb.toString());
 191.860 +    }
 191.861 +
 191.862 +    /**
 191.863 +     * Complete the formatting of a finite number.  On entry, the digitList must
 191.864 +     * be filled in with the correct digits.
 191.865 +     */
 191.866 +    private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,
 191.867 +                                   boolean isNegative, boolean isInteger,
 191.868 +                                   int maxIntDigits, int minIntDigits,
 191.869 +                                   int maxFraDigits, int minFraDigits) {
 191.870 +        // NOTE: This isn't required anymore because DigitList takes care of this.
 191.871 +        //
 191.872 +        //  // The negative of the exponent represents the number of leading
 191.873 +        //  // zeros between the decimal and the first non-zero digit, for
 191.874 +        //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
 191.875 +        //  // is more than the maximum fraction digits, then we have an underflow
 191.876 +        //  // for the printed representation.  We recognize this here and set
 191.877 +        //  // the DigitList representation to zero in this situation.
 191.878 +        //
 191.879 +        //  if (-digitList.decimalAt >= getMaximumFractionDigits())
 191.880 +        //  {
 191.881 +        //      digitList.count = 0;
 191.882 +        //  }
 191.883 +
 191.884 +        char zero = symbols.getZeroDigit();
 191.885 +        int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
 191.886 +        char grouping = symbols.getGroupingSeparator();
 191.887 +        char decimal = isCurrencyFormat ?
 191.888 +            symbols.getMonetaryDecimalSeparator() :
 191.889 +            symbols.getDecimalSeparator();
 191.890 +
 191.891 +        /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
 191.892 +         * format as zero.  This allows sensible computations and preserves
 191.893 +         * relations such as signum(1/x) = signum(x), where x is +Infinity or
 191.894 +         * -Infinity.  Prior to this fix, we always formatted zero values as if
 191.895 +         * they were positive.  Liu 7/6/98.
 191.896 +         */
 191.897 +        if (digitList.isZero()) {
 191.898 +            digitList.decimalAt = 0; // Normalize
 191.899 +        }
 191.900 +
 191.901 +        if (isNegative) {
 191.902 +            append(result, negativePrefix, delegate,
 191.903 +                   getNegativePrefixFieldPositions(), Field.SIGN);
 191.904 +        } else {
 191.905 +            append(result, positivePrefix, delegate,
 191.906 +                   getPositivePrefixFieldPositions(), Field.SIGN);
 191.907 +        }
 191.908 +
 191.909 +        if (useExponentialNotation) {
 191.910 +            int iFieldStart = result.length();
 191.911 +            int iFieldEnd = -1;
 191.912 +            int fFieldStart = -1;
 191.913 +
 191.914 +            // Minimum integer digits are handled in exponential format by
 191.915 +            // adjusting the exponent.  For example, 0.01234 with 3 minimum
 191.916 +            // integer digits is "123.4E-4".
 191.917 +
 191.918 +            // Maximum integer digits are interpreted as indicating the
 191.919 +            // repeating range.  This is useful for engineering notation, in
 191.920 +            // which the exponent is restricted to a multiple of 3.  For
 191.921 +            // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
 191.922 +            // If maximum integer digits are > 1 and are larger than
 191.923 +            // minimum integer digits, then minimum integer digits are
 191.924 +            // ignored.
 191.925 +            int exponent = digitList.decimalAt;
 191.926 +            int repeat = maxIntDigits;
 191.927 +            int minimumIntegerDigits = minIntDigits;
 191.928 +            if (repeat > 1 && repeat > minIntDigits) {
 191.929 +                // A repeating range is defined; adjust to it as follows.
 191.930 +                // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
 191.931 +                // -3,-4,-5=>-6, etc. This takes into account that the
 191.932 +                // exponent we have here is off by one from what we expect;
 191.933 +                // it is for the format 0.MMMMMx10^n.
 191.934 +                if (exponent >= 1) {
 191.935 +                    exponent = ((exponent - 1) / repeat) * repeat;
 191.936 +                } else {
 191.937 +                    // integer division rounds towards 0
 191.938 +                    exponent = ((exponent - repeat) / repeat) * repeat;
 191.939 +                }
 191.940 +                minimumIntegerDigits = 1;
 191.941 +            } else {
 191.942 +                // No repeating range is defined; use minimum integer digits.
 191.943 +                exponent -= minimumIntegerDigits;
 191.944 +            }
 191.945 +
 191.946 +            // We now output a minimum number of digits, and more if there
 191.947 +            // are more digits, up to the maximum number of digits.  We
 191.948 +            // place the decimal point after the "integer" digits, which
 191.949 +            // are the first (decimalAt - exponent) digits.
 191.950 +            int minimumDigits = minIntDigits + minFraDigits;
 191.951 +            if (minimumDigits < 0) {    // overflow?
 191.952 +                minimumDigits = Integer.MAX_VALUE;
 191.953 +            }
 191.954 +
 191.955 +            // The number of integer digits is handled specially if the number
 191.956 +            // is zero, since then there may be no digits.
 191.957 +            int integerDigits = digitList.isZero() ? minimumIntegerDigits :
 191.958 +                    digitList.decimalAt - exponent;
 191.959 +            if (minimumDigits < integerDigits) {
 191.960 +                minimumDigits = integerDigits;
 191.961 +            }
 191.962 +            int totalDigits = digitList.count;
 191.963 +            if (minimumDigits > totalDigits) {
 191.964 +                totalDigits = minimumDigits;
 191.965 +            }
 191.966 +            boolean addedDecimalSeparator = false;
 191.967 +
 191.968 +            for (int i=0; i<totalDigits; ++i) {
 191.969 +                if (i == integerDigits) {
 191.970 +                    // Record field information for caller.
 191.971 +                    iFieldEnd = result.length();
 191.972 +
 191.973 +                    result.append(decimal);
 191.974 +                    addedDecimalSeparator = true;
 191.975 +
 191.976 +                    // Record field information for caller.
 191.977 +                    fFieldStart = result.length();
 191.978 +                }
 191.979 +                result.append((i < digitList.count) ?
 191.980 +                              (char)(digitList.digits[i] + zeroDelta) :
 191.981 +                              zero);
 191.982 +            }
 191.983 +
 191.984 +            if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
 191.985 +                // Record field information for caller.
 191.986 +                iFieldEnd = result.length();
 191.987 +
 191.988 +                result.append(decimal);
 191.989 +                addedDecimalSeparator = true;
 191.990 +
 191.991 +                // Record field information for caller.
 191.992 +                fFieldStart = result.length();
 191.993 +            }
 191.994 +
 191.995 +            // Record field information
 191.996 +            if (iFieldEnd == -1) {
 191.997 +                iFieldEnd = result.length();
 191.998 +            }
 191.999 +            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
191.1000 +                               iFieldStart, iFieldEnd, result);
191.1001 +            if (addedDecimalSeparator) {
191.1002 +                delegate.formatted(Field.DECIMAL_SEPARATOR,
191.1003 +                                   Field.DECIMAL_SEPARATOR,
191.1004 +                                   iFieldEnd, fFieldStart, result);
191.1005 +            }
191.1006 +            if (fFieldStart == -1) {
191.1007 +                fFieldStart = result.length();
191.1008 +            }
191.1009 +            delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
191.1010 +                               fFieldStart, result.length(), result);
191.1011 +
191.1012 +            // The exponent is output using the pattern-specified minimum
191.1013 +            // exponent digits.  There is no maximum limit to the exponent
191.1014 +            // digits, since truncating the exponent would result in an
191.1015 +            // unacceptable inaccuracy.
191.1016 +            int fieldStart = result.length();
191.1017 +
191.1018 +            result.append(symbols.getExponentSeparator());
191.1019 +
191.1020 +            delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
191.1021 +                               fieldStart, result.length(), result);
191.1022 +
191.1023 +            // For zero values, we force the exponent to zero.  We
191.1024 +            // must do this here, and not earlier, because the value
191.1025 +            // is used to determine integer digit count above.
191.1026 +            if (digitList.isZero()) {
191.1027 +                exponent = 0;
191.1028 +            }
191.1029 +
191.1030 +            boolean negativeExponent = exponent < 0;
191.1031 +            if (negativeExponent) {
191.1032 +                exponent = -exponent;
191.1033 +                fieldStart = result.length();
191.1034 +                result.append(symbols.getMinusSign());
191.1035 +                delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
191.1036 +                                   fieldStart, result.length(), result);
191.1037 +            }
191.1038 +            digitList.set(negativeExponent, exponent);
191.1039 +
191.1040 +            int eFieldStart = result.length();
191.1041 +
191.1042 +            for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
191.1043 +                result.append(zero);
191.1044 +            }
191.1045 +            for (int i=0; i<digitList.decimalAt; ++i) {
191.1046 +                result.append((i < digitList.count) ?
191.1047 +                          (char)(digitList.digits[i] + zeroDelta) : zero);
191.1048 +            }
191.1049 +            delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
191.1050 +                               result.length(), result);
191.1051 +        } else {
191.1052 +            int iFieldStart = result.length();
191.1053 +
191.1054 +            // Output the integer portion.  Here 'count' is the total
191.1055 +            // number of integer digits we will display, including both
191.1056 +            // leading zeros required to satisfy getMinimumIntegerDigits,
191.1057 +            // and actual digits present in the number.
191.1058 +            int count = minIntDigits;
191.1059 +            int digitIndex = 0; // Index into digitList.fDigits[]
191.1060 +            if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
191.1061 +                count = digitList.decimalAt;
191.1062 +            }
191.1063 +
191.1064 +            // Handle the case where getMaximumIntegerDigits() is smaller
191.1065 +            // than the real number of integer digits.  If this is so, we
191.1066 +            // output the least significant max integer digits.  For example,
191.1067 +            // the value 1997 printed with 2 max integer digits is just "97".
191.1068 +            if (count > maxIntDigits) {
191.1069 +                count = maxIntDigits;
191.1070 +                digitIndex = digitList.decimalAt - count;
191.1071 +            }
191.1072 +
191.1073 +            int sizeBeforeIntegerPart = result.length();
191.1074 +            for (int i=count-1; i>=0; --i) {
191.1075 +                if (i < digitList.decimalAt && digitIndex < digitList.count) {
191.1076 +                    // Output a real digit
191.1077 +                    result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
191.1078 +                } else {
191.1079 +                    // Output a leading zero
191.1080 +                    result.append(zero);
191.1081 +                }
191.1082 +
191.1083 +                // Output grouping separator if necessary.  Don't output a
191.1084 +                // grouping separator if i==0 though; that's at the end of
191.1085 +                // the integer part.
191.1086 +                if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
191.1087 +                    (i % groupingSize == 0)) {
191.1088 +                    int gStart = result.length();
191.1089 +                    result.append(grouping);
191.1090 +                    delegate.formatted(Field.GROUPING_SEPARATOR,
191.1091 +                                       Field.GROUPING_SEPARATOR, gStart,
191.1092 +                                       result.length(), result);
191.1093 +                }
191.1094 +            }
191.1095 +
191.1096 +            // Determine whether or not there are any printable fractional
191.1097 +            // digits.  If we've used up the digits we know there aren't.
191.1098 +            boolean fractionPresent = (minFraDigits > 0) ||
191.1099 +                (!isInteger && digitIndex < digitList.count);
191.1100 +
191.1101 +            // If there is no fraction present, and we haven't printed any
191.1102 +            // integer digits, then print a zero.  Otherwise we won't print
191.1103 +            // _any_ digits, and we won't be able to parse this string.
191.1104 +            if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
191.1105 +                result.append(zero);
191.1106 +            }
191.1107 +
191.1108 +            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
191.1109 +                               iFieldStart, result.length(), result);
191.1110 +
191.1111 +            // Output the decimal separator if we always do so.
191.1112 +            int sStart = result.length();
191.1113 +            if (decimalSeparatorAlwaysShown || fractionPresent) {
191.1114 +                result.append(decimal);
191.1115 +            }
191.1116 +
191.1117 +            if (sStart != result.length()) {
191.1118 +                delegate.formatted(Field.DECIMAL_SEPARATOR,
191.1119 +                                   Field.DECIMAL_SEPARATOR,
191.1120 +                                   sStart, result.length(), result);
191.1121 +            }
191.1122 +            int fFieldStart = result.length();
191.1123 +
191.1124 +            for (int i=0; i < maxFraDigits; ++i) {
191.1125 +                // Here is where we escape from the loop.  We escape if we've
191.1126 +                // output the maximum fraction digits (specified in the for
191.1127 +                // expression above).
191.1128 +                // We also stop when we've output the minimum digits and either:
191.1129 +                // we have an integer, so there is no fractional stuff to
191.1130 +                // display, or we're out of significant digits.
191.1131 +                if (i >= minFraDigits &&
191.1132 +                    (isInteger || digitIndex >= digitList.count)) {
191.1133 +                    break;
191.1134 +                }
191.1135 +
191.1136 +                // Output leading fractional zeros. These are zeros that come
191.1137 +                // after the decimal but before any significant digits. These
191.1138 +                // are only output if abs(number being formatted) < 1.0.
191.1139 +                if (-1-i > (digitList.decimalAt-1)) {
191.1140 +                    result.append(zero);
191.1141 +                    continue;
191.1142 +                }
191.1143 +
191.1144 +                // Output a digit, if we have any precision left, or a
191.1145 +                // zero if we don't.  We don't want to output noise digits.
191.1146 +                if (!isInteger && digitIndex < digitList.count) {
191.1147 +                    result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
191.1148 +                } else {
191.1149 +                    result.append(zero);
191.1150 +                }
191.1151 +            }
191.1152 +
191.1153 +            // Record field information for caller.
191.1154 +            delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
191.1155 +                               fFieldStart, result.length(), result);
191.1156 +        }
191.1157 +
191.1158 +        if (isNegative) {
191.1159 +            append(result, negativeSuffix, delegate,
191.1160 +                   getNegativeSuffixFieldPositions(), Field.SIGN);
191.1161 +        }
191.1162 +        else {
191.1163 +            append(result, positiveSuffix, delegate,
191.1164 +                   getPositiveSuffixFieldPositions(), Field.SIGN);
191.1165 +        }
191.1166 +
191.1167 +        return result;
191.1168 +    }
191.1169 +
191.1170 +    /**
191.1171 +     * Appends the String <code>string</code> to <code>result</code>.
191.1172 +     * <code>delegate</code> is notified of all  the
191.1173 +     * <code>FieldPosition</code>s in <code>positions</code>.
191.1174 +     * <p>
191.1175 +     * If one of the <code>FieldPosition</code>s in <code>positions</code>
191.1176 +     * identifies a <code>SIGN</code> attribute, it is mapped to
191.1177 +     * <code>signAttribute</code>. This is used
191.1178 +     * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
191.1179 +     * attribute as necessary.
191.1180 +     * <p>
191.1181 +     * This is used by <code>subformat</code> to add the prefix/suffix.
191.1182 +     */
191.1183 +    private void append(StringBuffer result, String string,
191.1184 +                        FieldDelegate delegate,
191.1185 +                        FieldPosition[] positions,
191.1186 +                        Format.Field signAttribute) {
191.1187 +        int start = result.length();
191.1188 +
191.1189 +        if (string.length() > 0) {
191.1190 +            result.append(string);
191.1191 +            for (int counter = 0, max = positions.length; counter < max;
191.1192 +                 counter++) {
191.1193 +                FieldPosition fp = positions[counter];
191.1194 +                Format.Field attribute = fp.getFieldAttribute();
191.1195 +
191.1196 +                if (attribute == Field.SIGN) {
191.1197 +                    attribute = signAttribute;
191.1198 +                }
191.1199 +                delegate.formatted(attribute, attribute,
191.1200 +                                   start + fp.getBeginIndex(),
191.1201 +                                   start + fp.getEndIndex(), result);
191.1202 +            }
191.1203 +        }
191.1204 +    }
191.1205 +
191.1206 +    /**
191.1207 +     * Parses text from a string to produce a <code>Number</code>.
191.1208 +     * <p>
191.1209 +     * The method attempts to parse text starting at the index given by
191.1210 +     * <code>pos</code>.
191.1211 +     * If parsing succeeds, then the index of <code>pos</code> is updated
191.1212 +     * to the index after the last character used (parsing does not necessarily
191.1213 +     * use all characters up to the end of the string), and the parsed
191.1214 +     * number is returned. The updated <code>pos</code> can be used to
191.1215 +     * indicate the starting point for the next call to this method.
191.1216 +     * If an error occurs, then the index of <code>pos</code> is not
191.1217 +     * changed, the error index of <code>pos</code> is set to the index of
191.1218 +     * the character where the error occurred, and null is returned.
191.1219 +     * <p>
191.1220 +     * The subclass returned depends on the value of {@link #isParseBigDecimal}
191.1221 +     * as well as on the string being parsed.
191.1222 +     * <ul>
191.1223 +     *   <li>If <code>isParseBigDecimal()</code> is false (the default),
191.1224 +     *       most integer values are returned as <code>Long</code>
191.1225 +     *       objects, no matter how they are written: <code>"17"</code> and
191.1226 +     *       <code>"17.000"</code> both parse to <code>Long(17)</code>.
191.1227 +     *       Values that cannot fit into a <code>Long</code> are returned as
191.1228 +     *       <code>Double</code>s. This includes values with a fractional part,
191.1229 +     *       infinite values, <code>NaN</code>, and the value -0.0.
191.1230 +     *       <code>DecimalFormat</code> does <em>not</em> decide whether to
191.1231 +     *       return a <code>Double</code> or a <code>Long</code> based on the
191.1232 +     *       presence of a decimal separator in the source string. Doing so
191.1233 +     *       would prevent integers that overflow the mantissa of a double,
191.1234 +     *       such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
191.1235 +     *       parsed accurately.
191.1236 +     *       <p>
191.1237 +     *       Callers may use the <code>Number</code> methods
191.1238 +     *       <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
191.1239 +     *       the type they want.
191.1240 +     *   <li>If <code>isParseBigDecimal()</code> is true, values are returned
191.1241 +     *       as <code>BigDecimal</code> objects. The values are the ones
191.1242 +     *       constructed by {@link java.math.BigDecimal#BigDecimal(String)}
191.1243 +     *       for corresponding strings in locale-independent format. The
191.1244 +     *       special cases negative and positive infinity and NaN are returned
191.1245 +     *       as <code>Double</code> instances holding the values of the
191.1246 +     *       corresponding <code>Double</code> constants.
191.1247 +     * </ul>
191.1248 +     * <p>
191.1249 +     * <code>DecimalFormat</code> parses all Unicode characters that represent
191.1250 +     * decimal digits, as defined by <code>Character.digit()</code>. In
191.1251 +     * addition, <code>DecimalFormat</code> also recognizes as digits the ten
191.1252 +     * consecutive characters starting with the localized zero digit defined in
191.1253 +     * the <code>DecimalFormatSymbols</code> object.
191.1254 +     *
191.1255 +     * @param text the string to be parsed
191.1256 +     * @param pos  A <code>ParsePosition</code> object with index and error
191.1257 +     *             index information as described above.
191.1258 +     * @return     the parsed value, or <code>null</code> if the parse fails
191.1259 +     * @exception  NullPointerException if <code>text</code> or
191.1260 +     *             <code>pos</code> is null.
191.1261 +     */
191.1262 +    public Number parse(String text, ParsePosition pos) {
191.1263 +        // special case NaN
191.1264 +        if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
191.1265 +            pos.index = pos.index + symbols.getNaN().length();
191.1266 +            return new Double(Double.NaN);
191.1267 +        }
191.1268 +
191.1269 +        boolean[] status = new boolean[STATUS_LENGTH];
191.1270 +        if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {
191.1271 +            return null;
191.1272 +        }
191.1273 +
191.1274 +        // special case INFINITY
191.1275 +        if (status[STATUS_INFINITE]) {
191.1276 +            if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
191.1277 +                return new Double(Double.POSITIVE_INFINITY);
191.1278 +            } else {
191.1279 +                return new Double(Double.NEGATIVE_INFINITY);
191.1280 +            }
191.1281 +        }
191.1282 +
191.1283 +        if (multiplier == 0) {
191.1284 +            if (digitList.isZero()) {
191.1285 +                return new Double(Double.NaN);
191.1286 +            } else if (status[STATUS_POSITIVE]) {
191.1287 +                return new Double(Double.POSITIVE_INFINITY);
191.1288 +            } else {
191.1289 +                return new Double(Double.NEGATIVE_INFINITY);
191.1290 +            }
191.1291 +        }
191.1292 +
191.1293 +        if (isParseBigDecimal()) {
191.1294 +            BigDecimal bigDecimalResult = digitList.getBigDecimal();
191.1295 +
191.1296 +            if (multiplier != 1) {
191.1297 +                try {
191.1298 +                    bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());
191.1299 +                }
191.1300 +                catch (ArithmeticException e) {  // non-terminating decimal expansion
191.1301 +                    bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);
191.1302 +                }
191.1303 +            }
191.1304 +
191.1305 +            if (!status[STATUS_POSITIVE]) {
191.1306 +                bigDecimalResult = bigDecimalResult.negate();
191.1307 +            }
191.1308 +            return bigDecimalResult;
191.1309 +        } else {
191.1310 +            boolean gotDouble = true;
191.1311 +            boolean gotLongMinimum = false;
191.1312 +            double  doubleResult = 0.0;
191.1313 +            long    longResult = 0;
191.1314 +
191.1315 +            // Finally, have DigitList parse the digits into a value.
191.1316 +            if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
191.1317 +                gotDouble = false;
191.1318 +                longResult = digitList.getLong();
191.1319 +                if (longResult < 0) {  // got Long.MIN_VALUE
191.1320 +                    gotLongMinimum = true;
191.1321 +                }
191.1322 +            } else {
191.1323 +                doubleResult = digitList.getDouble();
191.1324 +            }
191.1325 +
191.1326 +            // Divide by multiplier. We have to be careful here not to do
191.1327 +            // unneeded conversions between double and long.
191.1328 +            if (multiplier != 1) {
191.1329 +                if (gotDouble) {
191.1330 +                    doubleResult /= multiplier;
191.1331 +                } else {
191.1332 +                    // Avoid converting to double if we can
191.1333 +                    if (longResult % multiplier == 0) {
191.1334 +                        longResult /= multiplier;
191.1335 +                    } else {
191.1336 +                        doubleResult = ((double)longResult) / multiplier;
191.1337 +                        gotDouble = true;
191.1338 +                    }
191.1339 +                }
191.1340 +            }
191.1341 +
191.1342 +            if (!status[STATUS_POSITIVE] && !gotLongMinimum) {
191.1343 +                doubleResult = -doubleResult;
191.1344 +                longResult = -longResult;
191.1345 +            }
191.1346 +
191.1347 +            // At this point, if we divided the result by the multiplier, the
191.1348 +            // result may fit into a long.  We check for this case and return
191.1349 +            // a long if possible.
191.1350 +            // We must do this AFTER applying the negative (if appropriate)
191.1351 +            // in order to handle the case of LONG_MIN; otherwise, if we do
191.1352 +            // this with a positive value -LONG_MIN, the double is > 0, but
191.1353 +            // the long is < 0. We also must retain a double in the case of
191.1354 +            // -0.0, which will compare as == to a long 0 cast to a double
191.1355 +            // (bug 4162852).
191.1356 +            if (multiplier != 1 && gotDouble) {
191.1357 +                longResult = (long)doubleResult;
191.1358 +                gotDouble = ((doubleResult != (double)longResult) ||
191.1359 +                            (doubleResult == 0.0 && 1/doubleResult < 0.0)) &&
191.1360 +                            !isParseIntegerOnly();
191.1361 +            }
191.1362 +
191.1363 +            return gotDouble ?
191.1364 +                (Number)new Double(doubleResult) : (Number)new Long(longResult);
191.1365 +        }
191.1366 +    }
191.1367 +
191.1368 +    /**
191.1369 +     * Return a BigInteger multiplier.
191.1370 +     */
191.1371 +    private BigInteger getBigIntegerMultiplier() {
191.1372 +        if (bigIntegerMultiplier == null) {
191.1373 +            bigIntegerMultiplier = BigInteger.valueOf(multiplier);
191.1374 +        }
191.1375 +        return bigIntegerMultiplier;
191.1376 +    }
191.1377 +    private transient BigInteger bigIntegerMultiplier;
191.1378 +
191.1379 +    /**
191.1380 +     * Return a BigDecimal multiplier.
191.1381 +     */
191.1382 +    private BigDecimal getBigDecimalMultiplier() {
191.1383 +        if (bigDecimalMultiplier == null) {
191.1384 +            bigDecimalMultiplier = new BigDecimal(multiplier);
191.1385 +        }
191.1386 +        return bigDecimalMultiplier;
191.1387 +    }
191.1388 +    private transient BigDecimal bigDecimalMultiplier;
191.1389 +
191.1390 +    private static final int STATUS_INFINITE = 0;
191.1391 +    private static final int STATUS_POSITIVE = 1;
191.1392 +    private static final int STATUS_LENGTH   = 2;
191.1393 +
191.1394 +    /**
191.1395 +     * Parse the given text into a number.  The text is parsed beginning at
191.1396 +     * parsePosition, until an unparseable character is seen.
191.1397 +     * @param text The string to parse.
191.1398 +     * @param parsePosition The position at which to being parsing.  Upon
191.1399 +     * return, the first unparseable character.
191.1400 +     * @param digits The DigitList to set to the parsed value.
191.1401 +     * @param isExponent If true, parse an exponent.  This means no
191.1402 +     * infinite values and integer only.
191.1403 +     * @param status Upon return contains boolean status flags indicating
191.1404 +     * whether the value was infinite and whether it was positive.
191.1405 +     */
191.1406 +    private final boolean subparse(String text, ParsePosition parsePosition,
191.1407 +                   String positivePrefix, String negativePrefix,
191.1408 +                   DigitList digits, boolean isExponent,
191.1409 +                   boolean status[]) {
191.1410 +        int position = parsePosition.index;
191.1411 +        int oldStart = parsePosition.index;
191.1412 +        int backup;
191.1413 +        boolean gotPositive, gotNegative;
191.1414 +
191.1415 +        // check for positivePrefix; take longest
191.1416 +        gotPositive = text.regionMatches(position, positivePrefix, 0,
191.1417 +                                         positivePrefix.length());
191.1418 +        gotNegative = text.regionMatches(position, negativePrefix, 0,
191.1419 +                                         negativePrefix.length());
191.1420 +
191.1421 +        if (gotPositive && gotNegative) {
191.1422 +            if (positivePrefix.length() > negativePrefix.length()) {
191.1423 +                gotNegative = false;
191.1424 +            } else if (positivePrefix.length() < negativePrefix.length()) {
191.1425 +                gotPositive = false;
191.1426 +            }
191.1427 +        }
191.1428 +
191.1429 +        if (gotPositive) {
191.1430 +            position += positivePrefix.length();
191.1431 +        } else if (gotNegative) {
191.1432 +            position += negativePrefix.length();
191.1433 +        } else {
191.1434 +            parsePosition.errorIndex = position;
191.1435 +            return false;
191.1436 +        }
191.1437 +
191.1438 +        // process digits or Inf, find decimal position
191.1439 +        status[STATUS_INFINITE] = false;
191.1440 +        if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
191.1441 +                          symbols.getInfinity().length())) {
191.1442 +            position += symbols.getInfinity().length();
191.1443 +            status[STATUS_INFINITE] = true;
191.1444 +        } else {
191.1445 +            // We now have a string of digits, possibly with grouping symbols,
191.1446 +            // and decimal points.  We want to process these into a DigitList.
191.1447 +            // We don't want to put a bunch of leading zeros into the DigitList
191.1448 +            // though, so we keep track of the location of the decimal point,
191.1449 +            // put only significant digits into the DigitList, and adjust the
191.1450 +            // exponent as needed.
191.1451 +
191.1452 +            digits.decimalAt = digits.count = 0;
191.1453 +            char zero = symbols.getZeroDigit();
191.1454 +            char decimal = isCurrencyFormat ?
191.1455 +                symbols.getMonetaryDecimalSeparator() :
191.1456 +                symbols.getDecimalSeparator();
191.1457 +            char grouping = symbols.getGroupingSeparator();
191.1458 +            String exponentString = symbols.getExponentSeparator();
191.1459 +            boolean sawDecimal = false;
191.1460 +            boolean sawExponent = false;
191.1461 +            boolean sawDigit = false;
191.1462 +            int exponent = 0; // Set to the exponent value, if any
191.1463 +
191.1464 +            // We have to track digitCount ourselves, because digits.count will
191.1465 +            // pin when the maximum allowable digits is reached.
191.1466 +            int digitCount = 0;
191.1467 +
191.1468 +            backup = -1;
191.1469 +            for (; position < text.length(); ++position) {
191.1470 +                char ch = text.charAt(position);
191.1471 +
191.1472 +                /* We recognize all digit ranges, not only the Latin digit range
191.1473 +                 * '0'..'9'.  We do so by using the Character.digit() method,
191.1474 +                 * which converts a valid Unicode digit to the range 0..9.
191.1475 +                 *
191.1476 +                 * The character 'ch' may be a digit.  If so, place its value
191.1477 +                 * from 0 to 9 in 'digit'.  First try using the locale digit,
191.1478 +                 * which may or MAY NOT be a standard Unicode digit range.  If
191.1479 +                 * this fails, try using the standard Unicode digit ranges by
191.1480 +                 * calling Character.digit().  If this also fails, digit will
191.1481 +                 * have a value outside the range 0..9.
191.1482 +                 */
191.1483 +                int digit = ch - zero;
191.1484 +                if (digit < 0 || digit > 9) {
191.1485 +                    digit = Character.digit(ch, 10);
191.1486 +                }
191.1487 +
191.1488 +                if (digit == 0) {
191.1489 +                    // Cancel out backup setting (see grouping handler below)
191.1490 +                    backup = -1; // Do this BEFORE continue statement below!!!
191.1491 +                    sawDigit = true;
191.1492 +
191.1493 +                    // Handle leading zeros
191.1494 +                    if (digits.count == 0) {
191.1495 +                        // Ignore leading zeros in integer part of number.
191.1496 +                        if (!sawDecimal) {
191.1497 +                            continue;
191.1498 +                        }
191.1499 +
191.1500 +                        // If we have seen the decimal, but no significant
191.1501 +                        // digits yet, then we account for leading zeros by
191.1502 +                        // decrementing the digits.decimalAt into negative
191.1503 +                        // values.
191.1504 +                        --digits.decimalAt;
191.1505 +                    } else {
191.1506 +                        ++digitCount;
191.1507 +                        digits.append((char)(digit + '0'));
191.1508 +                    }
191.1509 +                } else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above
191.1510 +                    sawDigit = true;
191.1511 +                    ++digitCount;
191.1512 +                    digits.append((char)(digit + '0'));
191.1513 +
191.1514 +                    // Cancel out backup setting (see grouping handler below)
191.1515 +                    backup = -1;
191.1516 +                } else if (!isExponent && ch == decimal) {
191.1517 +                    // If we're only parsing integers, or if we ALREADY saw the
191.1518 +                    // decimal, then don't parse this one.
191.1519 +                    if (isParseIntegerOnly() || sawDecimal) {
191.1520 +                        break;
191.1521 +                    }
191.1522 +                    digits.decimalAt = digitCount; // Not digits.count!
191.1523 +                    sawDecimal = true;
191.1524 +                } else if (!isExponent && ch == grouping && isGroupingUsed()) {
191.1525 +                    if (sawDecimal) {
191.1526 +                        break;
191.1527 +                    }
191.1528 +                    // Ignore grouping characters, if we are using them, but
191.1529 +                    // require that they be followed by a digit.  Otherwise
191.1530 +                    // we backup and reprocess them.
191.1531 +                    backup = position;
191.1532 +                } else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())
191.1533 +                             && !sawExponent) {
191.1534 +                    // Process the exponent by recursively calling this method.
191.1535 +                     ParsePosition pos = new ParsePosition(position + exponentString.length());
191.1536 +                    boolean[] stat = new boolean[STATUS_LENGTH];
191.1537 +                    DigitList exponentDigits = new DigitList();
191.1538 +
191.1539 +                    if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
191.1540 +                        exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
191.1541 +                        position = pos.index; // Advance past the exponent
191.1542 +                        exponent = (int)exponentDigits.getLong();
191.1543 +                        if (!stat[STATUS_POSITIVE]) {
191.1544 +                            exponent = -exponent;
191.1545 +                        }
191.1546 +                        sawExponent = true;
191.1547 +                    }
191.1548 +                    break; // Whether we fail or succeed, we exit this loop
191.1549 +                }
191.1550 +                else {
191.1551 +                    break;
191.1552 +                }
191.1553 +            }
191.1554 +
191.1555 +            if (backup != -1) {
191.1556 +                position = backup;
191.1557 +            }
191.1558 +
191.1559 +            // If there was no decimal point we have an integer
191.1560 +            if (!sawDecimal) {
191.1561 +                digits.decimalAt = digitCount; // Not digits.count!
191.1562 +            }
191.1563 +
191.1564 +            // Adjust for exponent, if any
191.1565 +            digits.decimalAt += exponent;
191.1566 +
191.1567 +            // If none of the text string was recognized.  For example, parse
191.1568 +            // "x" with pattern "#0.00" (return index and error index both 0)
191.1569 +            // parse "$" with pattern "$#0.00". (return index 0 and error
191.1570 +            // index 1).
191.1571 +            if (!sawDigit && digitCount == 0) {
191.1572 +                parsePosition.index = oldStart;
191.1573 +                parsePosition.errorIndex = oldStart;
191.1574 +                return false;
191.1575 +            }
191.1576 +        }
191.1577 +
191.1578 +        // check for suffix
191.1579 +        if (!isExponent) {
191.1580 +            if (gotPositive) {
191.1581 +                gotPositive = text.regionMatches(position,positiveSuffix,0,
191.1582 +                                                 positiveSuffix.length());
191.1583 +            }
191.1584 +            if (gotNegative) {
191.1585 +                gotNegative = text.regionMatches(position,negativeSuffix,0,
191.1586 +                                                 negativeSuffix.length());
191.1587 +            }
191.1588 +
191.1589 +        // if both match, take longest
191.1590 +        if (gotPositive && gotNegative) {
191.1591 +            if (positiveSuffix.length() > negativeSuffix.length()) {
191.1592 +                gotNegative = false;
191.1593 +            } else if (positiveSuffix.length() < negativeSuffix.length()) {
191.1594 +                gotPositive = false;
191.1595 +            }
191.1596 +        }
191.1597 +
191.1598 +        // fail if neither or both
191.1599 +        if (gotPositive == gotNegative) {
191.1600 +            parsePosition.errorIndex = position;
191.1601 +            return false;
191.1602 +        }
191.1603 +
191.1604 +        parsePosition.index = position +
191.1605 +            (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
191.1606 +        } else {
191.1607 +            parsePosition.index = position;
191.1608 +        }
191.1609 +
191.1610 +        status[STATUS_POSITIVE] = gotPositive;
191.1611 +        if (parsePosition.index == oldStart) {
191.1612 +            parsePosition.errorIndex = position;
191.1613 +            return false;
191.1614 +        }
191.1615 +        return true;
191.1616 +    }
191.1617 +
191.1618 +    /**
191.1619 +     * Returns a copy of the decimal format symbols, which is generally not
191.1620 +     * changed by the programmer or user.
191.1621 +     * @return a copy of the desired DecimalFormatSymbols
191.1622 +     * @see java.text.DecimalFormatSymbols
191.1623 +     */
191.1624 +    public DecimalFormatSymbols getDecimalFormatSymbols() {
191.1625 +        try {
191.1626 +            // don't allow multiple references
191.1627 +            return (DecimalFormatSymbols) symbols.clone();
191.1628 +        } catch (Exception foo) {
191.1629 +            return null; // should never happen
191.1630 +        }
191.1631 +    }
191.1632 +
191.1633 +
191.1634 +    /**
191.1635 +     * Sets the decimal format symbols, which is generally not changed
191.1636 +     * by the programmer or user.
191.1637 +     * @param newSymbols desired DecimalFormatSymbols
191.1638 +     * @see java.text.DecimalFormatSymbols
191.1639 +     */
191.1640 +    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
191.1641 +        try {
191.1642 +            // don't allow multiple references
191.1643 +            symbols = (DecimalFormatSymbols) newSymbols.clone();
191.1644 +            expandAffixes();
191.1645 +        } catch (Exception foo) {
191.1646 +            // should never happen
191.1647 +        }
191.1648 +    }
191.1649 +
191.1650 +    /**
191.1651 +     * Get the positive prefix.
191.1652 +     * <P>Examples: +123, $123, sFr123
191.1653 +     */
191.1654 +    public String getPositivePrefix () {
191.1655 +        return positivePrefix;
191.1656 +    }
191.1657 +
191.1658 +    /**
191.1659 +     * Set the positive prefix.
191.1660 +     * <P>Examples: +123, $123, sFr123
191.1661 +     */
191.1662 +    public void setPositivePrefix (String newValue) {
191.1663 +        positivePrefix = newValue;
191.1664 +        posPrefixPattern = null;
191.1665 +        positivePrefixFieldPositions = null;
191.1666 +    }
191.1667 +
191.1668 +    /**
191.1669 +     * Returns the FieldPositions of the fields in the prefix used for
191.1670 +     * positive numbers. This is not used if the user has explicitly set
191.1671 +     * a positive prefix via <code>setPositivePrefix</code>. This is
191.1672 +     * lazily created.
191.1673 +     *
191.1674 +     * @return FieldPositions in positive prefix
191.1675 +     */
191.1676 +    private FieldPosition[] getPositivePrefixFieldPositions() {
191.1677 +        if (positivePrefixFieldPositions == null) {
191.1678 +            if (posPrefixPattern != null) {
191.1679 +                positivePrefixFieldPositions = expandAffix(posPrefixPattern);
191.1680 +            }
191.1681 +            else {
191.1682 +                positivePrefixFieldPositions = EmptyFieldPositionArray;
191.1683 +            }
191.1684 +        }
191.1685 +        return positivePrefixFieldPositions;
191.1686 +    }
191.1687 +
191.1688 +    /**
191.1689 +     * Get the negative prefix.
191.1690 +     * <P>Examples: -123, ($123) (with negative suffix), sFr-123
191.1691 +     */
191.1692 +    public String getNegativePrefix () {
191.1693 +        return negativePrefix;
191.1694 +    }
191.1695 +
191.1696 +    /**
191.1697 +     * Set the negative prefix.
191.1698 +     * <P>Examples: -123, ($123) (with negative suffix), sFr-123
191.1699 +     */
191.1700 +    public void setNegativePrefix (String newValue) {
191.1701 +        negativePrefix = newValue;
191.1702 +        negPrefixPattern = null;
191.1703 +    }
191.1704 +
191.1705 +    /**
191.1706 +     * Returns the FieldPositions of the fields in the prefix used for
191.1707 +     * negative numbers. This is not used if the user has explicitly set
191.1708 +     * a negative prefix via <code>setNegativePrefix</code>. This is
191.1709 +     * lazily created.
191.1710 +     *
191.1711 +     * @return FieldPositions in positive prefix
191.1712 +     */
191.1713 +    private FieldPosition[] getNegativePrefixFieldPositions() {
191.1714 +        if (negativePrefixFieldPositions == null) {
191.1715 +            if (negPrefixPattern != null) {
191.1716 +                negativePrefixFieldPositions = expandAffix(negPrefixPattern);
191.1717 +            }
191.1718 +            else {
191.1719 +                negativePrefixFieldPositions = EmptyFieldPositionArray;
191.1720 +            }
191.1721 +        }
191.1722 +        return negativePrefixFieldPositions;
191.1723 +    }
191.1724 +
191.1725 +    /**
191.1726 +     * Get the positive suffix.
191.1727 +     * <P>Example: 123%
191.1728 +     */
191.1729 +    public String getPositiveSuffix () {
191.1730 +        return positiveSuffix;
191.1731 +    }
191.1732 +
191.1733 +    /**
191.1734 +     * Set the positive suffix.
191.1735 +     * <P>Example: 123%
191.1736 +     */
191.1737 +    public void setPositiveSuffix (String newValue) {
191.1738 +        positiveSuffix = newValue;
191.1739 +        posSuffixPattern = null;
191.1740 +    }
191.1741 +
191.1742 +    /**
191.1743 +     * Returns the FieldPositions of the fields in the suffix used for
191.1744 +     * positive numbers. This is not used if the user has explicitly set
191.1745 +     * a positive suffix via <code>setPositiveSuffix</code>. This is
191.1746 +     * lazily created.
191.1747 +     *
191.1748 +     * @return FieldPositions in positive prefix
191.1749 +     */
191.1750 +    private FieldPosition[] getPositiveSuffixFieldPositions() {
191.1751 +        if (positiveSuffixFieldPositions == null) {
191.1752 +            if (posSuffixPattern != null) {
191.1753 +                positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
191.1754 +            }
191.1755 +            else {
191.1756 +                positiveSuffixFieldPositions = EmptyFieldPositionArray;
191.1757 +            }
191.1758 +        }
191.1759 +        return positiveSuffixFieldPositions;
191.1760 +    }
191.1761 +
191.1762 +    /**
191.1763 +     * Get the negative suffix.
191.1764 +     * <P>Examples: -123%, ($123) (with positive suffixes)
191.1765 +     */
191.1766 +    public String getNegativeSuffix () {
191.1767 +        return negativeSuffix;
191.1768 +    }
191.1769 +
191.1770 +    /**
191.1771 +     * Set the negative suffix.
191.1772 +     * <P>Examples: 123%
191.1773 +     */
191.1774 +    public void setNegativeSuffix (String newValue) {
191.1775 +        negativeSuffix = newValue;
191.1776 +        negSuffixPattern = null;
191.1777 +    }
191.1778 +
191.1779 +    /**
191.1780 +     * Returns the FieldPositions of the fields in the suffix used for
191.1781 +     * negative numbers. This is not used if the user has explicitly set
191.1782 +     * a negative suffix via <code>setNegativeSuffix</code>. This is
191.1783 +     * lazily created.
191.1784 +     *
191.1785 +     * @return FieldPositions in positive prefix
191.1786 +     */
191.1787 +    private FieldPosition[] getNegativeSuffixFieldPositions() {
191.1788 +        if (negativeSuffixFieldPositions == null) {
191.1789 +            if (negSuffixPattern != null) {
191.1790 +                negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
191.1791 +            }
191.1792 +            else {
191.1793 +                negativeSuffixFieldPositions = EmptyFieldPositionArray;
191.1794 +            }
191.1795 +        }
191.1796 +        return negativeSuffixFieldPositions;
191.1797 +    }
191.1798 +
191.1799 +    /**
191.1800 +     * Gets the multiplier for use in percent, per mille, and similar
191.1801 +     * formats.
191.1802 +     *
191.1803 +     * @see #setMultiplier(int)
191.1804 +     */
191.1805 +    public int getMultiplier () {
191.1806 +        return multiplier;
191.1807 +    }
191.1808 +
191.1809 +    /**
191.1810 +     * Sets the multiplier for use in percent, per mille, and similar
191.1811 +     * formats.
191.1812 +     * For a percent format, set the multiplier to 100 and the suffixes to
191.1813 +     * have '%' (for Arabic, use the Arabic percent sign).
191.1814 +     * For a per mille format, set the multiplier to 1000 and the suffixes to
191.1815 +     * have '&#92;u2030'.
191.1816 +     *
191.1817 +     * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
191.1818 +     * "123" is parsed into 1.23.
191.1819 +     *
191.1820 +     * @see #getMultiplier
191.1821 +     */
191.1822 +    public void setMultiplier (int newValue) {
191.1823 +        multiplier = newValue;
191.1824 +        bigDecimalMultiplier = null;
191.1825 +        bigIntegerMultiplier = null;
191.1826 +    }
191.1827 +
191.1828 +    /**
191.1829 +     * Return the grouping size. Grouping size is the number of digits between
191.1830 +     * grouping separators in the integer portion of a number.  For example,
191.1831 +     * in the number "123,456.78", the grouping size is 3.
191.1832 +     * @see #setGroupingSize
191.1833 +     * @see java.text.NumberFormat#isGroupingUsed
191.1834 +     * @see java.text.DecimalFormatSymbols#getGroupingSeparator
191.1835 +     */
191.1836 +    public int getGroupingSize () {
191.1837 +        return groupingSize;
191.1838 +    }
191.1839 +
191.1840 +    /**
191.1841 +     * Set the grouping size. Grouping size is the number of digits between
191.1842 +     * grouping separators in the integer portion of a number.  For example,
191.1843 +     * in the number "123,456.78", the grouping size is 3.
191.1844 +     * <br>
191.1845 +     * The value passed in is converted to a byte, which may lose information.
191.1846 +     * @see #getGroupingSize
191.1847 +     * @see java.text.NumberFormat#setGroupingUsed
191.1848 +     * @see java.text.DecimalFormatSymbols#setGroupingSeparator
191.1849 +     */
191.1850 +    public void setGroupingSize (int newValue) {
191.1851 +        groupingSize = (byte)newValue;
191.1852 +    }
191.1853 +
191.1854 +    /**
191.1855 +     * Allows you to get the behavior of the decimal separator with integers.
191.1856 +     * (The decimal separator will always appear with decimals.)
191.1857 +     * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
191.1858 +     */
191.1859 +    public boolean isDecimalSeparatorAlwaysShown() {
191.1860 +        return decimalSeparatorAlwaysShown;
191.1861 +    }
191.1862 +
191.1863 +    /**
191.1864 +     * Allows you to set the behavior of the decimal separator with integers.
191.1865 +     * (The decimal separator will always appear with decimals.)
191.1866 +     * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
191.1867 +     */
191.1868 +    public void setDecimalSeparatorAlwaysShown(boolean newValue) {
191.1869 +        decimalSeparatorAlwaysShown = newValue;
191.1870 +    }
191.1871 +
191.1872 +    /**
191.1873 +     * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
191.1874 +     * method returns <code>BigDecimal</code>. The default value is false.
191.1875 +     * @see #setParseBigDecimal
191.1876 +     * @since 1.5
191.1877 +     */
191.1878 +    public boolean isParseBigDecimal() {
191.1879 +        return parseBigDecimal;
191.1880 +    }
191.1881 +
191.1882 +    /**
191.1883 +     * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
191.1884 +     * method returns <code>BigDecimal</code>.
191.1885 +     * @see #isParseBigDecimal
191.1886 +     * @since 1.5
191.1887 +     */
191.1888 +    public void setParseBigDecimal(boolean newValue) {
191.1889 +        parseBigDecimal = newValue;
191.1890 +    }
191.1891 +
191.1892 +    /**
191.1893 +     * Standard override; no change in semantics.
191.1894 +     */
191.1895 +    public Object clone() {
191.1896 +        try {
191.1897 +            DecimalFormat other = (DecimalFormat) super.clone();
191.1898 +            other.symbols = (DecimalFormatSymbols) symbols.clone();
191.1899 +            other.digitList = (DigitList) digitList.clone();
191.1900 +            return other;
191.1901 +        } catch (Exception e) {
191.1902 +            throw new InternalError();
191.1903 +        }
191.1904 +    }
191.1905 +
191.1906 +    /**
191.1907 +     * Overrides equals
191.1908 +     */
191.1909 +    public boolean equals(Object obj)
191.1910 +    {
191.1911 +        if (obj == null) return false;
191.1912 +        if (!super.equals(obj)) return false; // super does class check
191.1913 +        DecimalFormat other = (DecimalFormat) obj;
191.1914 +        return ((posPrefixPattern == other.posPrefixPattern &&
191.1915 +                 positivePrefix.equals(other.positivePrefix))
191.1916 +                || (posPrefixPattern != null &&
191.1917 +                    posPrefixPattern.equals(other.posPrefixPattern)))
191.1918 +            && ((posSuffixPattern == other.posSuffixPattern &&
191.1919 +                 positiveSuffix.equals(other.positiveSuffix))
191.1920 +                || (posSuffixPattern != null &&
191.1921 +                    posSuffixPattern.equals(other.posSuffixPattern)))
191.1922 +            && ((negPrefixPattern == other.negPrefixPattern &&
191.1923 +                 negativePrefix.equals(other.negativePrefix))
191.1924 +                || (negPrefixPattern != null &&
191.1925 +                    negPrefixPattern.equals(other.negPrefixPattern)))
191.1926 +            && ((negSuffixPattern == other.negSuffixPattern &&
191.1927 +                 negativeSuffix.equals(other.negativeSuffix))
191.1928 +                || (negSuffixPattern != null &&
191.1929 +                    negSuffixPattern.equals(other.negSuffixPattern)))
191.1930 +            && multiplier == other.multiplier
191.1931 +            && groupingSize == other.groupingSize
191.1932 +            && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
191.1933 +            && parseBigDecimal == other.parseBigDecimal
191.1934 +            && useExponentialNotation == other.useExponentialNotation
191.1935 +            && (!useExponentialNotation ||
191.1936 +                minExponentDigits == other.minExponentDigits)
191.1937 +            && maximumIntegerDigits == other.maximumIntegerDigits
191.1938 +            && minimumIntegerDigits == other.minimumIntegerDigits
191.1939 +            && maximumFractionDigits == other.maximumFractionDigits
191.1940 +            && minimumFractionDigits == other.minimumFractionDigits
191.1941 +            && roundingMode == other.roundingMode
191.1942 +            && symbols.equals(other.symbols);
191.1943 +    }
191.1944 +
191.1945 +    /**
191.1946 +     * Overrides hashCode
191.1947 +     */
191.1948 +    public int hashCode() {
191.1949 +        return super.hashCode() * 37 + positivePrefix.hashCode();
191.1950 +        // just enough fields for a reasonable distribution
191.1951 +    }
191.1952 +
191.1953 +    /**
191.1954 +     * Synthesizes a pattern string that represents the current state
191.1955 +     * of this Format object.
191.1956 +     * @see #applyPattern
191.1957 +     */
191.1958 +    public String toPattern() {
191.1959 +        return toPattern( false );
191.1960 +    }
191.1961 +
191.1962 +    /**
191.1963 +     * Synthesizes a localized pattern string that represents the current
191.1964 +     * state of this Format object.
191.1965 +     * @see #applyPattern
191.1966 +     */
191.1967 +    public String toLocalizedPattern() {
191.1968 +        return toPattern( true );
191.1969 +    }
191.1970 +
191.1971 +    /**
191.1972 +     * Expand the affix pattern strings into the expanded affix strings.  If any
191.1973 +     * affix pattern string is null, do not expand it.  This method should be
191.1974 +     * called any time the symbols or the affix patterns change in order to keep
191.1975 +     * the expanded affix strings up to date.
191.1976 +     */
191.1977 +    private void expandAffixes() {
191.1978 +        // Reuse one StringBuffer for better performance
191.1979 +        StringBuffer buffer = new StringBuffer();
191.1980 +        if (posPrefixPattern != null) {
191.1981 +            positivePrefix = expandAffix(posPrefixPattern, buffer);
191.1982 +            positivePrefixFieldPositions = null;
191.1983 +        }
191.1984 +        if (posSuffixPattern != null) {
191.1985 +            positiveSuffix = expandAffix(posSuffixPattern, buffer);
191.1986 +            positiveSuffixFieldPositions = null;
191.1987 +        }
191.1988 +        if (negPrefixPattern != null) {
191.1989 +            negativePrefix = expandAffix(negPrefixPattern, buffer);
191.1990 +            negativePrefixFieldPositions = null;
191.1991 +        }
191.1992 +        if (negSuffixPattern != null) {
191.1993 +            negativeSuffix = expandAffix(negSuffixPattern, buffer);
191.1994 +            negativeSuffixFieldPositions = null;
191.1995 +        }
191.1996 +    }
191.1997 +
191.1998 +    /**
191.1999 +     * Expand an affix pattern into an affix string.  All characters in the
191.2000 +     * pattern are literal unless prefixed by QUOTE.  The following characters
191.2001 +     * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
191.2002 +     * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
191.2003 +     * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
191.2004 +     * currency code.  Any other character after a QUOTE represents itself.
191.2005 +     * QUOTE must be followed by another character; QUOTE may not occur by
191.2006 +     * itself at the end of the pattern.
191.2007 +     *
191.2008 +     * @param pattern the non-null, possibly empty pattern
191.2009 +     * @param buffer a scratch StringBuffer; its contents will be lost
191.2010 +     * @return the expanded equivalent of pattern
191.2011 +     */
191.2012 +    private String expandAffix(String pattern, StringBuffer buffer) {
191.2013 +        buffer.setLength(0);
191.2014 +        for (int i=0; i<pattern.length(); ) {
191.2015 +            char c = pattern.charAt(i++);
191.2016 +            if (c == QUOTE) {
191.2017 +                c = pattern.charAt(i++);
191.2018 +                switch (c) {
191.2019 +                case CURRENCY_SIGN:
191.2020 +                    if (i<pattern.length() &&
191.2021 +                        pattern.charAt(i) == CURRENCY_SIGN) {
191.2022 +                        ++i;
191.2023 +                        buffer.append(symbols.getInternationalCurrencySymbol());
191.2024 +                    } else {
191.2025 +                        buffer.append(symbols.getCurrencySymbol());
191.2026 +                    }
191.2027 +                    continue;
191.2028 +                case PATTERN_PERCENT:
191.2029 +                    c = symbols.getPercent();
191.2030 +                    break;
191.2031 +                case PATTERN_PER_MILLE:
191.2032 +                    c = symbols.getPerMill();
191.2033 +                    break;
191.2034 +                case PATTERN_MINUS:
191.2035 +                    c = symbols.getMinusSign();
191.2036 +                    break;
191.2037 +                }
191.2038 +            }
191.2039 +            buffer.append(c);
191.2040 +        }
191.2041 +        return buffer.toString();
191.2042 +    }
191.2043 +
191.2044 +    /**
191.2045 +     * Expand an affix pattern into an array of FieldPositions describing
191.2046 +     * how the pattern would be expanded.
191.2047 +     * All characters in the
191.2048 +     * pattern are literal unless prefixed by QUOTE.  The following characters
191.2049 +     * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
191.2050 +     * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
191.2051 +     * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
191.2052 +     * currency code.  Any other character after a QUOTE represents itself.
191.2053 +     * QUOTE must be followed by another character; QUOTE may not occur by
191.2054 +     * itself at the end of the pattern.
191.2055 +     *
191.2056 +     * @param pattern the non-null, possibly empty pattern
191.2057 +     * @return FieldPosition array of the resulting fields.
191.2058 +     */
191.2059 +    private FieldPosition[] expandAffix(String pattern) {
191.2060 +        ArrayList positions = null;
191.2061 +        int stringIndex = 0;
191.2062 +        for (int i=0; i<pattern.length(); ) {
191.2063 +            char c = pattern.charAt(i++);
191.2064 +            if (c == QUOTE) {
191.2065 +                int field = -1;
191.2066 +                Format.Field fieldID = null;
191.2067 +                c = pattern.charAt(i++);
191.2068 +                switch (c) {
191.2069 +                case CURRENCY_SIGN:
191.2070 +                    String string;
191.2071 +                    if (i<pattern.length() &&
191.2072 +                        pattern.charAt(i) == CURRENCY_SIGN) {
191.2073 +                        ++i;
191.2074 +                        string = symbols.getInternationalCurrencySymbol();
191.2075 +                    } else {
191.2076 +                        string = symbols.getCurrencySymbol();
191.2077 +                    }
191.2078 +                    if (string.length() > 0) {
191.2079 +                        if (positions == null) {
191.2080 +                            positions = new ArrayList(2);
191.2081 +                        }
191.2082 +                        FieldPosition fp = new FieldPosition(Field.CURRENCY);
191.2083 +                        fp.setBeginIndex(stringIndex);
191.2084 +                        fp.setEndIndex(stringIndex + string.length());
191.2085 +                        positions.add(fp);
191.2086 +                        stringIndex += string.length();
191.2087 +                    }
191.2088 +                    continue;
191.2089 +                case PATTERN_PERCENT:
191.2090 +                    c = symbols.getPercent();
191.2091 +                    field = -1;
191.2092 +                    fieldID = Field.PERCENT;
191.2093 +                    break;
191.2094 +                case PATTERN_PER_MILLE:
191.2095 +                    c = symbols.getPerMill();
191.2096 +                    field = -1;
191.2097 +                    fieldID = Field.PERMILLE;
191.2098 +                    break;
191.2099 +                case PATTERN_MINUS:
191.2100 +                    c = symbols.getMinusSign();
191.2101 +                    field = -1;
191.2102 +                    fieldID = Field.SIGN;
191.2103 +                    break;
191.2104 +                }
191.2105 +                if (fieldID != null) {
191.2106 +                    if (positions == null) {
191.2107 +                        positions = new ArrayList(2);
191.2108 +                    }
191.2109 +                    FieldPosition fp = new FieldPosition(fieldID, field);
191.2110 +                    fp.setBeginIndex(stringIndex);
191.2111 +                    fp.setEndIndex(stringIndex + 1);
191.2112 +                    positions.add(fp);
191.2113 +                }
191.2114 +            }
191.2115 +            stringIndex++;
191.2116 +        }
191.2117 +        if (positions != null) {
191.2118 +            return (FieldPosition[])positions.toArray(EmptyFieldPositionArray);
191.2119 +        }
191.2120 +        return EmptyFieldPositionArray;
191.2121 +    }
191.2122 +
191.2123 +    /**
191.2124 +     * Appends an affix pattern to the given StringBuffer, quoting special
191.2125 +     * characters as needed.  Uses the internal affix pattern, if that exists,
191.2126 +     * or the literal affix, if the internal affix pattern is null.  The
191.2127 +     * appended string will generate the same affix pattern (or literal affix)
191.2128 +     * when passed to toPattern().
191.2129 +     *
191.2130 +     * @param buffer the affix string is appended to this
191.2131 +     * @param affixPattern a pattern such as posPrefixPattern; may be null
191.2132 +     * @param expAffix a corresponding expanded affix, such as positivePrefix.
191.2133 +     * Ignored unless affixPattern is null.  If affixPattern is null, then
191.2134 +     * expAffix is appended as a literal affix.
191.2135 +     * @param localized true if the appended pattern should contain localized
191.2136 +     * pattern characters; otherwise, non-localized pattern chars are appended
191.2137 +     */
191.2138 +    private void appendAffix(StringBuffer buffer, String affixPattern,
191.2139 +                             String expAffix, boolean localized) {
191.2140 +        if (affixPattern == null) {
191.2141 +            appendAffix(buffer, expAffix, localized);
191.2142 +        } else {
191.2143 +            int i;
191.2144 +            for (int pos=0; pos<affixPattern.length(); pos=i) {
191.2145 +                i = affixPattern.indexOf(QUOTE, pos);
191.2146 +                if (i < 0) {
191.2147 +                    appendAffix(buffer, affixPattern.substring(pos), localized);
191.2148 +                    break;
191.2149 +                }
191.2150 +                if (i > pos) {
191.2151 +                    appendAffix(buffer, affixPattern.substring(pos, i), localized);
191.2152 +                }
191.2153 +                char c = affixPattern.charAt(++i);
191.2154 +                ++i;
191.2155 +                if (c == QUOTE) {
191.2156 +                    buffer.append(c);
191.2157 +                    // Fall through and append another QUOTE below
191.2158 +                } else if (c == CURRENCY_SIGN &&
191.2159 +                           i<affixPattern.length() &&
191.2160 +                           affixPattern.charAt(i) == CURRENCY_SIGN) {
191.2161 +                    ++i;
191.2162 +                    buffer.append(c);
191.2163 +                    // Fall through and append another CURRENCY_SIGN below
191.2164 +                } else if (localized) {
191.2165 +                    switch (c) {
191.2166 +                    case PATTERN_PERCENT:
191.2167 +                        c = symbols.getPercent();
191.2168 +                        break;
191.2169 +                    case PATTERN_PER_MILLE:
191.2170 +                        c = symbols.getPerMill();
191.2171 +                        break;
191.2172 +                    case PATTERN_MINUS:
191.2173 +                        c = symbols.getMinusSign();
191.2174 +                        break;
191.2175 +                    }
191.2176 +                }
191.2177 +                buffer.append(c);
191.2178 +            }
191.2179 +        }
191.2180 +    }
191.2181 +
191.2182 +    /**
191.2183 +     * Append an affix to the given StringBuffer, using quotes if
191.2184 +     * there are special characters.  Single quotes themselves must be
191.2185 +     * escaped in either case.
191.2186 +     */
191.2187 +    private void appendAffix(StringBuffer buffer, String affix, boolean localized) {
191.2188 +        boolean needQuote;
191.2189 +        if (localized) {
191.2190 +            needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
191.2191 +                || affix.indexOf(symbols.getGroupingSeparator()) >= 0
191.2192 +                || affix.indexOf(symbols.getDecimalSeparator()) >= 0
191.2193 +                || affix.indexOf(symbols.getPercent()) >= 0
191.2194 +                || affix.indexOf(symbols.getPerMill()) >= 0
191.2195 +                || affix.indexOf(symbols.getDigit()) >= 0
191.2196 +                || affix.indexOf(symbols.getPatternSeparator()) >= 0
191.2197 +                || affix.indexOf(symbols.getMinusSign()) >= 0
191.2198 +                || affix.indexOf(CURRENCY_SIGN) >= 0;
191.2199 +        }
191.2200 +        else {
191.2201 +            needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
191.2202 +                || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
191.2203 +                || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
191.2204 +                || affix.indexOf(PATTERN_PERCENT) >= 0
191.2205 +                || affix.indexOf(PATTERN_PER_MILLE) >= 0
191.2206 +                || affix.indexOf(PATTERN_DIGIT) >= 0
191.2207 +                || affix.indexOf(PATTERN_SEPARATOR) >= 0
191.2208 +                || affix.indexOf(PATTERN_MINUS) >= 0
191.2209 +                || affix.indexOf(CURRENCY_SIGN) >= 0;
191.2210 +        }
191.2211 +        if (needQuote) buffer.append('\'');
191.2212 +        if (affix.indexOf('\'') < 0) buffer.append(affix);
191.2213 +        else {
191.2214 +            for (int j=0; j<affix.length(); ++j) {
191.2215 +                char c = affix.charAt(j);
191.2216 +                buffer.append(c);
191.2217 +                if (c == '\'') buffer.append(c);
191.2218 +            }
191.2219 +        }
191.2220 +        if (needQuote) buffer.append('\'');
191.2221 +    }
191.2222 +
191.2223 +    /**
191.2224 +     * Does the real work of generating a pattern.  */
191.2225 +    private String toPattern(boolean localized) {
191.2226 +        StringBuffer result = new StringBuffer();
191.2227 +        for (int j = 1; j >= 0; --j) {
191.2228 +            if (j == 1)
191.2229 +                appendAffix(result, posPrefixPattern, positivePrefix, localized);
191.2230 +            else appendAffix(result, negPrefixPattern, negativePrefix, localized);
191.2231 +            int i;
191.2232 +            int digitCount = useExponentialNotation
191.2233 +                        ? getMaximumIntegerDigits()
191.2234 +                        : Math.max(groupingSize, getMinimumIntegerDigits())+1;
191.2235 +            for (i = digitCount; i > 0; --i) {
191.2236 +                if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
191.2237 +                    i % groupingSize == 0) {
191.2238 +                    result.append(localized ? symbols.getGroupingSeparator() :
191.2239 +                                  PATTERN_GROUPING_SEPARATOR);
191.2240 +                }
191.2241 +                result.append(i <= getMinimumIntegerDigits()
191.2242 +                    ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
191.2243 +                    : (localized ? symbols.getDigit() : PATTERN_DIGIT));
191.2244 +            }
191.2245 +            if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
191.2246 +                result.append(localized ? symbols.getDecimalSeparator() :
191.2247 +                              PATTERN_DECIMAL_SEPARATOR);
191.2248 +            for (i = 0; i < getMaximumFractionDigits(); ++i) {
191.2249 +                if (i < getMinimumFractionDigits()) {
191.2250 +                    result.append(localized ? symbols.getZeroDigit() :
191.2251 +                                  PATTERN_ZERO_DIGIT);
191.2252 +                } else {
191.2253 +                    result.append(localized ? symbols.getDigit() :
191.2254 +                                  PATTERN_DIGIT);
191.2255 +                }
191.2256 +            }
191.2257 +        if (useExponentialNotation)
191.2258 +        {
191.2259 +            result.append(localized ? symbols.getExponentSeparator() :
191.2260 +                  PATTERN_EXPONENT);
191.2261 +        for (i=0; i<minExponentDigits; ++i)
191.2262 +                    result.append(localized ? symbols.getZeroDigit() :
191.2263 +                                  PATTERN_ZERO_DIGIT);
191.2264 +        }
191.2265 +            if (j == 1) {
191.2266 +                appendAffix(result, posSuffixPattern, positiveSuffix, localized);
191.2267 +                if ((negSuffixPattern == posSuffixPattern && // n == p == null
191.2268 +                     negativeSuffix.equals(positiveSuffix))
191.2269 +                    || (negSuffixPattern != null &&
191.2270 +                        negSuffixPattern.equals(posSuffixPattern))) {
191.2271 +                    if ((negPrefixPattern != null && posPrefixPattern != null &&
191.2272 +                         negPrefixPattern.equals("'-" + posPrefixPattern)) ||
191.2273 +                        (negPrefixPattern == posPrefixPattern && // n == p == null
191.2274 +                         negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
191.2275 +                        break;
191.2276 +                }
191.2277 +                result.append(localized ? symbols.getPatternSeparator() :
191.2278 +                              PATTERN_SEPARATOR);
191.2279 +            } else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
191.2280 +        }
191.2281 +        return result.toString();
191.2282 +    }
191.2283 +
191.2284 +    /**
191.2285 +     * Apply the given pattern to this Format object.  A pattern is a
191.2286 +     * short-hand specification for the various formatting properties.
191.2287 +     * These properties can also be changed individually through the
191.2288 +     * various setter methods.
191.2289 +     * <p>
191.2290 +     * There is no limit to integer digits set
191.2291 +     * by this routine, since that is the typical end-user desire;
191.2292 +     * use setMaximumInteger if you want to set a real value.
191.2293 +     * For negative numbers, use a second pattern, separated by a semicolon
191.2294 +     * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
191.2295 +     * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
191.2296 +     * a maximum of 2 fraction digits.
191.2297 +     * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
191.2298 +     * parentheses.
191.2299 +     * <p>In negative patterns, the minimum and maximum counts are ignored;
191.2300 +     * these are presumed to be set in the positive pattern.
191.2301 +     *
191.2302 +     * @exception NullPointerException if <code>pattern</code> is null
191.2303 +     * @exception IllegalArgumentException if the given pattern is invalid.
191.2304 +     */
191.2305 +    public void applyPattern(String pattern) {
191.2306 +        applyPattern(pattern, false);
191.2307 +    }
191.2308 +
191.2309 +    /**
191.2310 +     * Apply the given pattern to this Format object.  The pattern
191.2311 +     * is assumed to be in a localized notation. A pattern is a
191.2312 +     * short-hand specification for the various formatting properties.
191.2313 +     * These properties can also be changed individually through the
191.2314 +     * various setter methods.
191.2315 +     * <p>
191.2316 +     * There is no limit to integer digits set
191.2317 +     * by this routine, since that is the typical end-user desire;
191.2318 +     * use setMaximumInteger if you want to set a real value.
191.2319 +     * For negative numbers, use a second pattern, separated by a semicolon
191.2320 +     * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
191.2321 +     * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
191.2322 +     * a maximum of 2 fraction digits.
191.2323 +     * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
191.2324 +     * parentheses.
191.2325 +     * <p>In negative patterns, the minimum and maximum counts are ignored;
191.2326 +     * these are presumed to be set in the positive pattern.
191.2327 +     *
191.2328 +     * @exception NullPointerException if <code>pattern</code> is null
191.2329 +     * @exception IllegalArgumentException if the given pattern is invalid.
191.2330 +     */
191.2331 +    public void applyLocalizedPattern(String pattern) {
191.2332 +        applyPattern(pattern, true);
191.2333 +    }
191.2334 +
191.2335 +    /**
191.2336 +     * Does the real work of applying a pattern.
191.2337 +     */
191.2338 +    private void applyPattern(String pattern, boolean localized) {
191.2339 +        char zeroDigit         = PATTERN_ZERO_DIGIT;
191.2340 +        char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
191.2341 +        char decimalSeparator  = PATTERN_DECIMAL_SEPARATOR;
191.2342 +        char percent           = PATTERN_PERCENT;
191.2343 +        char perMill           = PATTERN_PER_MILLE;
191.2344 +        char digit             = PATTERN_DIGIT;
191.2345 +        char separator         = PATTERN_SEPARATOR;
191.2346 +        String exponent          = PATTERN_EXPONENT;
191.2347 +        char minus             = PATTERN_MINUS;
191.2348 +        if (localized) {
191.2349 +            zeroDigit         = symbols.getZeroDigit();
191.2350 +            groupingSeparator = symbols.getGroupingSeparator();
191.2351 +            decimalSeparator  = symbols.getDecimalSeparator();
191.2352 +            percent           = symbols.getPercent();
191.2353 +            perMill           = symbols.getPerMill();
191.2354 +            digit             = symbols.getDigit();
191.2355 +            separator         = symbols.getPatternSeparator();
191.2356 +            exponent          = symbols.getExponentSeparator();
191.2357 +            minus             = symbols.getMinusSign();
191.2358 +        }
191.2359 +        boolean gotNegative = false;
191.2360 +        decimalSeparatorAlwaysShown = false;
191.2361 +        isCurrencyFormat = false;
191.2362 +        useExponentialNotation = false;
191.2363 +
191.2364 +        // Two variables are used to record the subrange of the pattern
191.2365 +        // occupied by phase 1.  This is used during the processing of the
191.2366 +        // second pattern (the one representing negative numbers) to ensure
191.2367 +        // that no deviation exists in phase 1 between the two patterns.
191.2368 +        int phaseOneStart = 0;
191.2369 +        int phaseOneLength = 0;
191.2370 +
191.2371 +        int start = 0;
191.2372 +        for (int j = 1; j >= 0 && start < pattern.length(); --j) {
191.2373 +            boolean inQuote = false;
191.2374 +            StringBuffer prefix = new StringBuffer();
191.2375 +            StringBuffer suffix = new StringBuffer();
191.2376 +            int decimalPos = -1;
191.2377 +            int multiplier = 1;
191.2378 +            int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
191.2379 +            byte groupingCount = -1;
191.2380 +
191.2381 +            // The phase ranges from 0 to 2.  Phase 0 is the prefix.  Phase 1 is
191.2382 +            // the section of the pattern with digits, decimal separator,
191.2383 +            // grouping characters.  Phase 2 is the suffix.  In phases 0 and 2,
191.2384 +            // percent, per mille, and currency symbols are recognized and
191.2385 +            // translated.  The separation of the characters into phases is
191.2386 +            // strictly enforced; if phase 1 characters are to appear in the
191.2387 +            // suffix, for example, they must be quoted.
191.2388 +            int phase = 0;
191.2389 +
191.2390 +            // The affix is either the prefix or the suffix.
191.2391 +            StringBuffer affix = prefix;
191.2392 +
191.2393 +            for (int pos = start; pos < pattern.length(); ++pos) {
191.2394 +                char ch = pattern.charAt(pos);
191.2395 +                switch (phase) {
191.2396 +                case 0:
191.2397 +                case 2:
191.2398 +                    // Process the prefix / suffix characters
191.2399 +                    if (inQuote) {
191.2400 +                        // A quote within quotes indicates either the closing
191.2401 +                        // quote or two quotes, which is a quote literal. That
191.2402 +                        // is, we have the second quote in 'do' or 'don''t'.
191.2403 +                        if (ch == QUOTE) {
191.2404 +                            if ((pos+1) < pattern.length() &&
191.2405 +                                pattern.charAt(pos+1) == QUOTE) {
191.2406 +                                ++pos;
191.2407 +                                affix.append("''"); // 'don''t'
191.2408 +                            } else {
191.2409 +                                inQuote = false; // 'do'
191.2410 +                            }
191.2411 +                            continue;
191.2412 +                        }
191.2413 +                    } else {
191.2414 +                        // Process unquoted characters seen in prefix or suffix
191.2415 +                        // phase.
191.2416 +                        if (ch == digit ||
191.2417 +                            ch == zeroDigit ||
191.2418 +                            ch == groupingSeparator ||
191.2419 +                            ch == decimalSeparator) {
191.2420 +                            phase = 1;
191.2421 +                            if (j == 1) {
191.2422 +                                phaseOneStart = pos;
191.2423 +                            }
191.2424 +                            --pos; // Reprocess this character
191.2425 +                            continue;
191.2426 +                        } else if (ch == CURRENCY_SIGN) {
191.2427 +                            // Use lookahead to determine if the currency sign
191.2428 +                            // is doubled or not.
191.2429 +                            boolean doubled = (pos + 1) < pattern.length() &&
191.2430 +                                pattern.charAt(pos + 1) == CURRENCY_SIGN;
191.2431 +                            if (doubled) { // Skip over the doubled character
191.2432 +                             ++pos;
191.2433 +                            }
191.2434 +                            isCurrencyFormat = true;
191.2435 +                            affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
191.2436 +                            continue;
191.2437 +                        } else if (ch == QUOTE) {
191.2438 +                            // A quote outside quotes indicates either the
191.2439 +                            // opening quote or two quotes, which is a quote
191.2440 +                            // literal. That is, we have the first quote in 'do'
191.2441 +                            // or o''clock.
191.2442 +                            if (ch == QUOTE) {
191.2443 +                                if ((pos+1) < pattern.length() &&
191.2444 +                                    pattern.charAt(pos+1) == QUOTE) {
191.2445 +                                    ++pos;
191.2446 +                                    affix.append("''"); // o''clock
191.2447 +                                } else {
191.2448 +                                    inQuote = true; // 'do'
191.2449 +                                }
191.2450 +                                continue;
191.2451 +                            }
191.2452 +                        } else if (ch == separator) {
191.2453 +                            // Don't allow separators before we see digit
191.2454 +                            // characters of phase 1, and don't allow separators
191.2455 +                            // in the second pattern (j == 0).
191.2456 +                            if (phase == 0 || j == 0) {
191.2457 +                                throw new IllegalArgumentException("Unquoted special character '" +
191.2458 +                                    ch + "' in pattern \"" + pattern + '"');
191.2459 +                            }
191.2460 +                            start = pos + 1;
191.2461 +                            pos = pattern.length();
191.2462 +                            continue;
191.2463 +                        }
191.2464 +
191.2465 +                        // Next handle characters which are appended directly.
191.2466 +                        else if (ch == percent) {
191.2467 +                            if (multiplier != 1) {
191.2468 +                                throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
191.2469 +                                    pattern + '"');
191.2470 +                            }
191.2471 +                            multiplier = 100;
191.2472 +                            affix.append("'%");
191.2473 +                            continue;
191.2474 +                        } else if (ch == perMill) {
191.2475 +                            if (multiplier != 1) {
191.2476 +                                throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
191.2477 +                                    pattern + '"');
191.2478 +                            }
191.2479 +                            multiplier = 1000;
191.2480 +                            affix.append("'\u2030");
191.2481 +                            continue;
191.2482 +                        } else if (ch == minus) {
191.2483 +                            affix.append("'-");
191.2484 +                            continue;
191.2485 +                        }
191.2486 +                    }
191.2487 +                    // Note that if we are within quotes, or if this is an
191.2488 +                    // unquoted, non-special character, then we usually fall
191.2489 +                    // through to here.
191.2490 +                    affix.append(ch);
191.2491 +                    break;
191.2492 +
191.2493 +                case 1:
191.2494 +                    // Phase one must be identical in the two sub-patterns. We
191.2495 +                    // enforce this by doing a direct comparison. While
191.2496 +                    // processing the first sub-pattern, we just record its
191.2497 +                    // length. While processing the second, we compare
191.2498 +                    // characters.
191.2499 +                    if (j == 1) {
191.2500 +                        ++phaseOneLength;
191.2501 +                    } else {
191.2502 +                        if (--phaseOneLength == 0) {
191.2503 +                            phase = 2;
191.2504 +                            affix = suffix;
191.2505 +                        }
191.2506 +                        continue;
191.2507 +                    }
191.2508 +
191.2509 +                    // Process the digits, decimal, and grouping characters. We
191.2510 +                    // record five pieces of information. We expect the digits
191.2511 +                    // to occur in the pattern ####0000.####, and we record the
191.2512 +                    // number of left digits, zero (central) digits, and right
191.2513 +                    // digits. The position of the last grouping character is
191.2514 +                    // recorded (should be somewhere within the first two blocks
191.2515 +                    // of characters), as is the position of the decimal point,
191.2516 +                    // if any (should be in the zero digits). If there is no
191.2517 +                    // decimal point, then there should be no right digits.
191.2518 +                    if (ch == digit) {
191.2519 +                        if (zeroDigitCount > 0) {
191.2520 +                            ++digitRightCount;
191.2521 +                        } else {
191.2522 +                            ++digitLeftCount;
191.2523 +                        }
191.2524 +                        if (groupingCount >= 0 && decimalPos < 0) {
191.2525 +                            ++groupingCount;
191.2526 +                        }
191.2527 +                    } else if (ch == zeroDigit) {
191.2528 +                        if (digitRightCount > 0) {
191.2529 +                            throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
191.2530 +                                pattern + '"');
191.2531 +                        }
191.2532 +                        ++zeroDigitCount;
191.2533 +                        if (groupingCount >= 0 && decimalPos < 0) {
191.2534 +                            ++groupingCount;
191.2535 +                        }
191.2536 +                    } else if (ch == groupingSeparator) {
191.2537 +                        groupingCount = 0;
191.2538 +                    } else if (ch == decimalSeparator) {
191.2539 +                        if (decimalPos >= 0) {
191.2540 +                            throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
191.2541 +                                pattern + '"');
191.2542 +                        }
191.2543 +                        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
191.2544 +                    } else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){
191.2545 +                        if (useExponentialNotation) {
191.2546 +                            throw new IllegalArgumentException("Multiple exponential " +
191.2547 +                                "symbols in pattern \"" + pattern + '"');
191.2548 +                        }
191.2549 +                        useExponentialNotation = true;
191.2550 +                        minExponentDigits = 0;
191.2551 +
191.2552 +                        // Use lookahead to parse out the exponential part
191.2553 +                        // of the pattern, then jump into phase 2.
191.2554 +                        pos = pos+exponent.length();
191.2555 +                         while (pos < pattern.length() &&
191.2556 +                               pattern.charAt(pos) == zeroDigit) {
191.2557 +                            ++minExponentDigits;
191.2558 +                            ++phaseOneLength;
191.2559 +                            ++pos;
191.2560 +                        }
191.2561 +
191.2562 +                        if ((digitLeftCount + zeroDigitCount) < 1 ||
191.2563 +                            minExponentDigits < 1) {
191.2564 +                            throw new IllegalArgumentException("Malformed exponential " +
191.2565 +                                "pattern \"" + pattern + '"');
191.2566 +                        }
191.2567 +
191.2568 +                        // Transition to phase 2
191.2569 +                        phase = 2;
191.2570 +                        affix = suffix;
191.2571 +                        --pos;
191.2572 +                        continue;
191.2573 +                    } else {
191.2574 +                        phase = 2;
191.2575 +                        affix = suffix;
191.2576 +                        --pos;
191.2577 +                        --phaseOneLength;
191.2578 +                        continue;
191.2579 +                    }
191.2580 +                    break;
191.2581 +                }
191.2582 +            }
191.2583 +
191.2584 +            // Handle patterns with no '0' pattern character. These patterns
191.2585 +            // are legal, but must be interpreted.  "##.###" -> "#0.###".
191.2586 +            // ".###" -> ".0##".
191.2587 +            /* We allow patterns of the form "####" to produce a zeroDigitCount
191.2588 +             * of zero (got that?); although this seems like it might make it
191.2589 +             * possible for format() to produce empty strings, format() checks
191.2590 +             * for this condition and outputs a zero digit in this situation.
191.2591 +             * Having a zeroDigitCount of zero yields a minimum integer digits
191.2592 +             * of zero, which allows proper round-trip patterns.  That is, we
191.2593 +             * don't want "#" to become "#0" when toPattern() is called (even
191.2594 +             * though that's what it really is, semantically).
191.2595 +             */
191.2596 +            if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
191.2597 +                // Handle "###.###" and "###." and ".###"
191.2598 +                int n = decimalPos;
191.2599 +                if (n == 0) { // Handle ".###"
191.2600 +                    ++n;
191.2601 +                }
191.2602 +                digitRightCount = digitLeftCount - n;
191.2603 +                digitLeftCount = n - 1;
191.2604 +                zeroDigitCount = 1;
191.2605 +            }
191.2606 +
191.2607 +            // Do syntax checking on the digits.
191.2608 +            if ((decimalPos < 0 && digitRightCount > 0) ||
191.2609 +                (decimalPos >= 0 && (decimalPos < digitLeftCount ||
191.2610 +                 decimalPos > (digitLeftCount + zeroDigitCount))) ||
191.2611 +                 groupingCount == 0 || inQuote) {
191.2612 +                throw new IllegalArgumentException("Malformed pattern \"" +
191.2613 +                    pattern + '"');
191.2614 +            }
191.2615 +
191.2616 +            if (j == 1) {
191.2617 +                posPrefixPattern = prefix.toString();
191.2618 +                posSuffixPattern = suffix.toString();
191.2619 +                negPrefixPattern = posPrefixPattern;   // assume these for now
191.2620 +                negSuffixPattern = posSuffixPattern;
191.2621 +                int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
191.2622 +                /* The effectiveDecimalPos is the position the decimal is at or
191.2623 +                 * would be at if there is no decimal. Note that if decimalPos<0,
191.2624 +                 * then digitTotalCount == digitLeftCount + zeroDigitCount.
191.2625 +                 */
191.2626 +                int effectiveDecimalPos = decimalPos >= 0 ?
191.2627 +                    decimalPos : digitTotalCount;
191.2628 +                setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
191.2629 +                setMaximumIntegerDigits(useExponentialNotation ?
191.2630 +                    digitLeftCount + getMinimumIntegerDigits() :
191.2631 +                    MAXIMUM_INTEGER_DIGITS);
191.2632 +                setMaximumFractionDigits(decimalPos >= 0 ?
191.2633 +                    (digitTotalCount - decimalPos) : 0);
191.2634 +                setMinimumFractionDigits(decimalPos >= 0 ?
191.2635 +                    (digitLeftCount + zeroDigitCount - decimalPos) : 0);
191.2636 +                setGroupingUsed(groupingCount > 0);
191.2637 +                this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
191.2638 +                this.multiplier = multiplier;
191.2639 +                setDecimalSeparatorAlwaysShown(decimalPos == 0 ||
191.2640 +                    decimalPos == digitTotalCount);
191.2641 +            } else {
191.2642 +                negPrefixPattern = prefix.toString();
191.2643 +                negSuffixPattern = suffix.toString();
191.2644 +                gotNegative = true;
191.2645 +            }
191.2646 +        }
191.2647 +
191.2648 +        if (pattern.length() == 0) {
191.2649 +            posPrefixPattern = posSuffixPattern = "";
191.2650 +            setMinimumIntegerDigits(0);
191.2651 +            setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
191.2652 +            setMinimumFractionDigits(0);
191.2653 +            setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
191.2654 +        }
191.2655 +
191.2656 +        // If there was no negative pattern, or if the negative pattern is
191.2657 +        // identical to the positive pattern, then prepend the minus sign to
191.2658 +        // the positive pattern to form the negative pattern.
191.2659 +        if (!gotNegative ||
191.2660 +            (negPrefixPattern.equals(posPrefixPattern)
191.2661 +             && negSuffixPattern.equals(posSuffixPattern))) {
191.2662 +            negSuffixPattern = posSuffixPattern;
191.2663 +            negPrefixPattern = "'-" + posPrefixPattern;
191.2664 +        }
191.2665 +
191.2666 +        expandAffixes();
191.2667 +    }
191.2668 +
191.2669 +    /**
191.2670 +     * Sets the maximum number of digits allowed in the integer portion of a
191.2671 +     * number.
191.2672 +     * For formatting numbers other than <code>BigInteger</code> and
191.2673 +     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
191.2674 +     * 309 is used. Negative input values are replaced with 0.
191.2675 +     * @see NumberFormat#setMaximumIntegerDigits
191.2676 +     */
191.2677 +    public void setMaximumIntegerDigits(int newValue) {
191.2678 +        maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
191.2679 +        super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
191.2680 +            DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
191.2681 +        if (minimumIntegerDigits > maximumIntegerDigits) {
191.2682 +            minimumIntegerDigits = maximumIntegerDigits;
191.2683 +            super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
191.2684 +                DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
191.2685 +        }
191.2686 +    }
191.2687 +
191.2688 +    /**
191.2689 +     * Sets the minimum number of digits allowed in the integer portion of a
191.2690 +     * number.
191.2691 +     * For formatting numbers other than <code>BigInteger</code> and
191.2692 +     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
191.2693 +     * 309 is used. Negative input values are replaced with 0.
191.2694 +     * @see NumberFormat#setMinimumIntegerDigits
191.2695 +     */
191.2696 +    public void setMinimumIntegerDigits(int newValue) {
191.2697 +        minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
191.2698 +        super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
191.2699 +            DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
191.2700 +        if (minimumIntegerDigits > maximumIntegerDigits) {
191.2701 +            maximumIntegerDigits = minimumIntegerDigits;
191.2702 +            super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
191.2703 +                DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
191.2704 +        }
191.2705 +    }
191.2706 +
191.2707 +    /**
191.2708 +     * Sets the maximum number of digits allowed in the fraction portion of a
191.2709 +     * number.
191.2710 +     * For formatting numbers other than <code>BigInteger</code> and
191.2711 +     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
191.2712 +     * 340 is used. Negative input values are replaced with 0.
191.2713 +     * @see NumberFormat#setMaximumFractionDigits
191.2714 +     */
191.2715 +    public void setMaximumFractionDigits(int newValue) {
191.2716 +        maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
191.2717 +        super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
191.2718 +            DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
191.2719 +        if (minimumFractionDigits > maximumFractionDigits) {
191.2720 +            minimumFractionDigits = maximumFractionDigits;
191.2721 +            super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
191.2722 +                DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
191.2723 +        }
191.2724 +    }
191.2725 +
191.2726 +    /**
191.2727 +     * Sets the minimum number of digits allowed in the fraction portion of a
191.2728 +     * number.
191.2729 +     * For formatting numbers other than <code>BigInteger</code> and
191.2730 +     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
191.2731 +     * 340 is used. Negative input values are replaced with 0.
191.2732 +     * @see NumberFormat#setMinimumFractionDigits
191.2733 +     */
191.2734 +    public void setMinimumFractionDigits(int newValue) {
191.2735 +        minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
191.2736 +        super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
191.2737 +            DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
191.2738 +        if (minimumFractionDigits > maximumFractionDigits) {
191.2739 +            maximumFractionDigits = minimumFractionDigits;
191.2740 +            super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
191.2741 +                DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
191.2742 +        }
191.2743 +    }
191.2744 +
191.2745 +    /**
191.2746 +     * Gets the maximum number of digits allowed in the integer portion of a
191.2747 +     * number.
191.2748 +     * For formatting numbers other than <code>BigInteger</code> and
191.2749 +     * <code>BigDecimal</code> objects, the lower of the return value and
191.2750 +     * 309 is used.
191.2751 +     * @see #setMaximumIntegerDigits
191.2752 +     */
191.2753 +    public int getMaximumIntegerDigits() {
191.2754 +        return maximumIntegerDigits;
191.2755 +    }
191.2756 +
191.2757 +    /**
191.2758 +     * Gets the minimum number of digits allowed in the integer portion of a
191.2759 +     * number.
191.2760 +     * For formatting numbers other than <code>BigInteger</code> and
191.2761 +     * <code>BigDecimal</code> objects, the lower of the return value and
191.2762 +     * 309 is used.
191.2763 +     * @see #setMinimumIntegerDigits
191.2764 +     */
191.2765 +    public int getMinimumIntegerDigits() {
191.2766 +        return minimumIntegerDigits;
191.2767 +    }
191.2768 +
191.2769 +    /**
191.2770 +     * Gets the maximum number of digits allowed in the fraction portion of a
191.2771 +     * number.
191.2772 +     * For formatting numbers other than <code>BigInteger</code> and
191.2773 +     * <code>BigDecimal</code> objects, the lower of the return value and
191.2774 +     * 340 is used.
191.2775 +     * @see #setMaximumFractionDigits
191.2776 +     */
191.2777 +    public int getMaximumFractionDigits() {
191.2778 +        return maximumFractionDigits;
191.2779 +    }
191.2780 +
191.2781 +    /**
191.2782 +     * Gets the minimum number of digits allowed in the fraction portion of a
191.2783 +     * number.
191.2784 +     * For formatting numbers other than <code>BigInteger</code> and
191.2785 +     * <code>BigDecimal</code> objects, the lower of the return value and
191.2786 +     * 340 is used.
191.2787 +     * @see #setMinimumFractionDigits
191.2788 +     */
191.2789 +    public int getMinimumFractionDigits() {
191.2790 +        return minimumFractionDigits;
191.2791 +    }
191.2792 +
191.2793 +    /**
191.2794 +     * Gets the currency used by this decimal format when formatting
191.2795 +     * currency values.
191.2796 +     * The currency is obtained by calling
191.2797 +     * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
191.2798 +     * on this number format's symbols.
191.2799 +     *
191.2800 +     * @return the currency used by this decimal format, or <code>null</code>
191.2801 +     * @since 1.4
191.2802 +     */
191.2803 +    public Currency getCurrency() {
191.2804 +        return symbols.getCurrency();
191.2805 +    }
191.2806 +
191.2807 +    /**
191.2808 +     * Sets the currency used by this number format when formatting
191.2809 +     * currency values. This does not update the minimum or maximum
191.2810 +     * number of fraction digits used by the number format.
191.2811 +     * The currency is set by calling
191.2812 +     * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
191.2813 +     * on this number format's symbols.
191.2814 +     *
191.2815 +     * @param currency the new currency to be used by this decimal format
191.2816 +     * @exception NullPointerException if <code>currency</code> is null
191.2817 +     * @since 1.4
191.2818 +     */
191.2819 +    public void setCurrency(Currency currency) {
191.2820 +        if (currency != symbols.getCurrency()) {
191.2821 +            symbols.setCurrency(currency);
191.2822 +            if (isCurrencyFormat) {
191.2823 +                expandAffixes();
191.2824 +            }
191.2825 +        }
191.2826 +    }
191.2827 +
191.2828 +    /**
191.2829 +     * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
191.2830 +     *
191.2831 +     * @return The <code>RoundingMode</code> used for this DecimalFormat.
191.2832 +     * @see #setRoundingMode(RoundingMode)
191.2833 +     * @since 1.6
191.2834 +     */
191.2835 +    public RoundingMode getRoundingMode() {
191.2836 +        return roundingMode;
191.2837 +    }
191.2838 +
191.2839 +    /**
191.2840 +     * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
191.2841 +     *
191.2842 +     * @param roundingMode The <code>RoundingMode</code> to be used
191.2843 +     * @see #getRoundingMode()
191.2844 +     * @exception NullPointerException if <code>roundingMode</code> is null.
191.2845 +     * @since 1.6
191.2846 +     */
191.2847 +    public void setRoundingMode(RoundingMode roundingMode) {
191.2848 +        if (roundingMode == null) {
191.2849 +            throw new NullPointerException();
191.2850 +        }
191.2851 +
191.2852 +        this.roundingMode = roundingMode;
191.2853 +        digitList.setRoundingMode(roundingMode);
191.2854 +    }
191.2855 +
191.2856 +    /**
191.2857 +     * Adjusts the minimum and maximum fraction digits to values that
191.2858 +     * are reasonable for the currency's default fraction digits.
191.2859 +     */
191.2860 +    void adjustForCurrencyDefaultFractionDigits() {
191.2861 +        Currency currency = symbols.getCurrency();
191.2862 +        if (currency == null) {
191.2863 +            try {
191.2864 +                currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
191.2865 +            } catch (IllegalArgumentException e) {
191.2866 +            }
191.2867 +        }
191.2868 +        if (currency != null) {
191.2869 +            int digits = currency.getDefaultFractionDigits();
191.2870 +            if (digits != -1) {
191.2871 +                int oldMinDigits = getMinimumFractionDigits();
191.2872 +                // Common patterns are "#.##", "#.00", "#".
191.2873 +                // Try to adjust all of them in a reasonable way.
191.2874 +                if (oldMinDigits == getMaximumFractionDigits()) {
191.2875 +                    setMinimumFractionDigits(digits);
191.2876 +                    setMaximumFractionDigits(digits);
191.2877 +                } else {
191.2878 +                    setMinimumFractionDigits(Math.min(digits, oldMinDigits));
191.2879 +                    setMaximumFractionDigits(digits);
191.2880 +                }
191.2881 +            }
191.2882 +        }
191.2883 +    }
191.2884 +
191.2885 +    /**
191.2886 +     * Reads the default serializable fields from the stream and performs
191.2887 +     * validations and adjustments for older serialized versions. The
191.2888 +     * validations and adjustments are:
191.2889 +     * <ol>
191.2890 +     * <li>
191.2891 +     * Verify that the superclass's digit count fields correctly reflect
191.2892 +     * the limits imposed on formatting numbers other than
191.2893 +     * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
191.2894 +     * limits are stored in the superclass for serialization compatibility
191.2895 +     * with older versions, while the limits for <code>BigInteger</code> and
191.2896 +     * <code>BigDecimal</code> objects are kept in this class.
191.2897 +     * If, in the superclass, the minimum or maximum integer digit count is
191.2898 +     * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
191.2899 +     * maximum fraction digit count is larger than
191.2900 +     * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
191.2901 +     * and this method throws an <code>InvalidObjectException</code>.
191.2902 +     * <li>
191.2903 +     * If <code>serialVersionOnStream</code> is less than 4, initialize
191.2904 +     * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
191.2905 +     * RoundingMode.HALF_EVEN}.  This field is new with version 4.
191.2906 +     * <li>
191.2907 +     * If <code>serialVersionOnStream</code> is less than 3, then call
191.2908 +     * the setters for the minimum and maximum integer and fraction digits with
191.2909 +     * the values of the corresponding superclass getters to initialize the
191.2910 +     * fields in this class. The fields in this class are new with version 3.
191.2911 +     * <li>
191.2912 +     * If <code>serialVersionOnStream</code> is less than 1, indicating that
191.2913 +     * the stream was written by JDK 1.1, initialize
191.2914 +     * <code>useExponentialNotation</code>
191.2915 +     * to false, since it was not present in JDK 1.1.
191.2916 +     * <li>
191.2917 +     * Set <code>serialVersionOnStream</code> to the maximum allowed value so
191.2918 +     * that default serialization will work properly if this object is streamed
191.2919 +     * out again.
191.2920 +     * </ol>
191.2921 +     *
191.2922 +     * <p>Stream versions older than 2 will not have the affix pattern variables
191.2923 +     * <code>posPrefixPattern</code> etc.  As a result, they will be initialized
191.2924 +     * to <code>null</code>, which means the affix strings will be taken as
191.2925 +     * literal values.  This is exactly what we want, since that corresponds to
191.2926 +     * the pre-version-2 behavior.
191.2927 +     */
191.2928 +    private void readObject(ObjectInputStream stream)
191.2929 +         throws IOException, ClassNotFoundException
191.2930 +    {
191.2931 +        stream.defaultReadObject();
191.2932 +        digitList = new DigitList();
191.2933 +
191.2934 +        if (serialVersionOnStream < 4) {
191.2935 +            setRoundingMode(RoundingMode.HALF_EVEN);
191.2936 +        }
191.2937 +        // We only need to check the maximum counts because NumberFormat
191.2938 +        // .readObject has already ensured that the maximum is greater than the
191.2939 +        // minimum count.
191.2940 +        if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
191.2941 +            super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
191.2942 +            throw new InvalidObjectException("Digit count out of range");
191.2943 +        }
191.2944 +        if (serialVersionOnStream < 3) {
191.2945 +            setMaximumIntegerDigits(super.getMaximumIntegerDigits());
191.2946 +            setMinimumIntegerDigits(super.getMinimumIntegerDigits());
191.2947 +            setMaximumFractionDigits(super.getMaximumFractionDigits());
191.2948 +            setMinimumFractionDigits(super.getMinimumFractionDigits());
191.2949 +        }
191.2950 +        if (serialVersionOnStream < 1) {
191.2951 +            // Didn't have exponential fields
191.2952 +            useExponentialNotation = false;
191.2953 +        }
191.2954 +        serialVersionOnStream = currentSerialVersion;
191.2955 +    }
191.2956 +
191.2957 +    //----------------------------------------------------------------------
191.2958 +    // INSTANCE VARIABLES
191.2959 +    //----------------------------------------------------------------------
191.2960 +
191.2961 +    private transient DigitList digitList = new DigitList();
191.2962 +
191.2963 +    /**
191.2964 +     * The symbol used as a prefix when formatting positive numbers, e.g. "+".
191.2965 +     *
191.2966 +     * @serial
191.2967 +     * @see #getPositivePrefix
191.2968 +     */
191.2969 +    private String  positivePrefix = "";
191.2970 +
191.2971 +    /**
191.2972 +     * The symbol used as a suffix when formatting positive numbers.
191.2973 +     * This is often an empty string.
191.2974 +     *
191.2975 +     * @serial
191.2976 +     * @see #getPositiveSuffix
191.2977 +     */
191.2978 +    private String  positiveSuffix = "";
191.2979 +
191.2980 +    /**
191.2981 +     * The symbol used as a prefix when formatting negative numbers, e.g. "-".
191.2982 +     *
191.2983 +     * @serial
191.2984 +     * @see #getNegativePrefix
191.2985 +     */
191.2986 +    private String  negativePrefix = "-";
191.2987 +
191.2988 +    /**
191.2989 +     * The symbol used as a suffix when formatting negative numbers.
191.2990 +     * This is often an empty string.
191.2991 +     *
191.2992 +     * @serial
191.2993 +     * @see #getNegativeSuffix
191.2994 +     */
191.2995 +    private String  negativeSuffix = "";
191.2996 +
191.2997 +    /**
191.2998 +     * The prefix pattern for non-negative numbers.  This variable corresponds
191.2999 +     * to <code>positivePrefix</code>.
191.3000 +     *
191.3001 +     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
191.3002 +     * <code>positivePrefix</code> to update the latter to reflect changes in
191.3003 +     * <code>symbols</code>.  If this variable is <code>null</code> then
191.3004 +     * <code>positivePrefix</code> is taken as a literal value that does not
191.3005 +     * change when <code>symbols</code> changes.  This variable is always
191.3006 +     * <code>null</code> for <code>DecimalFormat</code> objects older than
191.3007 +     * stream version 2 restored from stream.
191.3008 +     *
191.3009 +     * @serial
191.3010 +     * @since 1.3
191.3011 +     */
191.3012 +    private String posPrefixPattern;
191.3013 +
191.3014 +    /**
191.3015 +     * The suffix pattern for non-negative numbers.  This variable corresponds
191.3016 +     * to <code>positiveSuffix</code>.  This variable is analogous to
191.3017 +     * <code>posPrefixPattern</code>; see that variable for further
191.3018 +     * documentation.
191.3019 +     *
191.3020 +     * @serial
191.3021 +     * @since 1.3
191.3022 +     */
191.3023 +    private String posSuffixPattern;
191.3024 +
191.3025 +    /**
191.3026 +     * The prefix pattern for negative numbers.  This variable corresponds
191.3027 +     * to <code>negativePrefix</code>.  This variable is analogous to
191.3028 +     * <code>posPrefixPattern</code>; see that variable for further
191.3029 +     * documentation.
191.3030 +     *
191.3031 +     * @serial
191.3032 +     * @since 1.3
191.3033 +     */
191.3034 +    private String negPrefixPattern;
191.3035 +
191.3036 +    /**
191.3037 +     * The suffix pattern for negative numbers.  This variable corresponds
191.3038 +     * to <code>negativeSuffix</code>.  This variable is analogous to
191.3039 +     * <code>posPrefixPattern</code>; see that variable for further
191.3040 +     * documentation.
191.3041 +     *
191.3042 +     * @serial
191.3043 +     * @since 1.3
191.3044 +     */
191.3045 +    private String negSuffixPattern;
191.3046 +
191.3047 +    /**
191.3048 +     * The multiplier for use in percent, per mille, etc.
191.3049 +     *
191.3050 +     * @serial
191.3051 +     * @see #getMultiplier
191.3052 +     */
191.3053 +    private int     multiplier = 1;
191.3054 +
191.3055 +    /**
191.3056 +     * The number of digits between grouping separators in the integer
191.3057 +     * portion of a number.  Must be greater than 0 if
191.3058 +     * <code>NumberFormat.groupingUsed</code> is true.
191.3059 +     *
191.3060 +     * @serial
191.3061 +     * @see #getGroupingSize
191.3062 +     * @see java.text.NumberFormat#isGroupingUsed
191.3063 +     */
191.3064 +    private byte    groupingSize = 3;  // invariant, > 0 if useThousands
191.3065 +
191.3066 +    /**
191.3067 +     * If true, forces the decimal separator to always appear in a formatted
191.3068 +     * number, even if the fractional part of the number is zero.
191.3069 +     *
191.3070 +     * @serial
191.3071 +     * @see #isDecimalSeparatorAlwaysShown
191.3072 +     */
191.3073 +    private boolean decimalSeparatorAlwaysShown = false;
191.3074 +
191.3075 +    /**
191.3076 +     * If true, parse returns BigDecimal wherever possible.
191.3077 +     *
191.3078 +     * @serial
191.3079 +     * @see #isParseBigDecimal
191.3080 +     * @since 1.5
191.3081 +     */
191.3082 +    private boolean parseBigDecimal = false;
191.3083 +
191.3084 +
191.3085 +    /**
191.3086 +     * True if this object represents a currency format.  This determines
191.3087 +     * whether the monetary decimal separator is used instead of the normal one.
191.3088 +     */
191.3089 +    private transient boolean isCurrencyFormat = false;
191.3090 +
191.3091 +    /**
191.3092 +     * The <code>DecimalFormatSymbols</code> object used by this format.
191.3093 +     * It contains the symbols used to format numbers, e.g. the grouping separator,
191.3094 +     * decimal separator, and so on.
191.3095 +     *
191.3096 +     * @serial
191.3097 +     * @see #setDecimalFormatSymbols
191.3098 +     * @see java.text.DecimalFormatSymbols
191.3099 +     */
191.3100 +    private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
191.3101 +
191.3102 +    /**
191.3103 +     * True to force the use of exponential (i.e. scientific) notation when formatting
191.3104 +     * numbers.
191.3105 +     *
191.3106 +     * @serial
191.3107 +     * @since 1.2
191.3108 +     */
191.3109 +    private boolean useExponentialNotation;  // Newly persistent in the Java 2 platform v.1.2
191.3110 +
191.3111 +    /**
191.3112 +     * FieldPositions describing the positive prefix String. This is
191.3113 +     * lazily created. Use <code>getPositivePrefixFieldPositions</code>
191.3114 +     * when needed.
191.3115 +     */
191.3116 +    private transient FieldPosition[] positivePrefixFieldPositions;
191.3117 +
191.3118 +    /**
191.3119 +     * FieldPositions describing the positive suffix String. This is
191.3120 +     * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
191.3121 +     * when needed.
191.3122 +     */
191.3123 +    private transient FieldPosition[] positiveSuffixFieldPositions;
191.3124 +
191.3125 +    /**
191.3126 +     * FieldPositions describing the negative prefix String. This is
191.3127 +     * lazily created. Use <code>getNegativePrefixFieldPositions</code>
191.3128 +     * when needed.
191.3129 +     */
191.3130 +    private transient FieldPosition[] negativePrefixFieldPositions;
191.3131 +
191.3132 +    /**
191.3133 +     * FieldPositions describing the negative suffix String. This is
191.3134 +     * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
191.3135 +     * when needed.
191.3136 +     */
191.3137 +    private transient FieldPosition[] negativeSuffixFieldPositions;
191.3138 +
191.3139 +    /**
191.3140 +     * The minimum number of digits used to display the exponent when a number is
191.3141 +     * formatted in exponential notation.  This field is ignored if
191.3142 +     * <code>useExponentialNotation</code> is not true.
191.3143 +     *
191.3144 +     * @serial
191.3145 +     * @since 1.2
191.3146 +     */
191.3147 +    private byte    minExponentDigits;       // Newly persistent in the Java 2 platform v.1.2
191.3148 +
191.3149 +    /**
191.3150 +     * The maximum number of digits allowed in the integer portion of a
191.3151 +     * <code>BigInteger</code> or <code>BigDecimal</code> number.
191.3152 +     * <code>maximumIntegerDigits</code> must be greater than or equal to
191.3153 +     * <code>minimumIntegerDigits</code>.
191.3154 +     *
191.3155 +     * @serial
191.3156 +     * @see #getMaximumIntegerDigits
191.3157 +     * @since 1.5
191.3158 +     */
191.3159 +    private int    maximumIntegerDigits = super.getMaximumIntegerDigits();
191.3160 +
191.3161 +    /**
191.3162 +     * The minimum number of digits allowed in the integer portion of a
191.3163 +     * <code>BigInteger</code> or <code>BigDecimal</code> number.
191.3164 +     * <code>minimumIntegerDigits</code> must be less than or equal to
191.3165 +     * <code>maximumIntegerDigits</code>.
191.3166 +     *
191.3167 +     * @serial
191.3168 +     * @see #getMinimumIntegerDigits
191.3169 +     * @since 1.5
191.3170 +     */
191.3171 +    private int    minimumIntegerDigits = super.getMinimumIntegerDigits();
191.3172 +
191.3173 +    /**
191.3174 +     * The maximum number of digits allowed in the fractional portion of a
191.3175 +     * <code>BigInteger</code> or <code>BigDecimal</code> number.
191.3176 +     * <code>maximumFractionDigits</code> must be greater than or equal to
191.3177 +     * <code>minimumFractionDigits</code>.
191.3178 +     *
191.3179 +     * @serial
191.3180 +     * @see #getMaximumFractionDigits
191.3181 +     * @since 1.5
191.3182 +     */
191.3183 +    private int    maximumFractionDigits = super.getMaximumFractionDigits();
191.3184 +
191.3185 +    /**
191.3186 +     * The minimum number of digits allowed in the fractional portion of a
191.3187 +     * <code>BigInteger</code> or <code>BigDecimal</code> number.
191.3188 +     * <code>minimumFractionDigits</code> must be less than or equal to
191.3189 +     * <code>maximumFractionDigits</code>.
191.3190 +     *
191.3191 +     * @serial
191.3192 +     * @see #getMinimumFractionDigits
191.3193 +     * @since 1.5
191.3194 +     */
191.3195 +    private int    minimumFractionDigits = super.getMinimumFractionDigits();
191.3196 +
191.3197 +    /**
191.3198 +     * The {@link java.math.RoundingMode} used in this DecimalFormat.
191.3199 +     *
191.3200 +     * @serial
191.3201 +     * @since 1.6
191.3202 +     */
191.3203 +    private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
191.3204 +
191.3205 +    //----------------------------------------------------------------------
191.3206 +
191.3207 +    static final int currentSerialVersion = 4;
191.3208 +
191.3209 +    /**
191.3210 +     * The internal serial version which says which version was written.
191.3211 +     * Possible values are:
191.3212 +     * <ul>
191.3213 +     * <li><b>0</b> (default): versions before the Java 2 platform v1.2
191.3214 +     * <li><b>1</b>: version for 1.2, which includes the two new fields
191.3215 +     *      <code>useExponentialNotation</code> and
191.3216 +     *      <code>minExponentDigits</code>.
191.3217 +     * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
191.3218 +     *      <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
191.3219 +     *      <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
191.3220 +     * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
191.3221 +     *      <code>maximumIntegerDigits</code>,
191.3222 +     *      <code>minimumIntegerDigits</code>,
191.3223 +     *      <code>maximumFractionDigits</code>,
191.3224 +     *      <code>minimumFractionDigits</code>, and
191.3225 +     *      <code>parseBigDecimal</code>.
191.3226 +     * <li><b>4</b>: version for 1.6 and later, which adds one new field:
191.3227 +     *      <code>roundingMode</code>.
191.3228 +     * </ul>
191.3229 +     * @since 1.2
191.3230 +     * @serial
191.3231 +     */
191.3232 +    private int serialVersionOnStream = currentSerialVersion;
191.3233 +
191.3234 +    //----------------------------------------------------------------------
191.3235 +    // CONSTANTS
191.3236 +    //----------------------------------------------------------------------
191.3237 +
191.3238 +    // Constants for characters used in programmatic (unlocalized) patterns.
191.3239 +    private static final char       PATTERN_ZERO_DIGIT         = '0';
191.3240 +    private static final char       PATTERN_GROUPING_SEPARATOR = ',';
191.3241 +    private static final char       PATTERN_DECIMAL_SEPARATOR  = '.';
191.3242 +    private static final char       PATTERN_PER_MILLE          = '\u2030';
191.3243 +    private static final char       PATTERN_PERCENT            = '%';
191.3244 +    private static final char       PATTERN_DIGIT              = '#';
191.3245 +    private static final char       PATTERN_SEPARATOR          = ';';
191.3246 +    private static final String     PATTERN_EXPONENT           = "E";
191.3247 +    private static final char       PATTERN_MINUS              = '-';
191.3248 +
191.3249 +    /**
191.3250 +     * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
191.3251 +     * is used in patterns and substituted with either the currency symbol,
191.3252 +     * or if it is doubled, with the international currency symbol.  If the
191.3253 +     * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
191.3254 +     * replaced with the monetary decimal separator.
191.3255 +     *
191.3256 +     * The CURRENCY_SIGN is not localized.
191.3257 +     */
191.3258 +    private static final char       CURRENCY_SIGN = '\u00A4';
191.3259 +
191.3260 +    private static final char       QUOTE = '\'';
191.3261 +
191.3262 +    private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];
191.3263 +
191.3264 +    // Upper limit on integer and fraction digits for a Java double
191.3265 +    static final int DOUBLE_INTEGER_DIGITS  = 309;
191.3266 +    static final int DOUBLE_FRACTION_DIGITS = 340;
191.3267 +
191.3268 +    // Upper limit on integer and fraction digits for BigDecimal and BigInteger
191.3269 +    static final int MAXIMUM_INTEGER_DIGITS  = Integer.MAX_VALUE;
191.3270 +    static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;
191.3271 +
191.3272 +    // Proclaim JDK 1.1 serial compatibility.
191.3273 +    static final long serialVersionUID = 864413376551465018L;
191.3274 +
191.3275 +    /**
191.3276 +     * Cache to hold the NumberPattern of a Locale.
191.3277 +     */
191.3278 +    private static final ConcurrentMap<Locale, String> cachedLocaleData
191.3279 +        = new ConcurrentHashMap<Locale, String>(3);
191.3280 +}
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/rt/emul/compact/src/main/java/java/text/DecimalFormatSymbols.java	Wed Apr 30 15:04:10 2014 +0200
   192.3 @@ -0,0 +1,834 @@
   192.4 +/*
   192.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   192.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   192.7 + *
   192.8 + * This code is free software; you can redistribute it and/or modify it
   192.9 + * under the terms of the GNU General Public License version 2 only, as
  192.10 + * published by the Free Software Foundation.  Oracle designates this
  192.11 + * particular file as subject to the "Classpath" exception as provided
  192.12 + * by Oracle in the LICENSE file that accompanied this code.
  192.13 + *
  192.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  192.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  192.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  192.17 + * version 2 for more details (a copy is included in the LICENSE file that
  192.18 + * accompanied this code).
  192.19 + *
  192.20 + * You should have received a copy of the GNU General Public License version
  192.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  192.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  192.23 + *
  192.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  192.25 + * or visit www.oracle.com if you need additional information or have any
  192.26 + * questions.
  192.27 + */
  192.28 +
  192.29 +/*
  192.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  192.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  192.32 + *
  192.33 + *   The original version of this source code and documentation is copyrighted
  192.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  192.35 + * materials are provided under terms of a License Agreement between Taligent
  192.36 + * and Sun. This technology is protected by multiple US and International
  192.37 + * patents. This notice and attribution to Taligent may not be removed.
  192.38 + *   Taligent is a registered trademark of Taligent, Inc.
  192.39 + *
  192.40 + */
  192.41 +
  192.42 +package java.text;
  192.43 +
  192.44 +import java.io.IOException;
  192.45 +import java.io.ObjectInputStream;
  192.46 +import java.io.Serializable;
  192.47 +import java.util.Currency;
  192.48 +import java.util.Locale;
  192.49 +import java.util.ResourceBundle;
  192.50 +import java.util.concurrent.ConcurrentHashMap;
  192.51 +
  192.52 +/**
  192.53 + * This class represents the set of symbols (such as the decimal separator,
  192.54 + * the grouping separator, and so on) needed by <code>DecimalFormat</code>
  192.55 + * to format numbers. <code>DecimalFormat</code> creates for itself an instance of
  192.56 + * <code>DecimalFormatSymbols</code> from its locale data.  If you need to change any
  192.57 + * of these symbols, you can get the <code>DecimalFormatSymbols</code> object from
  192.58 + * your <code>DecimalFormat</code> and modify it.
  192.59 + *
  192.60 + * @see          java.util.Locale
  192.61 + * @see          DecimalFormat
  192.62 + * @author       Mark Davis
  192.63 + * @author       Alan Liu
  192.64 + */
  192.65 +
  192.66 +public class DecimalFormatSymbols implements Cloneable, Serializable {
  192.67 +
  192.68 +    /**
  192.69 +     * Create a DecimalFormatSymbols object for the default locale.
  192.70 +     * This constructor can only construct instances for the locales
  192.71 +     * supported by the Java runtime environment, not for those
  192.72 +     * supported by installed
  192.73 +     * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
  192.74 +     * implementations. For full locale coverage, use the
  192.75 +     * {@link #getInstance(Locale) getInstance} method.
  192.76 +     */
  192.77 +    public DecimalFormatSymbols() {
  192.78 +        initialize( Locale.getDefault(Locale.Category.FORMAT) );
  192.79 +    }
  192.80 +
  192.81 +    /**
  192.82 +     * Create a DecimalFormatSymbols object for the given locale.
  192.83 +     * This constructor can only construct instances for the locales
  192.84 +     * supported by the Java runtime environment, not for those
  192.85 +     * supported by installed
  192.86 +     * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
  192.87 +     * implementations. For full locale coverage, use the
  192.88 +     * {@link #getInstance(Locale) getInstance} method.
  192.89 +     *
  192.90 +     * @exception NullPointerException if <code>locale</code> is null
  192.91 +     */
  192.92 +    public DecimalFormatSymbols( Locale locale ) {
  192.93 +        initialize( locale );
  192.94 +    }
  192.95 +
  192.96 +    /**
  192.97 +     * Returns an array of all locales for which the
  192.98 +     * <code>getInstance</code> methods of this class can return
  192.99 +     * localized instances.
 192.100 +     * The returned array represents the union of locales supported by the Java
 192.101 +     * runtime and by installed
 192.102 +     * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
 192.103 +     * implementations.  It must contain at least a <code>Locale</code>
 192.104 +     * instance equal to {@link java.util.Locale#US Locale.US}.
 192.105 +     *
 192.106 +     * @return An array of locales for which localized
 192.107 +     *         <code>DecimalFormatSymbols</code> instances are available.
 192.108 +     * @since 1.6
 192.109 +     */
 192.110 +    public static Locale[] getAvailableLocales() {
 192.111 +        return new Locale[] { Locale.US };
 192.112 +//        LocaleServiceProviderPool pool =
 192.113 +//            LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);
 192.114 +//        return pool.getAvailableLocales();
 192.115 +    }
 192.116 +
 192.117 +    /**
 192.118 +     * Gets the <code>DecimalFormatSymbols</code> instance for the default
 192.119 +     * locale.  This method provides access to <code>DecimalFormatSymbols</code>
 192.120 +     * instances for locales supported by the Java runtime itself as well
 192.121 +     * as for those supported by installed
 192.122 +     * {@link java.text.spi.DecimalFormatSymbolsProvider
 192.123 +     * DecimalFormatSymbolsProvider} implementations.
 192.124 +     * @return a <code>DecimalFormatSymbols</code> instance.
 192.125 +     * @since 1.6
 192.126 +     */
 192.127 +    public static final DecimalFormatSymbols getInstance() {
 192.128 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT));
 192.129 +    }
 192.130 +
 192.131 +    /**
 192.132 +     * Gets the <code>DecimalFormatSymbols</code> instance for the specified
 192.133 +     * locale.  This method provides access to <code>DecimalFormatSymbols</code>
 192.134 +     * instances for locales supported by the Java runtime itself as well
 192.135 +     * as for those supported by installed
 192.136 +     * {@link java.text.spi.DecimalFormatSymbolsProvider
 192.137 +     * DecimalFormatSymbolsProvider} implementations.
 192.138 +     * @param locale the desired locale.
 192.139 +     * @return a <code>DecimalFormatSymbols</code> instance.
 192.140 +     * @exception NullPointerException if <code>locale</code> is null
 192.141 +     * @since 1.6
 192.142 +     */
 192.143 +    public static final DecimalFormatSymbols getInstance(Locale locale) {
 192.144 +/*
 192.145 +        // Check whether a provider can provide an implementation that's closer
 192.146 +        // to the requested locale than what the Java runtime itself can provide.
 192.147 +        LocaleServiceProviderPool pool =
 192.148 +            LocaleServiceProviderPool.getPool(DecimalFormatSymbolsProvider.class);
 192.149 +        if (pool.hasProviders()) {
 192.150 +            DecimalFormatSymbols providersInstance = pool.getLocalizedObject(
 192.151 +                                DecimalFormatSymbolsGetter.INSTANCE, locale);
 192.152 +            if (providersInstance != null) {
 192.153 +                return providersInstance;
 192.154 +            }
 192.155 +        }
 192.156 +*/
 192.157 +        return new DecimalFormatSymbols(locale);
 192.158 +    }
 192.159 +
 192.160 +    /**
 192.161 +     * Gets the character used for zero. Different for Arabic, etc.
 192.162 +     */
 192.163 +    public char getZeroDigit() {
 192.164 +        return zeroDigit;
 192.165 +    }
 192.166 +
 192.167 +    /**
 192.168 +     * Sets the character used for zero. Different for Arabic, etc.
 192.169 +     */
 192.170 +    public void setZeroDigit(char zeroDigit) {
 192.171 +        this.zeroDigit = zeroDigit;
 192.172 +    }
 192.173 +
 192.174 +    /**
 192.175 +     * Gets the character used for thousands separator. Different for French, etc.
 192.176 +     */
 192.177 +    public char getGroupingSeparator() {
 192.178 +        return groupingSeparator;
 192.179 +    }
 192.180 +
 192.181 +    /**
 192.182 +     * Sets the character used for thousands separator. Different for French, etc.
 192.183 +     */
 192.184 +    public void setGroupingSeparator(char groupingSeparator) {
 192.185 +        this.groupingSeparator = groupingSeparator;
 192.186 +    }
 192.187 +
 192.188 +    /**
 192.189 +     * Gets the character used for decimal sign. Different for French, etc.
 192.190 +     */
 192.191 +    public char getDecimalSeparator() {
 192.192 +        return decimalSeparator;
 192.193 +    }
 192.194 +
 192.195 +    /**
 192.196 +     * Sets the character used for decimal sign. Different for French, etc.
 192.197 +     */
 192.198 +    public void setDecimalSeparator(char decimalSeparator) {
 192.199 +        this.decimalSeparator = decimalSeparator;
 192.200 +    }
 192.201 +
 192.202 +    /**
 192.203 +     * Gets the character used for per mille sign. Different for Arabic, etc.
 192.204 +     */
 192.205 +    public char getPerMill() {
 192.206 +        return perMill;
 192.207 +    }
 192.208 +
 192.209 +    /**
 192.210 +     * Sets the character used for per mille sign. Different for Arabic, etc.
 192.211 +     */
 192.212 +    public void setPerMill(char perMill) {
 192.213 +        this.perMill = perMill;
 192.214 +    }
 192.215 +
 192.216 +    /**
 192.217 +     * Gets the character used for percent sign. Different for Arabic, etc.
 192.218 +     */
 192.219 +    public char getPercent() {
 192.220 +        return percent;
 192.221 +    }
 192.222 +
 192.223 +    /**
 192.224 +     * Sets the character used for percent sign. Different for Arabic, etc.
 192.225 +     */
 192.226 +    public void setPercent(char percent) {
 192.227 +        this.percent = percent;
 192.228 +    }
 192.229 +
 192.230 +    /**
 192.231 +     * Gets the character used for a digit in a pattern.
 192.232 +     */
 192.233 +    public char getDigit() {
 192.234 +        return digit;
 192.235 +    }
 192.236 +
 192.237 +    /**
 192.238 +     * Sets the character used for a digit in a pattern.
 192.239 +     */
 192.240 +    public void setDigit(char digit) {
 192.241 +        this.digit = digit;
 192.242 +    }
 192.243 +
 192.244 +    /**
 192.245 +     * Gets the character used to separate positive and negative subpatterns
 192.246 +     * in a pattern.
 192.247 +     */
 192.248 +    public char getPatternSeparator() {
 192.249 +        return patternSeparator;
 192.250 +    }
 192.251 +
 192.252 +    /**
 192.253 +     * Sets the character used to separate positive and negative subpatterns
 192.254 +     * in a pattern.
 192.255 +     */
 192.256 +    public void setPatternSeparator(char patternSeparator) {
 192.257 +        this.patternSeparator = patternSeparator;
 192.258 +    }
 192.259 +
 192.260 +    /**
 192.261 +     * Gets the string used to represent infinity. Almost always left
 192.262 +     * unchanged.
 192.263 +     */
 192.264 +    public String getInfinity() {
 192.265 +        return infinity;
 192.266 +    }
 192.267 +
 192.268 +    /**
 192.269 +     * Sets the string used to represent infinity. Almost always left
 192.270 +     * unchanged.
 192.271 +     */
 192.272 +    public void setInfinity(String infinity) {
 192.273 +        this.infinity = infinity;
 192.274 +    }
 192.275 +
 192.276 +    /**
 192.277 +     * Gets the string used to represent "not a number". Almost always left
 192.278 +     * unchanged.
 192.279 +     */
 192.280 +    public String getNaN() {
 192.281 +        return NaN;
 192.282 +    }
 192.283 +
 192.284 +    /**
 192.285 +     * Sets the string used to represent "not a number". Almost always left
 192.286 +     * unchanged.
 192.287 +     */
 192.288 +    public void setNaN(String NaN) {
 192.289 +        this.NaN = NaN;
 192.290 +    }
 192.291 +
 192.292 +    /**
 192.293 +     * Gets the character used to represent minus sign. If no explicit
 192.294 +     * negative format is specified, one is formed by prefixing
 192.295 +     * minusSign to the positive format.
 192.296 +     */
 192.297 +    public char getMinusSign() {
 192.298 +        return minusSign;
 192.299 +    }
 192.300 +
 192.301 +    /**
 192.302 +     * Sets the character used to represent minus sign. If no explicit
 192.303 +     * negative format is specified, one is formed by prefixing
 192.304 +     * minusSign to the positive format.
 192.305 +     */
 192.306 +    public void setMinusSign(char minusSign) {
 192.307 +        this.minusSign = minusSign;
 192.308 +    }
 192.309 +
 192.310 +    /**
 192.311 +     * Returns the currency symbol for the currency of these
 192.312 +     * DecimalFormatSymbols in their locale.
 192.313 +     * @since 1.2
 192.314 +     */
 192.315 +    public String getCurrencySymbol()
 192.316 +    {
 192.317 +        return currencySymbol;
 192.318 +    }
 192.319 +
 192.320 +    /**
 192.321 +     * Sets the currency symbol for the currency of these
 192.322 +     * DecimalFormatSymbols in their locale.
 192.323 +     * @since 1.2
 192.324 +     */
 192.325 +    public void setCurrencySymbol(String currency)
 192.326 +    {
 192.327 +        currencySymbol = currency;
 192.328 +    }
 192.329 +
 192.330 +    /**
 192.331 +     * Returns the ISO 4217 currency code of the currency of these
 192.332 +     * DecimalFormatSymbols.
 192.333 +     * @since 1.2
 192.334 +     */
 192.335 +    public String getInternationalCurrencySymbol()
 192.336 +    {
 192.337 +        return intlCurrencySymbol;
 192.338 +    }
 192.339 +
 192.340 +    /**
 192.341 +     * Sets the ISO 4217 currency code of the currency of these
 192.342 +     * DecimalFormatSymbols.
 192.343 +     * If the currency code is valid (as defined by
 192.344 +     * {@link java.util.Currency#getInstance(java.lang.String) Currency.getInstance}),
 192.345 +     * this also sets the currency attribute to the corresponding Currency
 192.346 +     * instance and the currency symbol attribute to the currency's symbol
 192.347 +     * in the DecimalFormatSymbols' locale. If the currency code is not valid,
 192.348 +     * then the currency attribute is set to null and the currency symbol
 192.349 +     * attribute is not modified.
 192.350 +     *
 192.351 +     * @see #setCurrency
 192.352 +     * @see #setCurrencySymbol
 192.353 +     * @since 1.2
 192.354 +     */
 192.355 +    public void setInternationalCurrencySymbol(String currencyCode)
 192.356 +    {
 192.357 +        intlCurrencySymbol = currencyCode;
 192.358 +        currency = null;
 192.359 +        if (currencyCode != null) {
 192.360 +            try {
 192.361 +                currency = Currency.getInstance(currencyCode);
 192.362 +                currencySymbol = currency.getSymbol();
 192.363 +            } catch (IllegalArgumentException e) {
 192.364 +            }
 192.365 +        }
 192.366 +    }
 192.367 +
 192.368 +    /**
 192.369 +     * Gets the currency of these DecimalFormatSymbols. May be null if the
 192.370 +     * currency symbol attribute was previously set to a value that's not
 192.371 +     * a valid ISO 4217 currency code.
 192.372 +     *
 192.373 +     * @return the currency used, or null
 192.374 +     * @since 1.4
 192.375 +     */
 192.376 +    public Currency getCurrency() {
 192.377 +        return currency;
 192.378 +    }
 192.379 +
 192.380 +    /**
 192.381 +     * Sets the currency of these DecimalFormatSymbols.
 192.382 +     * This also sets the currency symbol attribute to the currency's symbol
 192.383 +     * in the DecimalFormatSymbols' locale, and the international currency
 192.384 +     * symbol attribute to the currency's ISO 4217 currency code.
 192.385 +     *
 192.386 +     * @param currency the new currency to be used
 192.387 +     * @exception NullPointerException if <code>currency</code> is null
 192.388 +     * @since 1.4
 192.389 +     * @see #setCurrencySymbol
 192.390 +     * @see #setInternationalCurrencySymbol
 192.391 +     */
 192.392 +    public void setCurrency(Currency currency) {
 192.393 +        if (currency == null) {
 192.394 +            throw new NullPointerException();
 192.395 +        }
 192.396 +        this.currency = currency;
 192.397 +        intlCurrencySymbol = currency.getCurrencyCode();
 192.398 +        currencySymbol = currency.getSymbol(locale);
 192.399 +    }
 192.400 +
 192.401 +
 192.402 +    /**
 192.403 +     * Returns the monetary decimal separator.
 192.404 +     * @since 1.2
 192.405 +     */
 192.406 +    public char getMonetaryDecimalSeparator()
 192.407 +    {
 192.408 +        return monetarySeparator;
 192.409 +    }
 192.410 +
 192.411 +    /**
 192.412 +     * Sets the monetary decimal separator.
 192.413 +     * @since 1.2
 192.414 +     */
 192.415 +    public void setMonetaryDecimalSeparator(char sep)
 192.416 +    {
 192.417 +        monetarySeparator = sep;
 192.418 +    }
 192.419 +
 192.420 +    //------------------------------------------------------------
 192.421 +    // BEGIN   Package Private methods ... to be made public later
 192.422 +    //------------------------------------------------------------
 192.423 +
 192.424 +    /**
 192.425 +     * Returns the character used to separate the mantissa from the exponent.
 192.426 +     */
 192.427 +    char getExponentialSymbol()
 192.428 +    {
 192.429 +        return exponential;
 192.430 +    }
 192.431 +  /**
 192.432 +   * Returns the string used to separate the mantissa from the exponent.
 192.433 +   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
 192.434 +   *
 192.435 +   * @return the exponent separator string
 192.436 +   * @see #setExponentSeparator(java.lang.String)
 192.437 +   * @since 1.6
 192.438 +   */
 192.439 +    public String getExponentSeparator()
 192.440 +    {
 192.441 +        return exponentialSeparator;
 192.442 +    }
 192.443 +
 192.444 +    /**
 192.445 +     * Sets the character used to separate the mantissa from the exponent.
 192.446 +     */
 192.447 +    void setExponentialSymbol(char exp)
 192.448 +    {
 192.449 +        exponential = exp;
 192.450 +    }
 192.451 +
 192.452 +  /**
 192.453 +   * Sets the string used to separate the mantissa from the exponent.
 192.454 +   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
 192.455 +   *
 192.456 +   * @param exp the exponent separator string
 192.457 +   * @exception NullPointerException if <code>exp</code> is null
 192.458 +   * @see #getExponentSeparator()
 192.459 +   * @since 1.6
 192.460 +   */
 192.461 +    public void setExponentSeparator(String exp)
 192.462 +    {
 192.463 +        if (exp == null) {
 192.464 +            throw new NullPointerException();
 192.465 +        }
 192.466 +        exponentialSeparator = exp;
 192.467 +     }
 192.468 +
 192.469 +
 192.470 +    //------------------------------------------------------------
 192.471 +    // END     Package Private methods ... to be made public later
 192.472 +    //------------------------------------------------------------
 192.473 +
 192.474 +    /**
 192.475 +     * Standard override.
 192.476 +     */
 192.477 +    public Object clone() {
 192.478 +        try {
 192.479 +            return (DecimalFormatSymbols)super.clone();
 192.480 +            // other fields are bit-copied
 192.481 +        } catch (CloneNotSupportedException e) {
 192.482 +            throw new InternalError();
 192.483 +        }
 192.484 +    }
 192.485 +
 192.486 +    /**
 192.487 +     * Override equals.
 192.488 +     */
 192.489 +    public boolean equals(Object obj) {
 192.490 +        if (obj == null) return false;
 192.491 +        if (this == obj) return true;
 192.492 +        if (getClass() != obj.getClass()) return false;
 192.493 +        DecimalFormatSymbols other = (DecimalFormatSymbols) obj;
 192.494 +        return (zeroDigit == other.zeroDigit &&
 192.495 +        groupingSeparator == other.groupingSeparator &&
 192.496 +        decimalSeparator == other.decimalSeparator &&
 192.497 +        percent == other.percent &&
 192.498 +        perMill == other.perMill &&
 192.499 +        digit == other.digit &&
 192.500 +        minusSign == other.minusSign &&
 192.501 +        patternSeparator == other.patternSeparator &&
 192.502 +        infinity.equals(other.infinity) &&
 192.503 +        NaN.equals(other.NaN) &&
 192.504 +        currencySymbol.equals(other.currencySymbol) &&
 192.505 +        intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
 192.506 +        currency == other.currency &&
 192.507 +        monetarySeparator == other.monetarySeparator &&
 192.508 +        exponentialSeparator.equals(other.exponentialSeparator) &&
 192.509 +        locale.equals(other.locale));
 192.510 +    }
 192.511 +
 192.512 +    /**
 192.513 +     * Override hashCode.
 192.514 +     */
 192.515 +    public int hashCode() {
 192.516 +            int result = zeroDigit;
 192.517 +            result = result * 37 + groupingSeparator;
 192.518 +            result = result * 37 + decimalSeparator;
 192.519 +            return result;
 192.520 +    }
 192.521 +
 192.522 +    /**
 192.523 +     * Initializes the symbols from the FormatData resource bundle.
 192.524 +     */
 192.525 +    private void initialize( Locale locale ) {
 192.526 +        this.locale = locale;
 192.527 +
 192.528 +        // get resource bundle data - try the cache first
 192.529 +        boolean needCacheUpdate = false;
 192.530 +        Object[] data = cachedLocaleData.get(locale);
 192.531 +        if (data == null) {  /* cache miss */
 192.532 +            // When numbering system is thai (Locale's extension contains u-nu-thai),
 192.533 +            // we read the data from th_TH_TH.
 192.534 +            Locale lookupLocale = locale;
 192.535 +            String numberType = locale.getUnicodeLocaleType("nu");
 192.536 +            if (numberType != null && numberType.equals("thai")) {
 192.537 +                lookupLocale = new Locale("th", "TH", "TH");
 192.538 +            }
 192.539 +            data = new Object[3];
 192.540 +//            ResourceBundle rb = LocaleData.getNumberFormatData(lookupLocale);
 192.541 +//            data[0] = rb.getStringArray("NumberElements");
 192.542 +            needCacheUpdate = true;
 192.543 +        }
 192.544 +
 192.545 +        String[] numberElements = (String[]) data[0];
 192.546 +
 192.547 +        decimalSeparator = numberElements[0].charAt(0);
 192.548 +        groupingSeparator = numberElements[1].charAt(0);
 192.549 +        patternSeparator = numberElements[2].charAt(0);
 192.550 +        percent = numberElements[3].charAt(0);
 192.551 +        zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
 192.552 +        digit = numberElements[5].charAt(0);
 192.553 +        minusSign = numberElements[6].charAt(0);
 192.554 +        exponential = numberElements[7].charAt(0);
 192.555 +        exponentialSeparator = numberElements[7]; //string representation new since 1.6
 192.556 +        perMill = numberElements[8].charAt(0);
 192.557 +        infinity  = numberElements[9];
 192.558 +        NaN = numberElements[10];
 192.559 +
 192.560 +        // Try to obtain the currency used in the locale's country.
 192.561 +        // Check for empty country string separately because it's a valid
 192.562 +        // country ID for Locale (and used for the C locale), but not a valid
 192.563 +        // ISO 3166 country code, and exceptions are expensive.
 192.564 +        if (!"".equals(locale.getCountry())) {
 192.565 +            try {
 192.566 +                currency = Currency.getInstance(locale);
 192.567 +            } catch (IllegalArgumentException e) {
 192.568 +                // use default values below for compatibility
 192.569 +            }
 192.570 +        }
 192.571 +        if (currency != null) {
 192.572 +            intlCurrencySymbol = currency.getCurrencyCode();
 192.573 +            if (data[1] != null && data[1] == intlCurrencySymbol) {
 192.574 +                currencySymbol = (String) data[2];
 192.575 +            } else {
 192.576 +                currencySymbol = currency.getSymbol(locale);
 192.577 +                data[1] = intlCurrencySymbol;
 192.578 +                data[2] = currencySymbol;
 192.579 +                needCacheUpdate = true;
 192.580 +            }
 192.581 +        } else {
 192.582 +            // default values
 192.583 +            intlCurrencySymbol = "XXX";
 192.584 +            try {
 192.585 +                currency = Currency.getInstance(intlCurrencySymbol);
 192.586 +            } catch (IllegalArgumentException e) {
 192.587 +            }
 192.588 +            currencySymbol = "\u00A4";
 192.589 +        }
 192.590 +        // Currently the monetary decimal separator is the same as the
 192.591 +        // standard decimal separator for all locales that we support.
 192.592 +        // If that changes, add a new entry to NumberElements.
 192.593 +        monetarySeparator = decimalSeparator;
 192.594 +
 192.595 +        if (needCacheUpdate) {
 192.596 +            cachedLocaleData.putIfAbsent(locale, data);
 192.597 +        }
 192.598 +    }
 192.599 +
 192.600 +    /**
 192.601 +     * Reads the default serializable fields, provides default values for objects
 192.602 +     * in older serial versions, and initializes non-serializable fields.
 192.603 +     * If <code>serialVersionOnStream</code>
 192.604 +     * is less than 1, initializes <code>monetarySeparator</code> to be
 192.605 +     * the same as <code>decimalSeparator</code> and <code>exponential</code>
 192.606 +     * to be 'E'.
 192.607 +     * If <code>serialVersionOnStream</code> is less than 2,
 192.608 +     * initializes <code>locale</code>to the root locale, and initializes
 192.609 +     * If <code>serialVersionOnStream</code> is less than 3, it initializes
 192.610 +     * <code>exponentialSeparator</code> using <code>exponential</code>.
 192.611 +     * Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that
 192.612 +     * default serialization will work properly if this object is streamed out again.
 192.613 +     * Initializes the currency from the intlCurrencySymbol field.
 192.614 +     *
 192.615 +     * @since JDK 1.1.6
 192.616 +     */
 192.617 +    private void readObject(ObjectInputStream stream)
 192.618 +            throws IOException, ClassNotFoundException {
 192.619 +        stream.defaultReadObject();
 192.620 +        if (serialVersionOnStream < 1) {
 192.621 +            // Didn't have monetarySeparator or exponential field;
 192.622 +            // use defaults.
 192.623 +            monetarySeparator = decimalSeparator;
 192.624 +            exponential       = 'E';
 192.625 +        }
 192.626 +        if (serialVersionOnStream < 2) {
 192.627 +            // didn't have locale; use root locale
 192.628 +            locale = Locale.ROOT;
 192.629 +        }
 192.630 +        if (serialVersionOnStream < 3) {
 192.631 +            // didn't have exponentialSeparator. Create one using exponential
 192.632 +            exponentialSeparator = Character.toString(exponential);
 192.633 +        }
 192.634 +        serialVersionOnStream = currentSerialVersion;
 192.635 +
 192.636 +        if (intlCurrencySymbol != null) {
 192.637 +            try {
 192.638 +                 currency = Currency.getInstance(intlCurrencySymbol);
 192.639 +            } catch (IllegalArgumentException e) {
 192.640 +            }
 192.641 +        }
 192.642 +    }
 192.643 +
 192.644 +    /**
 192.645 +     * Character used for zero.
 192.646 +     *
 192.647 +     * @serial
 192.648 +     * @see #getZeroDigit
 192.649 +     */
 192.650 +    private  char    zeroDigit;
 192.651 +
 192.652 +    /**
 192.653 +     * Character used for thousands separator.
 192.654 +     *
 192.655 +     * @serial
 192.656 +     * @see #getGroupingSeparator
 192.657 +     */
 192.658 +    private  char    groupingSeparator;
 192.659 +
 192.660 +    /**
 192.661 +     * Character used for decimal sign.
 192.662 +     *
 192.663 +     * @serial
 192.664 +     * @see #getDecimalSeparator
 192.665 +     */
 192.666 +    private  char    decimalSeparator;
 192.667 +
 192.668 +    /**
 192.669 +     * Character used for per mille sign.
 192.670 +     *
 192.671 +     * @serial
 192.672 +     * @see #getPerMill
 192.673 +     */
 192.674 +    private  char    perMill;
 192.675 +
 192.676 +    /**
 192.677 +     * Character used for percent sign.
 192.678 +     * @serial
 192.679 +     * @see #getPercent
 192.680 +     */
 192.681 +    private  char    percent;
 192.682 +
 192.683 +    /**
 192.684 +     * Character used for a digit in a pattern.
 192.685 +     *
 192.686 +     * @serial
 192.687 +     * @see #getDigit
 192.688 +     */
 192.689 +    private  char    digit;
 192.690 +
 192.691 +    /**
 192.692 +     * Character used to separate positive and negative subpatterns
 192.693 +     * in a pattern.
 192.694 +     *
 192.695 +     * @serial
 192.696 +     * @see #getPatternSeparator
 192.697 +     */
 192.698 +    private  char    patternSeparator;
 192.699 +
 192.700 +    /**
 192.701 +     * String used to represent infinity.
 192.702 +     * @serial
 192.703 +     * @see #getInfinity
 192.704 +     */
 192.705 +    private  String  infinity;
 192.706 +
 192.707 +    /**
 192.708 +     * String used to represent "not a number".
 192.709 +     * @serial
 192.710 +     * @see #getNaN
 192.711 +     */
 192.712 +    private  String  NaN;
 192.713 +
 192.714 +    /**
 192.715 +     * Character used to represent minus sign.
 192.716 +     * @serial
 192.717 +     * @see #getMinusSign
 192.718 +     */
 192.719 +    private  char    minusSign;
 192.720 +
 192.721 +    /**
 192.722 +     * String denoting the local currency, e.g. "$".
 192.723 +     * @serial
 192.724 +     * @see #getCurrencySymbol
 192.725 +     */
 192.726 +    private  String  currencySymbol;
 192.727 +
 192.728 +    /**
 192.729 +     * ISO 4217 currency code denoting the local currency, e.g. "USD".
 192.730 +     * @serial
 192.731 +     * @see #getInternationalCurrencySymbol
 192.732 +     */
 192.733 +    private  String  intlCurrencySymbol;
 192.734 +
 192.735 +    /**
 192.736 +     * The decimal separator used when formatting currency values.
 192.737 +     * @serial
 192.738 +     * @since JDK 1.1.6
 192.739 +     * @see #getMonetaryDecimalSeparator
 192.740 +     */
 192.741 +    private  char    monetarySeparator; // Field new in JDK 1.1.6
 192.742 +
 192.743 +    /**
 192.744 +     * The character used to distinguish the exponent in a number formatted
 192.745 +     * in exponential notation, e.g. 'E' for a number such as "1.23E45".
 192.746 +     * <p>
 192.747 +     * Note that the public API provides no way to set this field,
 192.748 +     * even though it is supported by the implementation and the stream format.
 192.749 +     * The intent is that this will be added to the API in the future.
 192.750 +     *
 192.751 +     * @serial
 192.752 +     * @since JDK 1.1.6
 192.753 +     */
 192.754 +    private  char    exponential;       // Field new in JDK 1.1.6
 192.755 +
 192.756 +  /**
 192.757 +   * The string used to separate the mantissa from the exponent.
 192.758 +   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
 192.759 +   * <p>
 192.760 +   * If both <code>exponential</code> and <code>exponentialSeparator</code>
 192.761 +   * exist, this <code>exponentialSeparator</code> has the precedence.
 192.762 +   *
 192.763 +   * @serial
 192.764 +   * @since 1.6
 192.765 +   */
 192.766 +    private  String    exponentialSeparator;       // Field new in JDK 1.6
 192.767 +
 192.768 +    /**
 192.769 +     * The locale of these currency format symbols.
 192.770 +     *
 192.771 +     * @serial
 192.772 +     * @since 1.4
 192.773 +     */
 192.774 +    private Locale locale;
 192.775 +
 192.776 +    // currency; only the ISO code is serialized.
 192.777 +    private transient Currency currency;
 192.778 +
 192.779 +    // Proclaim JDK 1.1 FCS compatibility
 192.780 +    static final long serialVersionUID = 5772796243397350300L;
 192.781 +
 192.782 +    // The internal serial version which says which version was written
 192.783 +    // - 0 (default) for version up to JDK 1.1.5
 192.784 +    // - 1 for version from JDK 1.1.6, which includes two new fields:
 192.785 +    //     monetarySeparator and exponential.
 192.786 +    // - 2 for version from J2SE 1.4, which includes locale field.
 192.787 +    // - 3 for version from J2SE 1.6, which includes exponentialSeparator field.
 192.788 +    private static final int currentSerialVersion = 3;
 192.789 +
 192.790 +    /**
 192.791 +     * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
 192.792 +     * Possible values are:
 192.793 +     * <ul>
 192.794 +     * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.
 192.795 +     *
 192.796 +     * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which include
 192.797 +     *      two new fields: <code>monetarySeparator</code> and <code>exponential</code>.
 192.798 +     * <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a
 192.799 +     *      new <code>locale</code> field.
 192.800 +     * <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a
 192.801 +     *      new <code>exponentialSeparator</code> field.
 192.802 +     * </ul>
 192.803 +     * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format
 192.804 +     * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
 192.805 +     * is always written.
 192.806 +     *
 192.807 +     * @serial
 192.808 +     * @since JDK 1.1.6
 192.809 +     */
 192.810 +    private int serialVersionOnStream = currentSerialVersion;
 192.811 +
 192.812 +    /**
 192.813 +     * cache to hold the NumberElements and the Currency
 192.814 +     * of a Locale.
 192.815 +     */
 192.816 +    private static final ConcurrentHashMap<Locale, Object[]> cachedLocaleData = new ConcurrentHashMap<Locale, Object[]>(3);
 192.817 +
 192.818 +    /**
 192.819 +     * Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider
 192.820 +     * implementation.
 192.821 +    private static class DecimalFormatSymbolsGetter
 192.822 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<DecimalFormatSymbolsProvider,
 192.823 +                                                                   DecimalFormatSymbols> {
 192.824 +        private static final DecimalFormatSymbolsGetter INSTANCE =
 192.825 +            new DecimalFormatSymbolsGetter();
 192.826 +
 192.827 +        public DecimalFormatSymbols getObject(
 192.828 +                                DecimalFormatSymbolsProvider decimalFormatSymbolsProvider,
 192.829 +                                Locale locale,
 192.830 +                                String key,
 192.831 +                                Object... params) {
 192.832 +            assert params.length == 0;
 192.833 +            return decimalFormatSymbolsProvider.getInstance(locale);
 192.834 +        }
 192.835 +    }
 192.836 +     */
 192.837 +}
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/rt/emul/compact/src/main/java/java/text/DigitList.java	Wed Apr 30 15:04:10 2014 +0200
   193.3 @@ -0,0 +1,715 @@
   193.4 +/*
   193.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   193.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   193.7 + *
   193.8 + * This code is free software; you can redistribute it and/or modify it
   193.9 + * under the terms of the GNU General Public License version 2 only, as
  193.10 + * published by the Free Software Foundation.  Oracle designates this
  193.11 + * particular file as subject to the "Classpath" exception as provided
  193.12 + * by Oracle in the LICENSE file that accompanied this code.
  193.13 + *
  193.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  193.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  193.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  193.17 + * version 2 for more details (a copy is included in the LICENSE file that
  193.18 + * accompanied this code).
  193.19 + *
  193.20 + * You should have received a copy of the GNU General Public License version
  193.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  193.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  193.23 + *
  193.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  193.25 + * or visit www.oracle.com if you need additional information or have any
  193.26 + * questions.
  193.27 + */
  193.28 +
  193.29 +/*
  193.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  193.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  193.32 + *
  193.33 + *   The original version of this source code and documentation is copyrighted
  193.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  193.35 + * materials are provided under terms of a License Agreement between Taligent
  193.36 + * and Sun. This technology is protected by multiple US and International
  193.37 + * patents. This notice and attribution to Taligent may not be removed.
  193.38 + *   Taligent is a registered trademark of Taligent, Inc.
  193.39 + *
  193.40 + */
  193.41 +
  193.42 +package java.text;
  193.43 +
  193.44 +import java.math.BigDecimal;
  193.45 +import java.math.BigInteger;
  193.46 +import java.math.RoundingMode;
  193.47 +
  193.48 +/**
  193.49 + * Digit List. Private to DecimalFormat.
  193.50 + * Handles the transcoding
  193.51 + * between numeric values and strings of characters.  Only handles
  193.52 + * non-negative numbers.  The division of labor between DigitList and
  193.53 + * DecimalFormat is that DigitList handles the radix 10 representation
  193.54 + * issues; DecimalFormat handles the locale-specific issues such as
  193.55 + * positive/negative, grouping, decimal point, currency, and so on.
  193.56 + *
  193.57 + * A DigitList is really a representation of a floating point value.
  193.58 + * It may be an integer value; we assume that a double has sufficient
  193.59 + * precision to represent all digits of a long.
  193.60 + *
  193.61 + * The DigitList representation consists of a string of characters,
  193.62 + * which are the digits radix 10, from '0' to '9'.  It also has a radix
  193.63 + * 10 exponent associated with it.  The value represented by a DigitList
  193.64 + * object can be computed by mulitplying the fraction f, where 0 <= f < 1,
  193.65 + * derived by placing all the digits of the list to the right of the
  193.66 + * decimal point, by 10^exponent.
  193.67 + *
  193.68 + * @see  Locale
  193.69 + * @see  Format
  193.70 + * @see  NumberFormat
  193.71 + * @see  DecimalFormat
  193.72 + * @see  ChoiceFormat
  193.73 + * @see  MessageFormat
  193.74 + * @author       Mark Davis, Alan Liu
  193.75 + */
  193.76 +final class DigitList implements Cloneable {
  193.77 +    /**
  193.78 +     * The maximum number of significant digits in an IEEE 754 double, that
  193.79 +     * is, in a Java double.  This must not be increased, or garbage digits
  193.80 +     * will be generated, and should not be decreased, or accuracy will be lost.
  193.81 +     */
  193.82 +    public static final int MAX_COUNT = 19; // == Long.toString(Long.MAX_VALUE).length()
  193.83 +
  193.84 +    /**
  193.85 +     * These data members are intentionally public and can be set directly.
  193.86 +     *
  193.87 +     * The value represented is given by placing the decimal point before
  193.88 +     * digits[decimalAt].  If decimalAt is < 0, then leading zeros between
  193.89 +     * the decimal point and the first nonzero digit are implied.  If decimalAt
  193.90 +     * is > count, then trailing zeros between the digits[count-1] and the
  193.91 +     * decimal point are implied.
  193.92 +     *
  193.93 +     * Equivalently, the represented value is given by f * 10^decimalAt.  Here
  193.94 +     * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to
  193.95 +     * the right of the decimal.
  193.96 +     *
  193.97 +     * DigitList is normalized, so if it is non-zero, figits[0] is non-zero.  We
  193.98 +     * don't allow denormalized numbers because our exponent is effectively of
  193.99 +     * unlimited magnitude.  The count value contains the number of significant
 193.100 +     * digits present in digits[].
 193.101 +     *
 193.102 +     * Zero is represented by any DigitList with count == 0 or with each digits[i]
 193.103 +     * for all i <= count == '0'.
 193.104 +     */
 193.105 +    public int decimalAt = 0;
 193.106 +    public int count = 0;
 193.107 +    public char[] digits = new char[MAX_COUNT];
 193.108 +
 193.109 +    private char[] data;
 193.110 +    private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
 193.111 +    private boolean isNegative = false;
 193.112 +
 193.113 +    /**
 193.114 +     * Return true if the represented number is zero.
 193.115 +     */
 193.116 +    boolean isZero() {
 193.117 +        for (int i=0; i < count; ++i) {
 193.118 +            if (digits[i] != '0') {
 193.119 +                return false;
 193.120 +            }
 193.121 +        }
 193.122 +        return true;
 193.123 +    }
 193.124 +
 193.125 +    /**
 193.126 +     * Set the rounding mode
 193.127 +     */
 193.128 +    void setRoundingMode(RoundingMode r) {
 193.129 +        roundingMode = r;
 193.130 +    }
 193.131 +
 193.132 +    /**
 193.133 +     * Clears out the digits.
 193.134 +     * Use before appending them.
 193.135 +     * Typically, you set a series of digits with append, then at the point
 193.136 +     * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count;
 193.137 +     * then go on appending digits.
 193.138 +     */
 193.139 +    public void clear () {
 193.140 +        decimalAt = 0;
 193.141 +        count = 0;
 193.142 +    }
 193.143 +
 193.144 +    /**
 193.145 +     * Appends a digit to the list, extending the list when necessary.
 193.146 +     */
 193.147 +    public void append(char digit) {
 193.148 +        if (count == digits.length) {
 193.149 +            char[] data = new char[count + 100];
 193.150 +            System.arraycopy(digits, 0, data, 0, count);
 193.151 +            digits = data;
 193.152 +        }
 193.153 +        digits[count++] = digit;
 193.154 +    }
 193.155 +
 193.156 +    /**
 193.157 +     * Utility routine to get the value of the digit list
 193.158 +     * If (count == 0) this throws a NumberFormatException, which
 193.159 +     * mimics Long.parseLong().
 193.160 +     */
 193.161 +    public final double getDouble() {
 193.162 +        if (count == 0) {
 193.163 +            return 0.0;
 193.164 +        }
 193.165 +
 193.166 +        StringBuffer temp = getStringBuffer();
 193.167 +        temp.append('.');
 193.168 +        temp.append(digits, 0, count);
 193.169 +        temp.append('E');
 193.170 +        temp.append(decimalAt);
 193.171 +        return Double.parseDouble(temp.toString());
 193.172 +    }
 193.173 +
 193.174 +    /**
 193.175 +     * Utility routine to get the value of the digit list.
 193.176 +     * If (count == 0) this returns 0, unlike Long.parseLong().
 193.177 +     */
 193.178 +    public final long getLong() {
 193.179 +        // for now, simple implementation; later, do proper IEEE native stuff
 193.180 +
 193.181 +        if (count == 0) {
 193.182 +            return 0;
 193.183 +        }
 193.184 +
 193.185 +        // We have to check for this, because this is the one NEGATIVE value
 193.186 +        // we represent.  If we tried to just pass the digits off to parseLong,
 193.187 +        // we'd get a parse failure.
 193.188 +        if (isLongMIN_VALUE()) {
 193.189 +            return Long.MIN_VALUE;
 193.190 +        }
 193.191 +
 193.192 +        StringBuffer temp = getStringBuffer();
 193.193 +        temp.append(digits, 0, count);
 193.194 +        for (int i = count; i < decimalAt; ++i) {
 193.195 +            temp.append('0');
 193.196 +        }
 193.197 +        return Long.parseLong(temp.toString());
 193.198 +    }
 193.199 +
 193.200 +    public final BigDecimal getBigDecimal() {
 193.201 +        if (count == 0) {
 193.202 +            if (decimalAt == 0) {
 193.203 +                return BigDecimal.ZERO;
 193.204 +            } else {
 193.205 +                return new BigDecimal("0E" + decimalAt);
 193.206 +            }
 193.207 +        }
 193.208 +
 193.209 +       if (decimalAt == count) {
 193.210 +           return new BigDecimal(digits, 0, count);
 193.211 +       } else {
 193.212 +           return new BigDecimal(digits, 0, count).scaleByPowerOfTen(decimalAt - count);
 193.213 +       }
 193.214 +    }
 193.215 +
 193.216 +    /**
 193.217 +     * Return true if the number represented by this object can fit into
 193.218 +     * a long.
 193.219 +     * @param isPositive true if this number should be regarded as positive
 193.220 +     * @param ignoreNegativeZero true if -0 should be regarded as identical to
 193.221 +     * +0; otherwise they are considered distinct
 193.222 +     * @return true if this number fits into a Java long
 193.223 +     */
 193.224 +    boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) {
 193.225 +        // Figure out if the result will fit in a long.  We have to
 193.226 +        // first look for nonzero digits after the decimal point;
 193.227 +        // then check the size.  If the digit count is 18 or less, then
 193.228 +        // the value can definitely be represented as a long.  If it is 19
 193.229 +        // then it may be too large.
 193.230 +
 193.231 +        // Trim trailing zeros.  This does not change the represented value.
 193.232 +        while (count > 0 && digits[count - 1] == '0') {
 193.233 +            --count;
 193.234 +        }
 193.235 +
 193.236 +        if (count == 0) {
 193.237 +            // Positive zero fits into a long, but negative zero can only
 193.238 +            // be represented as a double. - bug 4162852
 193.239 +            return isPositive || ignoreNegativeZero;
 193.240 +        }
 193.241 +
 193.242 +        if (decimalAt < count || decimalAt > MAX_COUNT) {
 193.243 +            return false;
 193.244 +        }
 193.245 +
 193.246 +        if (decimalAt < MAX_COUNT) return true;
 193.247 +
 193.248 +        // At this point we have decimalAt == count, and count == MAX_COUNT.
 193.249 +        // The number will overflow if it is larger than 9223372036854775807
 193.250 +        // or smaller than -9223372036854775808.
 193.251 +        for (int i=0; i<count; ++i) {
 193.252 +            char dig = digits[i], max = LONG_MIN_REP[i];
 193.253 +            if (dig > max) return false;
 193.254 +            if (dig < max) return true;
 193.255 +        }
 193.256 +
 193.257 +        // At this point the first count digits match.  If decimalAt is less
 193.258 +        // than count, then the remaining digits are zero, and we return true.
 193.259 +        if (count < decimalAt) return true;
 193.260 +
 193.261 +        // Now we have a representation of Long.MIN_VALUE, without the leading
 193.262 +        // negative sign.  If this represents a positive value, then it does
 193.263 +        // not fit; otherwise it fits.
 193.264 +        return !isPositive;
 193.265 +    }
 193.266 +
 193.267 +    /**
 193.268 +     * Set the digit list to a representation of the given double value.
 193.269 +     * This method supports fixed-point notation.
 193.270 +     * @param isNegative Boolean value indicating whether the number is negative.
 193.271 +     * @param source Value to be converted; must not be Inf, -Inf, Nan,
 193.272 +     * or a value <= 0.
 193.273 +     * @param maximumFractionDigits The most fractional digits which should
 193.274 +     * be converted.
 193.275 +     */
 193.276 +    public final void set(boolean isNegative, double source, int maximumFractionDigits) {
 193.277 +        set(isNegative, source, maximumFractionDigits, true);
 193.278 +    }
 193.279 +
 193.280 +    /**
 193.281 +     * Set the digit list to a representation of the given double value.
 193.282 +     * This method supports both fixed-point and exponential notation.
 193.283 +     * @param isNegative Boolean value indicating whether the number is negative.
 193.284 +     * @param source Value to be converted; must not be Inf, -Inf, Nan,
 193.285 +     * or a value <= 0.
 193.286 +     * @param maximumDigits The most fractional or total digits which should
 193.287 +     * be converted.
 193.288 +     * @param fixedPoint If true, then maximumDigits is the maximum
 193.289 +     * fractional digits to be converted.  If false, total digits.
 193.290 +     */
 193.291 +    final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) {
 193.292 +        set(isNegative, Double.toString(source), maximumDigits, fixedPoint);
 193.293 +    }
 193.294 +
 193.295 +    /**
 193.296 +     * Generate a representation of the form DDDDD, DDDDD.DDDDD, or
 193.297 +     * DDDDDE+/-DDDDD.
 193.298 +     */
 193.299 +    final void set(boolean isNegative, String s, int maximumDigits, boolean fixedPoint) {
 193.300 +        this.isNegative = isNegative;
 193.301 +        int len = s.length();
 193.302 +        char[] source = getDataChars(len);
 193.303 +        s.getChars(0, len, source, 0);
 193.304 +
 193.305 +        decimalAt = -1;
 193.306 +        count = 0;
 193.307 +        int exponent = 0;
 193.308 +        // Number of zeros between decimal point and first non-zero digit after
 193.309 +        // decimal point, for numbers < 1.
 193.310 +        int leadingZerosAfterDecimal = 0;
 193.311 +        boolean nonZeroDigitSeen = false;
 193.312 +
 193.313 +        for (int i = 0; i < len; ) {
 193.314 +            char c = source[i++];
 193.315 +            if (c == '.') {
 193.316 +                decimalAt = count;
 193.317 +            } else if (c == 'e' || c == 'E') {
 193.318 +                exponent = parseInt(source, i, len);
 193.319 +                break;
 193.320 +            } else {
 193.321 +                if (!nonZeroDigitSeen) {
 193.322 +                    nonZeroDigitSeen = (c != '0');
 193.323 +                    if (!nonZeroDigitSeen && decimalAt != -1)
 193.324 +                        ++leadingZerosAfterDecimal;
 193.325 +                }
 193.326 +                if (nonZeroDigitSeen) {
 193.327 +                    digits[count++] = c;
 193.328 +                }
 193.329 +            }
 193.330 +        }
 193.331 +        if (decimalAt == -1) {
 193.332 +            decimalAt = count;
 193.333 +        }
 193.334 +        if (nonZeroDigitSeen) {
 193.335 +            decimalAt += exponent - leadingZerosAfterDecimal;
 193.336 +        }
 193.337 +
 193.338 +        if (fixedPoint) {
 193.339 +            // The negative of the exponent represents the number of leading
 193.340 +            // zeros between the decimal and the first non-zero digit, for
 193.341 +            // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2).  If this
 193.342 +            // is more than the maximum fraction digits, then we have an underflow
 193.343 +            // for the printed representation.
 193.344 +            if (-decimalAt > maximumDigits) {
 193.345 +                // Handle an underflow to zero when we round something like
 193.346 +                // 0.0009 to 2 fractional digits.
 193.347 +                count = 0;
 193.348 +                return;
 193.349 +            } else if (-decimalAt == maximumDigits) {
 193.350 +                // If we round 0.0009 to 3 fractional digits, then we have to
 193.351 +                // create a new one digit in the least significant location.
 193.352 +                if (shouldRoundUp(0)) {
 193.353 +                    count = 1;
 193.354 +                    ++decimalAt;
 193.355 +                    digits[0] = '1';
 193.356 +                } else {
 193.357 +                    count = 0;
 193.358 +                }
 193.359 +                return;
 193.360 +            }
 193.361 +            // else fall through
 193.362 +        }
 193.363 +
 193.364 +        // Eliminate trailing zeros.
 193.365 +        while (count > 1 && digits[count - 1] == '0') {
 193.366 +            --count;
 193.367 +        }
 193.368 +
 193.369 +        // Eliminate digits beyond maximum digits to be displayed.
 193.370 +        // Round up if appropriate.
 193.371 +        round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits);
 193.372 +    }
 193.373 +
 193.374 +    /**
 193.375 +     * Round the representation to the given number of digits.
 193.376 +     * @param maximumDigits The maximum number of digits to be shown.
 193.377 +     * Upon return, count will be less than or equal to maximumDigits.
 193.378 +     */
 193.379 +    private final void round(int maximumDigits) {
 193.380 +        // Eliminate digits beyond maximum digits to be displayed.
 193.381 +        // Round up if appropriate.
 193.382 +        if (maximumDigits >= 0 && maximumDigits < count) {
 193.383 +            if (shouldRoundUp(maximumDigits)) {
 193.384 +                // Rounding up involved incrementing digits from LSD to MSD.
 193.385 +                // In most cases this is simple, but in a worst case situation
 193.386 +                // (9999..99) we have to adjust the decimalAt value.
 193.387 +                for (;;) {
 193.388 +                    --maximumDigits;
 193.389 +                    if (maximumDigits < 0) {
 193.390 +                        // We have all 9's, so we increment to a single digit
 193.391 +                        // of one and adjust the exponent.
 193.392 +                        digits[0] = '1';
 193.393 +                        ++decimalAt;
 193.394 +                        maximumDigits = 0; // Adjust the count
 193.395 +                        break;
 193.396 +                    }
 193.397 +
 193.398 +                    ++digits[maximumDigits];
 193.399 +                    if (digits[maximumDigits] <= '9') break;
 193.400 +                    // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
 193.401 +                }
 193.402 +                ++maximumDigits; // Increment for use as count
 193.403 +            }
 193.404 +            count = maximumDigits;
 193.405 +
 193.406 +            // Eliminate trailing zeros.
 193.407 +            while (count > 1 && digits[count-1] == '0') {
 193.408 +                --count;
 193.409 +            }
 193.410 +        }
 193.411 +    }
 193.412 +
 193.413 +
 193.414 +    /**
 193.415 +     * Return true if truncating the representation to the given number
 193.416 +     * of digits will result in an increment to the last digit.  This
 193.417 +     * method implements the rounding modes defined in the
 193.418 +     * java.math.RoundingMode class.
 193.419 +     * [bnf]
 193.420 +     * @param maximumDigits the number of digits to keep, from 0 to
 193.421 +     * <code>count-1</code>.  If 0, then all digits are rounded away, and
 193.422 +     * this method returns true if a one should be generated (e.g., formatting
 193.423 +     * 0.09 with "#.#").
 193.424 +     * @exception ArithmeticException if rounding is needed with rounding
 193.425 +     *            mode being set to RoundingMode.UNNECESSARY
 193.426 +     * @return true if digit <code>maximumDigits-1</code> should be
 193.427 +     * incremented
 193.428 +     */
 193.429 +    private boolean shouldRoundUp(int maximumDigits) {
 193.430 +        if (maximumDigits < count) {
 193.431 +            switch(roundingMode) {
 193.432 +            case UP:
 193.433 +                for (int i=maximumDigits; i<count; ++i) {
 193.434 +                    if (digits[i] != '0') {
 193.435 +                        return true;
 193.436 +                    }
 193.437 +                }
 193.438 +                break;
 193.439 +            case DOWN:
 193.440 +                break;
 193.441 +            case CEILING:
 193.442 +                for (int i=maximumDigits; i<count; ++i) {
 193.443 +                    if (digits[i] != '0') {
 193.444 +                        return !isNegative;
 193.445 +                    }
 193.446 +                }
 193.447 +                break;
 193.448 +            case FLOOR:
 193.449 +                for (int i=maximumDigits; i<count; ++i) {
 193.450 +                    if (digits[i] != '0') {
 193.451 +                        return isNegative;
 193.452 +                    }
 193.453 +                }
 193.454 +                break;
 193.455 +            case HALF_UP:
 193.456 +                if (digits[maximumDigits] >= '5') {
 193.457 +                    return true;
 193.458 +                }
 193.459 +                break;
 193.460 +            case HALF_DOWN:
 193.461 +                if (digits[maximumDigits] > '5') {
 193.462 +                    return true;
 193.463 +                } else if (digits[maximumDigits] == '5' ) {
 193.464 +                    for (int i=maximumDigits+1; i<count; ++i) {
 193.465 +                        if (digits[i] != '0') {
 193.466 +                            return true;
 193.467 +                        }
 193.468 +                    }
 193.469 +                }
 193.470 +                break;
 193.471 +            case HALF_EVEN:
 193.472 +                // Implement IEEE half-even rounding
 193.473 +                if (digits[maximumDigits] > '5') {
 193.474 +                    return true;
 193.475 +                } else if (digits[maximumDigits] == '5' ) {
 193.476 +                    for (int i=maximumDigits+1; i<count; ++i) {
 193.477 +                        if (digits[i] != '0') {
 193.478 +                            return true;
 193.479 +                        }
 193.480 +                    }
 193.481 +                    return maximumDigits > 0 && (digits[maximumDigits-1] % 2 != 0);
 193.482 +                }
 193.483 +                break;
 193.484 +            case UNNECESSARY:
 193.485 +                for (int i=maximumDigits; i<count; ++i) {
 193.486 +                    if (digits[i] != '0') {
 193.487 +                        throw new ArithmeticException(
 193.488 +                            "Rounding needed with the rounding mode being set to RoundingMode.UNNECESSARY");
 193.489 +                    }
 193.490 +                }
 193.491 +                break;
 193.492 +            default:
 193.493 +                assert false;
 193.494 +            }
 193.495 +        }
 193.496 +        return false;
 193.497 +    }
 193.498 +
 193.499 +    /**
 193.500 +     * Utility routine to set the value of the digit list from a long
 193.501 +     */
 193.502 +    public final void set(boolean isNegative, long source) {
 193.503 +        set(isNegative, source, 0);
 193.504 +    }
 193.505 +
 193.506 +    /**
 193.507 +     * Set the digit list to a representation of the given long value.
 193.508 +     * @param isNegative Boolean value indicating whether the number is negative.
 193.509 +     * @param source Value to be converted; must be >= 0 or ==
 193.510 +     * Long.MIN_VALUE.
 193.511 +     * @param maximumDigits The most digits which should be converted.
 193.512 +     * If maximumDigits is lower than the number of significant digits
 193.513 +     * in source, the representation will be rounded.  Ignored if <= 0.
 193.514 +     */
 193.515 +    public final void set(boolean isNegative, long source, int maximumDigits) {
 193.516 +        this.isNegative = isNegative;
 193.517 +
 193.518 +        // This method does not expect a negative number. However,
 193.519 +        // "source" can be a Long.MIN_VALUE (-9223372036854775808),
 193.520 +        // if the number being formatted is a Long.MIN_VALUE.  In that
 193.521 +        // case, it will be formatted as -Long.MIN_VALUE, a number
 193.522 +        // which is outside the legal range of a long, but which can
 193.523 +        // be represented by DigitList.
 193.524 +        if (source <= 0) {
 193.525 +            if (source == Long.MIN_VALUE) {
 193.526 +                decimalAt = count = MAX_COUNT;
 193.527 +                System.arraycopy(LONG_MIN_REP, 0, digits, 0, count);
 193.528 +            } else {
 193.529 +                decimalAt = count = 0; // Values <= 0 format as zero
 193.530 +            }
 193.531 +        } else {
 193.532 +            // Rewritten to improve performance.  I used to call
 193.533 +            // Long.toString(), which was about 4x slower than this code.
 193.534 +            int left = MAX_COUNT;
 193.535 +            int right;
 193.536 +            while (source > 0) {
 193.537 +                digits[--left] = (char)('0' + (source % 10));
 193.538 +                source /= 10;
 193.539 +            }
 193.540 +            decimalAt = MAX_COUNT - left;
 193.541 +            // Don't copy trailing zeros.  We are guaranteed that there is at
 193.542 +            // least one non-zero digit, so we don't have to check lower bounds.
 193.543 +            for (right = MAX_COUNT - 1; digits[right] == '0'; --right)
 193.544 +                ;
 193.545 +            count = right - left + 1;
 193.546 +            System.arraycopy(digits, left, digits, 0, count);
 193.547 +        }
 193.548 +        if (maximumDigits > 0) round(maximumDigits);
 193.549 +    }
 193.550 +
 193.551 +    /**
 193.552 +     * Set the digit list to a representation of the given BigDecimal value.
 193.553 +     * This method supports both fixed-point and exponential notation.
 193.554 +     * @param isNegative Boolean value indicating whether the number is negative.
 193.555 +     * @param source Value to be converted; must not be a value <= 0.
 193.556 +     * @param maximumDigits The most fractional or total digits which should
 193.557 +     * be converted.
 193.558 +     * @param fixedPoint If true, then maximumDigits is the maximum
 193.559 +     * fractional digits to be converted.  If false, total digits.
 193.560 +     */
 193.561 +    final void set(boolean isNegative, BigDecimal source, int maximumDigits, boolean fixedPoint) {
 193.562 +        String s = source.toString();
 193.563 +        extendDigits(s.length());
 193.564 +
 193.565 +        set(isNegative, s, maximumDigits, fixedPoint);
 193.566 +    }
 193.567 +
 193.568 +    /**
 193.569 +     * Set the digit list to a representation of the given BigInteger value.
 193.570 +     * @param isNegative Boolean value indicating whether the number is negative.
 193.571 +     * @param source Value to be converted; must be >= 0.
 193.572 +     * @param maximumDigits The most digits which should be converted.
 193.573 +     * If maximumDigits is lower than the number of significant digits
 193.574 +     * in source, the representation will be rounded.  Ignored if <= 0.
 193.575 +     */
 193.576 +    final void set(boolean isNegative, BigInteger source, int maximumDigits) {
 193.577 +        this.isNegative = isNegative;
 193.578 +        String s = source.toString();
 193.579 +        int len = s.length();
 193.580 +        extendDigits(len);
 193.581 +        s.getChars(0, len, digits, 0);
 193.582 +
 193.583 +        decimalAt = len;
 193.584 +        int right;
 193.585 +        for (right = len - 1; right >= 0 && digits[right] == '0'; --right)
 193.586 +            ;
 193.587 +        count = right + 1;
 193.588 +
 193.589 +        if (maximumDigits > 0) {
 193.590 +            round(maximumDigits);
 193.591 +        }
 193.592 +    }
 193.593 +
 193.594 +    /**
 193.595 +     * equality test between two digit lists.
 193.596 +     */
 193.597 +    public boolean equals(Object obj) {
 193.598 +        if (this == obj)                      // quick check
 193.599 +            return true;
 193.600 +        if (!(obj instanceof DigitList))         // (1) same object?
 193.601 +            return false;
 193.602 +        DigitList other = (DigitList) obj;
 193.603 +        if (count != other.count ||
 193.604 +        decimalAt != other.decimalAt)
 193.605 +            return false;
 193.606 +        for (int i = 0; i < count; i++)
 193.607 +            if (digits[i] != other.digits[i])
 193.608 +                return false;
 193.609 +        return true;
 193.610 +    }
 193.611 +
 193.612 +    /**
 193.613 +     * Generates the hash code for the digit list.
 193.614 +     */
 193.615 +    public int hashCode() {
 193.616 +        int hashcode = decimalAt;
 193.617 +
 193.618 +        for (int i = 0; i < count; i++) {
 193.619 +            hashcode = hashcode * 37 + digits[i];
 193.620 +        }
 193.621 +
 193.622 +        return hashcode;
 193.623 +    }
 193.624 +
 193.625 +    /**
 193.626 +     * Creates a copy of this object.
 193.627 +     * @return a clone of this instance.
 193.628 +     */
 193.629 +    public Object clone() {
 193.630 +        try {
 193.631 +            DigitList other = (DigitList) super.clone();
 193.632 +            char[] newDigits = new char[digits.length];
 193.633 +            System.arraycopy(digits, 0, newDigits, 0, digits.length);
 193.634 +            other.digits = newDigits;
 193.635 +            other.tempBuffer = null;
 193.636 +            return other;
 193.637 +        } catch (CloneNotSupportedException e) {
 193.638 +            throw new InternalError();
 193.639 +        }
 193.640 +    }
 193.641 +
 193.642 +    /**
 193.643 +     * Returns true if this DigitList represents Long.MIN_VALUE;
 193.644 +     * false, otherwise.  This is required so that getLong() works.
 193.645 +     */
 193.646 +    private boolean isLongMIN_VALUE() {
 193.647 +        if (decimalAt != count || count != MAX_COUNT) {
 193.648 +            return false;
 193.649 +        }
 193.650 +
 193.651 +        for (int i = 0; i < count; ++i) {
 193.652 +            if (digits[i] != LONG_MIN_REP[i]) return false;
 193.653 +        }
 193.654 +
 193.655 +        return true;
 193.656 +    }
 193.657 +
 193.658 +    private static final int parseInt(char[] str, int offset, int strLen) {
 193.659 +        char c;
 193.660 +        boolean positive = true;
 193.661 +        if ((c = str[offset]) == '-') {
 193.662 +            positive = false;
 193.663 +            offset++;
 193.664 +        } else if (c == '+') {
 193.665 +            offset++;
 193.666 +        }
 193.667 +
 193.668 +        int value = 0;
 193.669 +        while (offset < strLen) {
 193.670 +            c = str[offset++];
 193.671 +            if (c >= '0' && c <= '9') {
 193.672 +                value = value * 10 + (c - '0');
 193.673 +            } else {
 193.674 +                break;
 193.675 +            }
 193.676 +        }
 193.677 +        return positive ? value : -value;
 193.678 +    }
 193.679 +
 193.680 +    // The digit part of -9223372036854775808L
 193.681 +    private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray();
 193.682 +
 193.683 +    public String toString() {
 193.684 +        if (isZero()) {
 193.685 +            return "0";
 193.686 +        }
 193.687 +        StringBuffer buf = getStringBuffer();
 193.688 +        buf.append("0.");
 193.689 +        buf.append(digits, 0, count);
 193.690 +        buf.append("x10^");
 193.691 +        buf.append(decimalAt);
 193.692 +        return buf.toString();
 193.693 +    }
 193.694 +
 193.695 +    private StringBuffer tempBuffer;
 193.696 +
 193.697 +    private StringBuffer getStringBuffer() {
 193.698 +        if (tempBuffer == null) {
 193.699 +            tempBuffer = new StringBuffer(MAX_COUNT);
 193.700 +        } else {
 193.701 +            tempBuffer.setLength(0);
 193.702 +        }
 193.703 +        return tempBuffer;
 193.704 +    }
 193.705 +
 193.706 +    private void extendDigits(int len) {
 193.707 +        if (len > digits.length) {
 193.708 +            digits = new char[len];
 193.709 +        }
 193.710 +    }
 193.711 +
 193.712 +    private final char[] getDataChars(int length) {
 193.713 +        if (data == null || data.length < length) {
 193.714 +            data = new char[length];
 193.715 +        }
 193.716 +        return data;
 193.717 +    }
 193.718 +}
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/rt/emul/compact/src/main/java/java/text/DontCareFieldPosition.java	Wed Apr 30 15:04:10 2014 +0200
   194.3 @@ -0,0 +1,53 @@
   194.4 +/*
   194.5 + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   194.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   194.7 + *
   194.8 + * This code is free software; you can redistribute it and/or modify it
   194.9 + * under the terms of the GNU General Public License version 2 only, as
  194.10 + * published by the Free Software Foundation.  Oracle designates this
  194.11 + * particular file as subject to the "Classpath" exception as provided
  194.12 + * by Oracle in the LICENSE file that accompanied this code.
  194.13 + *
  194.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  194.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  194.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  194.17 + * version 2 for more details (a copy is included in the LICENSE file that
  194.18 + * accompanied this code).
  194.19 + *
  194.20 + * You should have received a copy of the GNU General Public License version
  194.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  194.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  194.23 + *
  194.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  194.25 + * or visit www.oracle.com if you need additional information or have any
  194.26 + * questions.
  194.27 + */
  194.28 +
  194.29 +package java.text;
  194.30 +
  194.31 +/**
  194.32 + * DontCareFieldPosition defines no-op FieldDelegate. Its
  194.33 + * singleton is used for the format methods that don't take a
  194.34 + * FieldPosition.
  194.35 + */
  194.36 +class DontCareFieldPosition extends FieldPosition {
  194.37 +    // The singleton of DontCareFieldPosition.
  194.38 +    static final FieldPosition INSTANCE = new DontCareFieldPosition();
  194.39 +
  194.40 +    private final Format.FieldDelegate noDelegate = new Format.FieldDelegate() {
  194.41 +        public void formatted(Format.Field attr, Object value, int start,
  194.42 +                              int end, StringBuffer buffer) {
  194.43 +        }
  194.44 +        public void formatted(int fieldID, Format.Field attr, Object value,
  194.45 +                              int start, int end, StringBuffer buffer) {
  194.46 +        }
  194.47 +    };
  194.48 +
  194.49 +    private DontCareFieldPosition() {
  194.50 +        super(0);
  194.51 +    }
  194.52 +
  194.53 +    Format.FieldDelegate getFieldDelegate() {
  194.54 +        return noDelegate;
  194.55 +    }
  194.56 +}
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/rt/emul/compact/src/main/java/java/text/FieldPosition.java	Wed Apr 30 15:04:10 2014 +0200
   195.3 @@ -0,0 +1,303 @@
   195.4 +/*
   195.5 + * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
   195.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   195.7 + *
   195.8 + * This code is free software; you can redistribute it and/or modify it
   195.9 + * under the terms of the GNU General Public License version 2 only, as
  195.10 + * published by the Free Software Foundation.  Oracle designates this
  195.11 + * particular file as subject to the "Classpath" exception as provided
  195.12 + * by Oracle in the LICENSE file that accompanied this code.
  195.13 + *
  195.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  195.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  195.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  195.17 + * version 2 for more details (a copy is included in the LICENSE file that
  195.18 + * accompanied this code).
  195.19 + *
  195.20 + * You should have received a copy of the GNU General Public License version
  195.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  195.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  195.23 + *
  195.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  195.25 + * or visit www.oracle.com if you need additional information or have any
  195.26 + * questions.
  195.27 + */
  195.28 +
  195.29 +/*
  195.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  195.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  195.32 + *
  195.33 + *   The original version of this source code and documentation is copyrighted
  195.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  195.35 + * materials are provided under terms of a License Agreement between Taligent
  195.36 + * and Sun. This technology is protected by multiple US and International
  195.37 + * patents. This notice and attribution to Taligent may not be removed.
  195.38 + *   Taligent is a registered trademark of Taligent, Inc.
  195.39 + *
  195.40 + */
  195.41 +
  195.42 +package java.text;
  195.43 +
  195.44 +/**
  195.45 + * <code>FieldPosition</code> is a simple class used by <code>Format</code>
  195.46 + * and its subclasses to identify fields in formatted output. Fields can
  195.47 + * be identified in two ways:
  195.48 + * <ul>
  195.49 + *  <li>By an integer constant, whose names typically end with
  195.50 + *      <code>_FIELD</code>. The constants are defined in the various
  195.51 + *      subclasses of <code>Format</code>.
  195.52 + *  <li>By a <code>Format.Field</code> constant, see <code>ERA_FIELD</code>
  195.53 + *      and its friends in <code>DateFormat</code> for an example.
  195.54 + * </ul>
  195.55 + * <p>
  195.56 + * <code>FieldPosition</code> keeps track of the position of the
  195.57 + * field within the formatted output with two indices: the index
  195.58 + * of the first character of the field and the index of the last
  195.59 + * character of the field.
  195.60 + *
  195.61 + * <p>
  195.62 + * One version of the <code>format</code> method in the various
  195.63 + * <code>Format</code> classes requires a <code>FieldPosition</code>
  195.64 + * object as an argument. You use this <code>format</code> method
  195.65 + * to perform partial formatting or to get information about the
  195.66 + * formatted output (such as the position of a field).
  195.67 + *
  195.68 + * <p>
  195.69 + * If you are interested in the positions of all attributes in the
  195.70 + * formatted string use the <code>Format</code> method
  195.71 + * <code>formatToCharacterIterator</code>.
  195.72 + *
  195.73 + * @author      Mark Davis
  195.74 + * @see         java.text.Format
  195.75 + */
  195.76 +public class FieldPosition {
  195.77 +
  195.78 +    /**
  195.79 +     * Input: Desired field to determine start and end offsets for.
  195.80 +     * The meaning depends on the subclass of Format.
  195.81 +     */
  195.82 +    int field = 0;
  195.83 +
  195.84 +    /**
  195.85 +     * Output: End offset of field in text.
  195.86 +     * If the field does not occur in the text, 0 is returned.
  195.87 +     */
  195.88 +    int endIndex = 0;
  195.89 +
  195.90 +    /**
  195.91 +     * Output: Start offset of field in text.
  195.92 +     * If the field does not occur in the text, 0 is returned.
  195.93 +     */
  195.94 +    int beginIndex = 0;
  195.95 +
  195.96 +    /**
  195.97 +     * Desired field this FieldPosition is for.
  195.98 +     */
  195.99 +    private Format.Field attribute;
 195.100 +
 195.101 +    /**
 195.102 +     * Creates a FieldPosition object for the given field.  Fields are
 195.103 +     * identified by constants, whose names typically end with _FIELD,
 195.104 +     * in the various subclasses of Format.
 195.105 +     *
 195.106 +     * @see java.text.NumberFormat#INTEGER_FIELD
 195.107 +     * @see java.text.NumberFormat#FRACTION_FIELD
 195.108 +     * @see java.text.DateFormat#YEAR_FIELD
 195.109 +     * @see java.text.DateFormat#MONTH_FIELD
 195.110 +     */
 195.111 +    public FieldPosition(int field) {
 195.112 +        this.field = field;
 195.113 +    }
 195.114 +
 195.115 +    /**
 195.116 +     * Creates a FieldPosition object for the given field constant. Fields are
 195.117 +     * identified by constants defined in the various <code>Format</code>
 195.118 +     * subclasses. This is equivalent to calling
 195.119 +     * <code>new FieldPosition(attribute, -1)</code>.
 195.120 +     *
 195.121 +     * @param attribute Format.Field constant identifying a field
 195.122 +     * @since 1.4
 195.123 +     */
 195.124 +    public FieldPosition(Format.Field attribute) {
 195.125 +        this(attribute, -1);
 195.126 +    }
 195.127 +
 195.128 +    /**
 195.129 +     * Creates a <code>FieldPosition</code> object for the given field.
 195.130 +     * The field is identified by an attribute constant from one of the
 195.131 +     * <code>Field</code> subclasses as well as an integer field ID
 195.132 +     * defined by the <code>Format</code> subclasses. <code>Format</code>
 195.133 +     * subclasses that are aware of <code>Field</code> should give precedence
 195.134 +     * to <code>attribute</code> and ignore <code>fieldID</code> if
 195.135 +     * <code>attribute</code> is not null. However, older <code>Format</code>
 195.136 +     * subclasses may not be aware of <code>Field</code> and rely on
 195.137 +     * <code>fieldID</code>. If the field has no corresponding integer
 195.138 +     * constant, <code>fieldID</code> should be -1.
 195.139 +     *
 195.140 +     * @param attribute Format.Field constant identifying a field
 195.141 +     * @param fieldID integer constantce identifying a field
 195.142 +     * @since 1.4
 195.143 +     */
 195.144 +    public FieldPosition(Format.Field attribute, int fieldID) {
 195.145 +        this.attribute = attribute;
 195.146 +        this.field = fieldID;
 195.147 +    }
 195.148 +
 195.149 +    /**
 195.150 +     * Returns the field identifier as an attribute constant
 195.151 +     * from one of the <code>Field</code> subclasses. May return null if
 195.152 +     * the field is specified only by an integer field ID.
 195.153 +     *
 195.154 +     * @return Identifier for the field
 195.155 +     * @since 1.4
 195.156 +     */
 195.157 +    public Format.Field getFieldAttribute() {
 195.158 +        return attribute;
 195.159 +    }
 195.160 +
 195.161 +    /**
 195.162 +     * Retrieves the field identifier.
 195.163 +     */
 195.164 +    public int getField() {
 195.165 +        return field;
 195.166 +    }
 195.167 +
 195.168 +    /**
 195.169 +     * Retrieves the index of the first character in the requested field.
 195.170 +     */
 195.171 +    public int getBeginIndex() {
 195.172 +        return beginIndex;
 195.173 +    }
 195.174 +
 195.175 +    /**
 195.176 +     * Retrieves the index of the character following the last character in the
 195.177 +     * requested field.
 195.178 +     */
 195.179 +    public int getEndIndex() {
 195.180 +        return endIndex;
 195.181 +    }
 195.182 +
 195.183 +    /**
 195.184 +     * Sets the begin index.  For use by subclasses of Format.
 195.185 +     * @since 1.2
 195.186 +     */
 195.187 +    public void setBeginIndex(int bi) {
 195.188 +        beginIndex = bi;
 195.189 +    }
 195.190 +
 195.191 +    /**
 195.192 +     * Sets the end index.  For use by subclasses of Format.
 195.193 +     * @since 1.2
 195.194 +     */
 195.195 +    public void setEndIndex(int ei) {
 195.196 +        endIndex = ei;
 195.197 +    }
 195.198 +
 195.199 +    /**
 195.200 +     * Returns a <code>Format.FieldDelegate</code> instance that is associated
 195.201 +     * with the FieldPosition. When the delegate is notified of the same
 195.202 +     * field the FieldPosition is associated with, the begin/end will be
 195.203 +     * adjusted.
 195.204 +     */
 195.205 +    Format.FieldDelegate getFieldDelegate() {
 195.206 +        return new Delegate();
 195.207 +    }
 195.208 +
 195.209 +    /**
 195.210 +     * Overrides equals
 195.211 +     */
 195.212 +    public boolean equals(Object obj)
 195.213 +    {
 195.214 +        if (obj == null) return false;
 195.215 +        if (!(obj instanceof FieldPosition))
 195.216 +            return false;
 195.217 +        FieldPosition other = (FieldPosition) obj;
 195.218 +        if (attribute == null) {
 195.219 +            if (other.attribute != null) {
 195.220 +                return false;
 195.221 +            }
 195.222 +        }
 195.223 +        else if (!attribute.equals(other.attribute)) {
 195.224 +            return false;
 195.225 +        }
 195.226 +        return (beginIndex == other.beginIndex
 195.227 +            && endIndex == other.endIndex
 195.228 +            && field == other.field);
 195.229 +    }
 195.230 +
 195.231 +    /**
 195.232 +     * Returns a hash code for this FieldPosition.
 195.233 +     * @return a hash code value for this object
 195.234 +     */
 195.235 +    public int hashCode() {
 195.236 +        return (field << 24) | (beginIndex << 16) | endIndex;
 195.237 +    }
 195.238 +
 195.239 +    /**
 195.240 +     * Return a string representation of this FieldPosition.
 195.241 +     * @return  a string representation of this object
 195.242 +     */
 195.243 +    public String toString() {
 195.244 +        return getClass().getName() +
 195.245 +            "[field=" + field + ",attribute=" + attribute +
 195.246 +            ",beginIndex=" + beginIndex +
 195.247 +            ",endIndex=" + endIndex + ']';
 195.248 +    }
 195.249 +
 195.250 +
 195.251 +    /**
 195.252 +     * Return true if the receiver wants a <code>Format.Field</code> value and
 195.253 +     * <code>attribute</code> is equal to it.
 195.254 +     */
 195.255 +    private boolean matchesField(Format.Field attribute) {
 195.256 +        if (this.attribute != null) {
 195.257 +            return this.attribute.equals(attribute);
 195.258 +        }
 195.259 +        return false;
 195.260 +    }
 195.261 +
 195.262 +    /**
 195.263 +     * Return true if the receiver wants a <code>Format.Field</code> value and
 195.264 +     * <code>attribute</code> is equal to it, or true if the receiver
 195.265 +     * represents an inteter constant and <code>field</code> equals it.
 195.266 +     */
 195.267 +    private boolean matchesField(Format.Field attribute, int field) {
 195.268 +        if (this.attribute != null) {
 195.269 +            return this.attribute.equals(attribute);
 195.270 +        }
 195.271 +        return (field == this.field);
 195.272 +    }
 195.273 +
 195.274 +
 195.275 +    /**
 195.276 +     * An implementation of FieldDelegate that will adjust the begin/end
 195.277 +     * of the FieldPosition if the arguments match the field of
 195.278 +     * the FieldPosition.
 195.279 +     */
 195.280 +    private class Delegate implements Format.FieldDelegate {
 195.281 +        /**
 195.282 +         * Indicates whether the field has been  encountered before. If this
 195.283 +         * is true, and <code>formatted</code> is invoked, the begin/end
 195.284 +         * are not updated.
 195.285 +         */
 195.286 +        private boolean encounteredField;
 195.287 +
 195.288 +        public void formatted(Format.Field attr, Object value, int start,
 195.289 +                              int end, StringBuffer buffer) {
 195.290 +            if (!encounteredField && matchesField(attr)) {
 195.291 +                setBeginIndex(start);
 195.292 +                setEndIndex(end);
 195.293 +                encounteredField = (start != end);
 195.294 +            }
 195.295 +        }
 195.296 +
 195.297 +        public void formatted(int fieldID, Format.Field attr, Object value,
 195.298 +                              int start, int end, StringBuffer buffer) {
 195.299 +            if (!encounteredField && matchesField(attr, fieldID)) {
 195.300 +                setBeginIndex(start);
 195.301 +                setEndIndex(end);
 195.302 +                encounteredField = (start != end);
 195.303 +            }
 195.304 +        }
 195.305 +    }
 195.306 +}
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/rt/emul/compact/src/main/java/java/text/Format.java	Wed Apr 30 15:04:10 2014 +0200
   196.3 @@ -0,0 +1,406 @@
   196.4 +/*
   196.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
   196.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   196.7 + *
   196.8 + * This code is free software; you can redistribute it and/or modify it
   196.9 + * under the terms of the GNU General Public License version 2 only, as
  196.10 + * published by the Free Software Foundation.  Oracle designates this
  196.11 + * particular file as subject to the "Classpath" exception as provided
  196.12 + * by Oracle in the LICENSE file that accompanied this code.
  196.13 + *
  196.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  196.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  196.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  196.17 + * version 2 for more details (a copy is included in the LICENSE file that
  196.18 + * accompanied this code).
  196.19 + *
  196.20 + * You should have received a copy of the GNU General Public License version
  196.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  196.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  196.23 + *
  196.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  196.25 + * or visit www.oracle.com if you need additional information or have any
  196.26 + * questions.
  196.27 + */
  196.28 +
  196.29 +/*
  196.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  196.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  196.32 + *
  196.33 + *   The original version of this source code and documentation is copyrighted
  196.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  196.35 + * materials are provided under terms of a License Agreement between Taligent
  196.36 + * and Sun. This technology is protected by multiple US and International
  196.37 + * patents. This notice and attribution to Taligent may not be removed.
  196.38 + *   Taligent is a registered trademark of Taligent, Inc.
  196.39 + *
  196.40 + */
  196.41 +
  196.42 +package java.text;
  196.43 +
  196.44 +import java.io.Serializable;
  196.45 +
  196.46 +/**
  196.47 + * <code>Format</code> is an abstract base class for formatting locale-sensitive
  196.48 + * information such as dates, messages, and numbers.
  196.49 + *
  196.50 + * <p>
  196.51 + * <code>Format</code> defines the programming interface for formatting
  196.52 + * locale-sensitive objects into <code>String</code>s (the
  196.53 + * <code>format</code> method) and for parsing <code>String</code>s back
  196.54 + * into objects (the <code>parseObject</code> method).
  196.55 + *
  196.56 + * <p>
  196.57 + * Generally, a format's <code>parseObject</code> method must be able to parse
  196.58 + * any string formatted by its <code>format</code> method. However, there may
  196.59 + * be exceptional cases where this is not possible. For example, a
  196.60 + * <code>format</code> method might create two adjacent integer numbers with
  196.61 + * no separator in between, and in this case the <code>parseObject</code> could
  196.62 + * not tell which digits belong to which number.
  196.63 + *
  196.64 + * <h4>Subclassing</h4>
  196.65 + *
  196.66 + * <p>
  196.67 + * The Java Platform provides three specialized subclasses of <code>Format</code>--
  196.68 + * <code>DateFormat</code>, <code>MessageFormat</code>, and
  196.69 + * <code>NumberFormat</code>--for formatting dates, messages, and numbers,
  196.70 + * respectively.
  196.71 + * <p>
  196.72 + * Concrete subclasses must implement three methods:
  196.73 + * <ol>
  196.74 + * <li> <code>format(Object obj, StringBuffer toAppendTo, FieldPosition pos)</code>
  196.75 + * <li> <code>formatToCharacterIterator(Object obj)</code>
  196.76 + * <li> <code>parseObject(String source, ParsePosition pos)</code>
  196.77 + * </ol>
  196.78 + * These general methods allow polymorphic parsing and formatting of objects
  196.79 + * and are used, for example, by <code>MessageFormat</code>.
  196.80 + * Subclasses often also provide additional <code>format</code> methods for
  196.81 + * specific input types as well as <code>parse</code> methods for specific
  196.82 + * result types. Any <code>parse</code> method that does not take a
  196.83 + * <code>ParsePosition</code> argument should throw <code>ParseException</code>
  196.84 + * when no text in the required format is at the beginning of the input text.
  196.85 + *
  196.86 + * <p>
  196.87 + * Most subclasses will also implement the following factory methods:
  196.88 + * <ol>
  196.89 + * <li>
  196.90 + * <code>getInstance</code> for getting a useful format object appropriate
  196.91 + * for the current locale
  196.92 + * <li>
  196.93 + * <code>getInstance(Locale)</code> for getting a useful format
  196.94 + * object appropriate for the specified locale
  196.95 + * </ol>
  196.96 + * In addition, some subclasses may also implement other
  196.97 + * <code>getXxxxInstance</code> methods for more specialized control. For
  196.98 + * example, the <code>NumberFormat</code> class provides
  196.99 + * <code>getPercentInstance</code> and <code>getCurrencyInstance</code>
 196.100 + * methods for getting specialized number formatters.
 196.101 + *
 196.102 + * <p>
 196.103 + * Subclasses of <code>Format</code> that allow programmers to create objects
 196.104 + * for locales (with <code>getInstance(Locale)</code> for example)
 196.105 + * must also implement the following class method:
 196.106 + * <blockquote>
 196.107 + * <pre>
 196.108 + * public static Locale[] getAvailableLocales()
 196.109 + * </pre>
 196.110 + * </blockquote>
 196.111 + *
 196.112 + * <p>
 196.113 + * And finally subclasses may define a set of constants to identify the various
 196.114 + * fields in the formatted output. These constants are used to create a FieldPosition
 196.115 + * object which identifies what information is contained in the field and its
 196.116 + * position in the formatted result. These constants should be named
 196.117 + * <code><em>item</em>_FIELD</code> where <code><em>item</em></code> identifies
 196.118 + * the field. For examples of these constants, see <code>ERA_FIELD</code> and its
 196.119 + * friends in {@link DateFormat}.
 196.120 + *
 196.121 + * <h4><a name="synchronization">Synchronization</a></h4>
 196.122 + *
 196.123 + * <p>
 196.124 + * Formats are generally not synchronized.
 196.125 + * It is recommended to create separate format instances for each thread.
 196.126 + * If multiple threads access a format concurrently, it must be synchronized
 196.127 + * externally.
 196.128 + *
 196.129 + * @see          java.text.ParsePosition
 196.130 + * @see          java.text.FieldPosition
 196.131 + * @see          java.text.NumberFormat
 196.132 + * @see          java.text.DateFormat
 196.133 + * @see          java.text.MessageFormat
 196.134 + * @author       Mark Davis
 196.135 + */
 196.136 +public abstract class Format implements Serializable, Cloneable {
 196.137 +
 196.138 +    private static final long serialVersionUID = -299282585814624189L;
 196.139 +
 196.140 +    /**
 196.141 +     * Sole constructor.  (For invocation by subclass constructors, typically
 196.142 +     * implicit.)
 196.143 +     */
 196.144 +    protected Format() {
 196.145 +    }
 196.146 +
 196.147 +    /**
 196.148 +     * Formats an object to produce a string. This is equivalent to
 196.149 +     * <blockquote>
 196.150 +     * {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj,
 196.151 +     *         new StringBuffer(), new FieldPosition(0)).toString();</code>
 196.152 +     * </blockquote>
 196.153 +     *
 196.154 +     * @param obj    The object to format
 196.155 +     * @return       Formatted string.
 196.156 +     * @exception IllegalArgumentException if the Format cannot format the given
 196.157 +     *            object
 196.158 +     */
 196.159 +    public final String format (Object obj) {
 196.160 +        return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
 196.161 +    }
 196.162 +
 196.163 +    /**
 196.164 +     * Formats an object and appends the resulting text to a given string
 196.165 +     * buffer.
 196.166 +     * If the <code>pos</code> argument identifies a field used by the format,
 196.167 +     * then its indices are set to the beginning and end of the first such
 196.168 +     * field encountered.
 196.169 +     *
 196.170 +     * @param obj    The object to format
 196.171 +     * @param toAppendTo    where the text is to be appended
 196.172 +     * @param pos    A <code>FieldPosition</code> identifying a field
 196.173 +     *               in the formatted text
 196.174 +     * @return       the string buffer passed in as <code>toAppendTo</code>,
 196.175 +     *               with formatted text appended
 196.176 +     * @exception NullPointerException if <code>toAppendTo</code> or
 196.177 +     *            <code>pos</code> is null
 196.178 +     * @exception IllegalArgumentException if the Format cannot format the given
 196.179 +     *            object
 196.180 +     */
 196.181 +    public abstract StringBuffer format(Object obj,
 196.182 +                    StringBuffer toAppendTo,
 196.183 +                    FieldPosition pos);
 196.184 +
 196.185 +    /**
 196.186 +     * Formats an Object producing an <code>AttributedCharacterIterator</code>.
 196.187 +     * You can use the returned <code>AttributedCharacterIterator</code>
 196.188 +     * to build the resulting String, as well as to determine information
 196.189 +     * about the resulting String.
 196.190 +     * <p>
 196.191 +     * Each attribute key of the AttributedCharacterIterator will be of type
 196.192 +     * <code>Field</code>. It is up to each <code>Format</code> implementation
 196.193 +     * to define what the legal values are for each attribute in the
 196.194 +     * <code>AttributedCharacterIterator</code>, but typically the attribute
 196.195 +     * key is also used as the attribute value.
 196.196 +     * <p>The default implementation creates an
 196.197 +     * <code>AttributedCharacterIterator</code> with no attributes. Subclasses
 196.198 +     * that support fields should override this and create an
 196.199 +     * <code>AttributedCharacterIterator</code> with meaningful attributes.
 196.200 +     *
 196.201 +     * @exception NullPointerException if obj is null.
 196.202 +     * @exception IllegalArgumentException when the Format cannot format the
 196.203 +     *            given object.
 196.204 +     * @param obj The object to format
 196.205 +     * @return AttributedCharacterIterator describing the formatted value.
 196.206 +     * @since 1.4
 196.207 +     */
 196.208 +    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
 196.209 +        return createAttributedCharacterIterator(format(obj));
 196.210 +    }
 196.211 +
 196.212 +    /**
 196.213 +     * Parses text from a string to produce an object.
 196.214 +     * <p>
 196.215 +     * The method attempts to parse text starting at the index given by
 196.216 +     * <code>pos</code>.
 196.217 +     * If parsing succeeds, then the index of <code>pos</code> is updated
 196.218 +     * to the index after the last character used (parsing does not necessarily
 196.219 +     * use all characters up to the end of the string), and the parsed
 196.220 +     * object is returned. The updated <code>pos</code> can be used to
 196.221 +     * indicate the starting point for the next call to this method.
 196.222 +     * If an error occurs, then the index of <code>pos</code> is not
 196.223 +     * changed, the error index of <code>pos</code> is set to the index of
 196.224 +     * the character where the error occurred, and null is returned.
 196.225 +     *
 196.226 +     * @param source A <code>String</code>, part of which should be parsed.
 196.227 +     * @param pos A <code>ParsePosition</code> object with index and error
 196.228 +     *            index information as described above.
 196.229 +     * @return An <code>Object</code> parsed from the string. In case of
 196.230 +     *         error, returns null.
 196.231 +     * @exception NullPointerException if <code>pos</code> is null.
 196.232 +     */
 196.233 +    public abstract Object parseObject (String source, ParsePosition pos);
 196.234 +
 196.235 +    /**
 196.236 +     * Parses text from the beginning of the given string to produce an object.
 196.237 +     * The method may not use the entire text of the given string.
 196.238 +     *
 196.239 +     * @param source A <code>String</code> whose beginning should be parsed.
 196.240 +     * @return An <code>Object</code> parsed from the string.
 196.241 +     * @exception ParseException if the beginning of the specified string
 196.242 +     *            cannot be parsed.
 196.243 +     */
 196.244 +    public Object parseObject(String source) throws ParseException {
 196.245 +        ParsePosition pos = new ParsePosition(0);
 196.246 +        Object result = parseObject(source, pos);
 196.247 +        if (pos.index == 0) {
 196.248 +            throw new ParseException("Format.parseObject(String) failed",
 196.249 +                pos.errorIndex);
 196.250 +        }
 196.251 +        return result;
 196.252 +    }
 196.253 +
 196.254 +    /**
 196.255 +     * Creates and returns a copy of this object.
 196.256 +     *
 196.257 +     * @return a clone of this instance.
 196.258 +     */
 196.259 +    public Object clone() {
 196.260 +        try {
 196.261 +            return super.clone();
 196.262 +        } catch (CloneNotSupportedException e) {
 196.263 +            // will never happen
 196.264 +            return null;
 196.265 +        }
 196.266 +    }
 196.267 +
 196.268 +    //
 196.269 +    // Convenience methods for creating AttributedCharacterIterators from
 196.270 +    // different parameters.
 196.271 +    //
 196.272 +
 196.273 +    /**
 196.274 +     * Creates an <code>AttributedCharacterIterator</code> for the String
 196.275 +     * <code>s</code>.
 196.276 +     *
 196.277 +     * @param s String to create AttributedCharacterIterator from
 196.278 +     * @return AttributedCharacterIterator wrapping s
 196.279 +     */
 196.280 +    AttributedCharacterIterator createAttributedCharacterIterator(String s) {
 196.281 +        AttributedString as = new AttributedString(s);
 196.282 +
 196.283 +        return as.getIterator();
 196.284 +    }
 196.285 +
 196.286 +    /**
 196.287 +     * Creates an <code>AttributedCharacterIterator</code> containg the
 196.288 +     * concatenated contents of the passed in
 196.289 +     * <code>AttributedCharacterIterator</code>s.
 196.290 +     *
 196.291 +     * @param iterators AttributedCharacterIterators used to create resulting
 196.292 +     *                  AttributedCharacterIterators
 196.293 +     * @return AttributedCharacterIterator wrapping passed in
 196.294 +     *         AttributedCharacterIterators
 196.295 +     */
 196.296 +    AttributedCharacterIterator createAttributedCharacterIterator(
 196.297 +                       AttributedCharacterIterator[] iterators) {
 196.298 +        AttributedString as = new AttributedString(iterators);
 196.299 +
 196.300 +        return as.getIterator();
 196.301 +    }
 196.302 +
 196.303 +    /**
 196.304 +     * Returns an AttributedCharacterIterator with the String
 196.305 +     * <code>string</code> and additional key/value pair <code>key</code>,
 196.306 +     * <code>value</code>.
 196.307 +     *
 196.308 +     * @param string String to create AttributedCharacterIterator from
 196.309 +     * @param key Key for AttributedCharacterIterator
 196.310 +     * @param value Value associated with key in AttributedCharacterIterator
 196.311 +     * @return AttributedCharacterIterator wrapping args
 196.312 +     */
 196.313 +    AttributedCharacterIterator createAttributedCharacterIterator(
 196.314 +                      String string, AttributedCharacterIterator.Attribute key,
 196.315 +                      Object value) {
 196.316 +        AttributedString as = new AttributedString(string);
 196.317 +
 196.318 +        as.addAttribute(key, value);
 196.319 +        return as.getIterator();
 196.320 +    }
 196.321 +
 196.322 +    /**
 196.323 +     * Creates an AttributedCharacterIterator with the contents of
 196.324 +     * <code>iterator</code> and the additional attribute <code>key</code>
 196.325 +     * <code>value</code>.
 196.326 +     *
 196.327 +     * @param iterator Initial AttributedCharacterIterator to add arg to
 196.328 +     * @param key Key for AttributedCharacterIterator
 196.329 +     * @param value Value associated with key in AttributedCharacterIterator
 196.330 +     * @return AttributedCharacterIterator wrapping args
 196.331 +     */
 196.332 +    AttributedCharacterIterator createAttributedCharacterIterator(
 196.333 +              AttributedCharacterIterator iterator,
 196.334 +              AttributedCharacterIterator.Attribute key, Object value) {
 196.335 +        AttributedString as = new AttributedString(iterator);
 196.336 +
 196.337 +        as.addAttribute(key, value);
 196.338 +        return as.getIterator();
 196.339 +    }
 196.340 +
 196.341 +
 196.342 +    /**
 196.343 +     * Defines constants that are used as attribute keys in the
 196.344 +     * <code>AttributedCharacterIterator</code> returned
 196.345 +     * from <code>Format.formatToCharacterIterator</code> and as
 196.346 +     * field identifiers in <code>FieldPosition</code>.
 196.347 +     *
 196.348 +     * @since 1.4
 196.349 +     */
 196.350 +    public static class Field extends AttributedCharacterIterator.Attribute {
 196.351 +
 196.352 +        // Proclaim serial compatibility with 1.4 FCS
 196.353 +        private static final long serialVersionUID = 276966692217360283L;
 196.354 +
 196.355 +        /**
 196.356 +         * Creates a Field with the specified name.
 196.357 +         *
 196.358 +         * @param name Name of the attribute
 196.359 +         */
 196.360 +        protected Field(String name) {
 196.361 +            super(name);
 196.362 +        }
 196.363 +    }
 196.364 +
 196.365 +
 196.366 +    /**
 196.367 +     * FieldDelegate is notified by the various <code>Format</code>
 196.368 +     * implementations as they are formatting the Objects. This allows for
 196.369 +     * storage of the individual sections of the formatted String for
 196.370 +     * later use, such as in a <code>FieldPosition</code> or for an
 196.371 +     * <code>AttributedCharacterIterator</code>.
 196.372 +     * <p>
 196.373 +     * Delegates should NOT assume that the <code>Format</code> will notify
 196.374 +     * the delegate of fields in any particular order.
 196.375 +     *
 196.376 +     * @see FieldPosition.Delegate
 196.377 +     * @see CharacterIteratorFieldDelegate
 196.378 +     */
 196.379 +    interface FieldDelegate {
 196.380 +        /**
 196.381 +         * Notified when a particular region of the String is formatted. This
 196.382 +         * method will be invoked if there is no corresponding integer field id
 196.383 +         * matching <code>attr</code>.
 196.384 +         *
 196.385 +         * @param attr Identifies the field matched
 196.386 +         * @param value Value associated with the field
 196.387 +         * @param start Beginning location of the field, will be >= 0
 196.388 +         * @param end End of the field, will be >= start and <= buffer.length()
 196.389 +         * @param buffer Contains current formatted value, receiver should
 196.390 +         *        NOT modify it.
 196.391 +         */
 196.392 +        public void formatted(Format.Field attr, Object value, int start,
 196.393 +                              int end, StringBuffer buffer);
 196.394 +
 196.395 +        /**
 196.396 +         * Notified when a particular region of the String is formatted.
 196.397 +         *
 196.398 +         * @param fieldID Identifies the field by integer
 196.399 +         * @param attr Identifies the field matched
 196.400 +         * @param value Value associated with the field
 196.401 +         * @param start Beginning location of the field, will be >= 0
 196.402 +         * @param end End of the field, will be >= start and <= buffer.length()
 196.403 +         * @param buffer Contains current formatted value, receiver should
 196.404 +         *        NOT modify it.
 196.405 +         */
 196.406 +        public void formatted(int fieldID, Format.Field attr, Object value,
 196.407 +                              int start, int end, StringBuffer buffer);
 196.408 +    }
 196.409 +}
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/rt/emul/compact/src/main/java/java/text/MessageFormat.java	Wed Apr 30 15:04:10 2014 +0200
   197.3 @@ -0,0 +1,1594 @@
   197.4 +/*
   197.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   197.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   197.7 + *
   197.8 + * This code is free software; you can redistribute it and/or modify it
   197.9 + * under the terms of the GNU General Public License version 2 only, as
  197.10 + * published by the Free Software Foundation.  Oracle designates this
  197.11 + * particular file as subject to the "Classpath" exception as provided
  197.12 + * by Oracle in the LICENSE file that accompanied this code.
  197.13 + *
  197.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  197.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  197.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  197.17 + * version 2 for more details (a copy is included in the LICENSE file that
  197.18 + * accompanied this code).
  197.19 + *
  197.20 + * You should have received a copy of the GNU General Public License version
  197.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  197.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  197.23 + *
  197.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  197.25 + * or visit www.oracle.com if you need additional information or have any
  197.26 + * questions.
  197.27 + */
  197.28 +
  197.29 +/*
  197.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  197.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  197.32 + *
  197.33 + *   The original version of this source code and documentation is copyrighted
  197.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  197.35 + * materials are provided under terms of a License Agreement between Taligent
  197.36 + * and Sun. This technology is protected by multiple US and International
  197.37 + * patents. This notice and attribution to Taligent may not be removed.
  197.38 + *   Taligent is a registered trademark of Taligent, Inc.
  197.39 + *
  197.40 + */
  197.41 +
  197.42 +package java.text;
  197.43 +
  197.44 +import java.io.InvalidObjectException;
  197.45 +import java.io.IOException;
  197.46 +import java.io.ObjectInputStream;
  197.47 +import java.text.DecimalFormat;
  197.48 +import java.util.ArrayList;
  197.49 +import java.util.Arrays;
  197.50 +import java.util.Date;
  197.51 +import java.util.List;
  197.52 +import java.util.Locale;
  197.53 +
  197.54 +
  197.55 +/**
  197.56 + * <code>MessageFormat</code> provides a means to produce concatenated
  197.57 + * messages in a language-neutral way. Use this to construct messages
  197.58 + * displayed for end users.
  197.59 + *
  197.60 + * <p>
  197.61 + * <code>MessageFormat</code> takes a set of objects, formats them, then
  197.62 + * inserts the formatted strings into the pattern at the appropriate places.
  197.63 + *
  197.64 + * <p>
  197.65 + * <strong>Note:</strong>
  197.66 + * <code>MessageFormat</code> differs from the other <code>Format</code>
  197.67 + * classes in that you create a <code>MessageFormat</code> object with one
  197.68 + * of its constructors (not with a <code>getInstance</code> style factory
  197.69 + * method). The factory methods aren't necessary because <code>MessageFormat</code>
  197.70 + * itself doesn't implement locale specific behavior. Any locale specific
  197.71 + * behavior is defined by the pattern that you provide as well as the
  197.72 + * subformats used for inserted arguments.
  197.73 + *
  197.74 + * <h4><a name="patterns">Patterns and Their Interpretation</a></h4>
  197.75 + *
  197.76 + * <code>MessageFormat</code> uses patterns of the following form:
  197.77 + * <blockquote><pre>
  197.78 + * <i>MessageFormatPattern:</i>
  197.79 + *         <i>String</i>
  197.80 + *         <i>MessageFormatPattern</i> <i>FormatElement</i> <i>String</i>
  197.81 + *
  197.82 + * <i>FormatElement:</i>
  197.83 + *         { <i>ArgumentIndex</i> }
  197.84 + *         { <i>ArgumentIndex</i> , <i>FormatType</i> }
  197.85 + *         { <i>ArgumentIndex</i> , <i>FormatType</i> , <i>FormatStyle</i> }
  197.86 + *
  197.87 + * <i>FormatType: one of </i>
  197.88 + *         number date time choice
  197.89 + *
  197.90 + * <i>FormatStyle:</i>
  197.91 + *         short
  197.92 + *         medium
  197.93 + *         long
  197.94 + *         full
  197.95 + *         integer
  197.96 + *         currency
  197.97 + *         percent
  197.98 + *         <i>SubformatPattern</i>
  197.99 + * </pre></blockquote>
 197.100 + *
 197.101 + * <p>Within a <i>String</i>, a pair of single quotes can be used to
 197.102 + * quote any arbitrary characters except single quotes. For example,
 197.103 + * pattern string <code>"'{0}'"</code> represents string
 197.104 + * <code>"{0}"</code>, not a <i>FormatElement</i>. A single quote itself
 197.105 + * must be represented by doubled single quotes {@code ''} throughout a
 197.106 + * <i>String</i>.  For example, pattern string <code>"'{''}'"</code> is
 197.107 + * interpreted as a sequence of <code>'{</code> (start of quoting and a
 197.108 + * left curly brace), <code>''</code> (a single quote), and
 197.109 + * <code>}'</code> (a right curly brace and end of quoting),
 197.110 + * <em>not</em> <code>'{'</code> and <code>'}'</code> (quoted left and
 197.111 + * right curly braces): representing string <code>"{'}"</code>,
 197.112 + * <em>not</em> <code>"{}"</code>.
 197.113 + *
 197.114 + * <p>A <i>SubformatPattern</i> is interpreted by its corresponding
 197.115 + * subformat, and subformat-dependent pattern rules apply. For example,
 197.116 + * pattern string <code>"{1,number,<u>$'#',##</u>}"</code>
 197.117 + * (<i>SubformatPattern</i> with underline) will produce a number format
 197.118 + * with the pound-sign quoted, with a result such as: {@code
 197.119 + * "$#31,45"}. Refer to each {@code Format} subclass documentation for
 197.120 + * details.
 197.121 + *
 197.122 + * <p>Any unmatched quote is treated as closed at the end of the given
 197.123 + * pattern. For example, pattern string {@code "'{0}"} is treated as
 197.124 + * pattern {@code "'{0}'"}.
 197.125 + *
 197.126 + * <p>Any curly braces within an unquoted pattern must be balanced. For
 197.127 + * example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code> are
 197.128 + * valid patterns, but <code>"ab {0'}' de"</code>, <code>"ab } de"</code>
 197.129 + * and <code>"''{''"</code> are not.
 197.130 + *
 197.131 + * <p>
 197.132 + * <dl><dt><b>Warning:</b><dd>The rules for using quotes within message
 197.133 + * format patterns unfortunately have shown to be somewhat confusing.
 197.134 + * In particular, it isn't always obvious to localizers whether single
 197.135 + * quotes need to be doubled or not. Make sure to inform localizers about
 197.136 + * the rules, and tell them (for example, by using comments in resource
 197.137 + * bundle source files) which strings will be processed by {@code MessageFormat}.
 197.138 + * Note that localizers may need to use single quotes in translated
 197.139 + * strings where the original version doesn't have them.
 197.140 + * </dl>
 197.141 + * <p>
 197.142 + * The <i>ArgumentIndex</i> value is a non-negative integer written
 197.143 + * using the digits {@code '0'} through {@code '9'}, and represents an index into the
 197.144 + * {@code arguments} array passed to the {@code format} methods
 197.145 + * or the result array returned by the {@code parse} methods.
 197.146 + * <p>
 197.147 + * The <i>FormatType</i> and <i>FormatStyle</i> values are used to create
 197.148 + * a {@code Format} instance for the format element. The following
 197.149 + * table shows how the values map to {@code Format} instances. Combinations not
 197.150 + * shown in the table are illegal. A <i>SubformatPattern</i> must
 197.151 + * be a valid pattern string for the {@code Format} subclass used.
 197.152 + * <p>
 197.153 + * <table border=1 summary="Shows how FormatType and FormatStyle values map to Format instances">
 197.154 + *    <tr>
 197.155 + *       <th id="ft" class="TableHeadingColor">FormatType
 197.156 + *       <th id="fs" class="TableHeadingColor">FormatStyle
 197.157 + *       <th id="sc" class="TableHeadingColor">Subformat Created
 197.158 + *    <tr>
 197.159 + *       <td headers="ft"><i>(none)</i>
 197.160 + *       <td headers="fs"><i>(none)</i>
 197.161 + *       <td headers="sc"><code>null</code>
 197.162 + *    <tr>
 197.163 + *       <td headers="ft" rowspan=5><code>number</code>
 197.164 + *       <td headers="fs"><i>(none)</i>
 197.165 + *       <td headers="sc">{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())}
 197.166 + *    <tr>
 197.167 + *       <td headers="fs"><code>integer</code>
 197.168 + *       <td headers="sc">{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())}
 197.169 + *    <tr>
 197.170 + *       <td headers="fs"><code>currency</code>
 197.171 + *       <td headers="sc">{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())}
 197.172 + *    <tr>
 197.173 + *       <td headers="fs"><code>percent</code>
 197.174 + *       <td headers="sc">{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())}
 197.175 + *    <tr>
 197.176 + *       <td headers="fs"><i>SubformatPattern</i>
 197.177 + *       <td headers="sc">{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))}
 197.178 + *    <tr>
 197.179 + *       <td headers="ft" rowspan=6><code>date</code>
 197.180 + *       <td headers="fs"><i>(none)</i>
 197.181 + *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
 197.182 + *    <tr>
 197.183 + *       <td headers="fs"><code>short</code>
 197.184 + *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
 197.185 + *    <tr>
 197.186 + *       <td headers="fs"><code>medium</code>
 197.187 + *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
 197.188 + *    <tr>
 197.189 + *       <td headers="fs"><code>long</code>
 197.190 + *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
 197.191 + *    <tr>
 197.192 + *       <td headers="fs"><code>full</code>
 197.193 + *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
 197.194 + *    <tr>
 197.195 + *       <td headers="fs"><i>SubformatPattern</i>
 197.196 + *       <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
 197.197 + *    <tr>
 197.198 + *       <td headers="ft" rowspan=6><code>time</code>
 197.199 + *       <td headers="fs"><i>(none)</i>
 197.200 + *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
 197.201 + *    <tr>
 197.202 + *       <td headers="fs"><code>short</code>
 197.203 + *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
 197.204 + *    <tr>
 197.205 + *       <td headers="fs"><code>medium</code>
 197.206 + *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
 197.207 + *    <tr>
 197.208 + *       <td headers="fs"><code>long</code>
 197.209 + *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
 197.210 + *    <tr>
 197.211 + *       <td headers="fs"><code>full</code>
 197.212 + *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
 197.213 + *    <tr>
 197.214 + *       <td headers="fs"><i>SubformatPattern</i>
 197.215 + *       <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
 197.216 + *    <tr>
 197.217 + *       <td headers="ft"><code>choice</code>
 197.218 + *       <td headers="fs"><i>SubformatPattern</i>
 197.219 + *       <td headers="sc">{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
 197.220 + * </table>
 197.221 + * <p>
 197.222 + *
 197.223 + * <h4>Usage Information</h4>
 197.224 + *
 197.225 + * <p>
 197.226 + * Here are some examples of usage.
 197.227 + * In real internationalized programs, the message format pattern and other
 197.228 + * static strings will, of course, be obtained from resource bundles.
 197.229 + * Other parameters will be dynamically determined at runtime.
 197.230 + * <p>
 197.231 + * The first example uses the static method <code>MessageFormat.format</code>,
 197.232 + * which internally creates a <code>MessageFormat</code> for one-time use:
 197.233 + * <blockquote><pre>
 197.234 + * int planet = 7;
 197.235 + * String event = "a disturbance in the Force";
 197.236 + *
 197.237 + * String result = MessageFormat.format(
 197.238 + *     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
 197.239 + *     planet, new Date(), event);
 197.240 + * </pre></blockquote>
 197.241 + * The output is:
 197.242 + * <blockquote><pre>
 197.243 + * At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.
 197.244 + * </pre></blockquote>
 197.245 + *
 197.246 + * <p>
 197.247 + * The following example creates a <code>MessageFormat</code> instance that
 197.248 + * can be used repeatedly:
 197.249 + * <blockquote><pre>
 197.250 + * int fileCount = 1273;
 197.251 + * String diskName = "MyDisk";
 197.252 + * Object[] testArgs = {new Long(fileCount), diskName};
 197.253 + *
 197.254 + * MessageFormat form = new MessageFormat(
 197.255 + *     "The disk \"{1}\" contains {0} file(s).");
 197.256 + *
 197.257 + * System.out.println(form.format(testArgs));
 197.258 + * </pre></blockquote>
 197.259 + * The output with different values for <code>fileCount</code>:
 197.260 + * <blockquote><pre>
 197.261 + * The disk "MyDisk" contains 0 file(s).
 197.262 + * The disk "MyDisk" contains 1 file(s).
 197.263 + * The disk "MyDisk" contains 1,273 file(s).
 197.264 + * </pre></blockquote>
 197.265 + *
 197.266 + * <p>
 197.267 + * For more sophisticated patterns, you can use a <code>ChoiceFormat</code>
 197.268 + * to produce correct forms for singular and plural:
 197.269 + * <blockquote><pre>
 197.270 + * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
 197.271 + * double[] filelimits = {0,1,2};
 197.272 + * String[] filepart = {"no files","one file","{0,number} files"};
 197.273 + * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
 197.274 + * form.setFormatByArgumentIndex(0, fileform);
 197.275 + *
 197.276 + * int fileCount = 1273;
 197.277 + * String diskName = "MyDisk";
 197.278 + * Object[] testArgs = {new Long(fileCount), diskName};
 197.279 + *
 197.280 + * System.out.println(form.format(testArgs));
 197.281 + * </pre></blockquote>
 197.282 + * The output with different values for <code>fileCount</code>:
 197.283 + * <blockquote><pre>
 197.284 + * The disk "MyDisk" contains no files.
 197.285 + * The disk "MyDisk" contains one file.
 197.286 + * The disk "MyDisk" contains 1,273 files.
 197.287 + * </pre></blockquote>
 197.288 + *
 197.289 + * <p>
 197.290 + * You can create the <code>ChoiceFormat</code> programmatically, as in the
 197.291 + * above example, or by using a pattern. See {@link ChoiceFormat}
 197.292 + * for more information.
 197.293 + * <blockquote><pre>
 197.294 + * form.applyPattern(
 197.295 + *    "There {0,choice,0#are no files|1#is one file|1&lt;are {0,number,integer} files}.");
 197.296 + * </pre></blockquote>
 197.297 + *
 197.298 + * <p>
 197.299 + * <strong>Note:</strong> As we see above, the string produced
 197.300 + * by a <code>ChoiceFormat</code> in <code>MessageFormat</code> is treated as special;
 197.301 + * occurrences of '{' are used to indicate subformats, and cause recursion.
 197.302 + * If you create both a <code>MessageFormat</code> and <code>ChoiceFormat</code>
 197.303 + * programmatically (instead of using the string patterns), then be careful not to
 197.304 + * produce a format that recurses on itself, which will cause an infinite loop.
 197.305 + * <p>
 197.306 + * When a single argument is parsed more than once in the string, the last match
 197.307 + * will be the final result of the parsing.  For example,
 197.308 + * <blockquote><pre>
 197.309 + * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
 197.310 + * Object[] objs = {new Double(3.1415)};
 197.311 + * String result = mf.format( objs );
 197.312 + * // result now equals "3.14, 3.1"
 197.313 + * objs = null;
 197.314 + * objs = mf.parse(result, new ParsePosition(0));
 197.315 + * // objs now equals {new Double(3.1)}
 197.316 + * </pre></blockquote>
 197.317 + *
 197.318 + * <p>
 197.319 + * Likewise, parsing with a {@code MessageFormat} object using patterns containing
 197.320 + * multiple occurrences of the same argument would return the last match.  For
 197.321 + * example,
 197.322 + * <blockquote><pre>
 197.323 + * MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
 197.324 + * String forParsing = "x, y, z";
 197.325 + * Object[] objs = mf.parse(forParsing, new ParsePosition(0));
 197.326 + * // result now equals {new String("z")}
 197.327 + * </pre></blockquote>
 197.328 + *
 197.329 + * <h4><a name="synchronization">Synchronization</a></h4>
 197.330 + *
 197.331 + * <p>
 197.332 + * Message formats are not synchronized.
 197.333 + * It is recommended to create separate format instances for each thread.
 197.334 + * If multiple threads access a format concurrently, it must be synchronized
 197.335 + * externally.
 197.336 + *
 197.337 + * @see          java.util.Locale
 197.338 + * @see          Format
 197.339 + * @see          NumberFormat
 197.340 + * @see          DecimalFormat
 197.341 + * @see          DecimalFormatSymbols
 197.342 + * @see          ChoiceFormat
 197.343 + * @see          DateFormat
 197.344 + * @see          SimpleDateFormat
 197.345 + *
 197.346 + * @author       Mark Davis
 197.347 + */
 197.348 +
 197.349 +public class MessageFormat extends Format {
 197.350 +
 197.351 +    private static final long serialVersionUID = 6479157306784022952L;
 197.352 +
 197.353 +    /**
 197.354 +     * Constructs a MessageFormat for the default locale and the
 197.355 +     * specified pattern.
 197.356 +     * The constructor first sets the locale, then parses the pattern and
 197.357 +     * creates a list of subformats for the format elements contained in it.
 197.358 +     * Patterns and their interpretation are specified in the
 197.359 +     * <a href="#patterns">class description</a>.
 197.360 +     *
 197.361 +     * @param pattern the pattern for this message format
 197.362 +     * @exception IllegalArgumentException if the pattern is invalid
 197.363 +     */
 197.364 +    public MessageFormat(String pattern) {
 197.365 +        this.locale = Locale.getDefault(Locale.Category.FORMAT);
 197.366 +        applyPattern(pattern);
 197.367 +    }
 197.368 +
 197.369 +    /**
 197.370 +     * Constructs a MessageFormat for the specified locale and
 197.371 +     * pattern.
 197.372 +     * The constructor first sets the locale, then parses the pattern and
 197.373 +     * creates a list of subformats for the format elements contained in it.
 197.374 +     * Patterns and their interpretation are specified in the
 197.375 +     * <a href="#patterns">class description</a>.
 197.376 +     *
 197.377 +     * @param pattern the pattern for this message format
 197.378 +     * @param locale the locale for this message format
 197.379 +     * @exception IllegalArgumentException if the pattern is invalid
 197.380 +     * @since 1.4
 197.381 +     */
 197.382 +    public MessageFormat(String pattern, Locale locale) {
 197.383 +        this.locale = locale;
 197.384 +        applyPattern(pattern);
 197.385 +    }
 197.386 +
 197.387 +    /**
 197.388 +     * Sets the locale to be used when creating or comparing subformats.
 197.389 +     * This affects subsequent calls
 197.390 +     * <ul>
 197.391 +     * <li>to the {@link #applyPattern applyPattern}
 197.392 +     *     and {@link #toPattern toPattern} methods if format elements specify
 197.393 +     *     a format type and therefore have the subformats created in the
 197.394 +     *     <code>applyPattern</code> method, as well as
 197.395 +     * <li>to the <code>format</code> and
 197.396 +     *     {@link #formatToCharacterIterator formatToCharacterIterator} methods
 197.397 +     *     if format elements do not specify a format type and therefore have
 197.398 +     *     the subformats created in the formatting methods.
 197.399 +     * </ul>
 197.400 +     * Subformats that have already been created are not affected.
 197.401 +     *
 197.402 +     * @param locale the locale to be used when creating or comparing subformats
 197.403 +     */
 197.404 +    public void setLocale(Locale locale) {
 197.405 +        this.locale = locale;
 197.406 +    }
 197.407 +
 197.408 +    /**
 197.409 +     * Gets the locale that's used when creating or comparing subformats.
 197.410 +     *
 197.411 +     * @return the locale used when creating or comparing subformats
 197.412 +     */
 197.413 +    public Locale getLocale() {
 197.414 +        return locale;
 197.415 +    }
 197.416 +
 197.417 +
 197.418 +    /**
 197.419 +     * Sets the pattern used by this message format.
 197.420 +     * The method parses the pattern and creates a list of subformats
 197.421 +     * for the format elements contained in it.
 197.422 +     * Patterns and their interpretation are specified in the
 197.423 +     * <a href="#patterns">class description</a>.
 197.424 +     *
 197.425 +     * @param pattern the pattern for this message format
 197.426 +     * @exception IllegalArgumentException if the pattern is invalid
 197.427 +     */
 197.428 +    public void applyPattern(String pattern) {
 197.429 +            StringBuilder[] segments = new StringBuilder[4];
 197.430 +            // Allocate only segments[SEG_RAW] here. The rest are
 197.431 +            // allocated on demand.
 197.432 +            segments[SEG_RAW] = new StringBuilder();
 197.433 +
 197.434 +            int part = SEG_RAW;
 197.435 +            int formatNumber = 0;
 197.436 +            boolean inQuote = false;
 197.437 +            int braceStack = 0;
 197.438 +            maxOffset = -1;
 197.439 +            for (int i = 0; i < pattern.length(); ++i) {
 197.440 +                char ch = pattern.charAt(i);
 197.441 +                if (part == SEG_RAW) {
 197.442 +                    if (ch == '\'') {
 197.443 +                        if (i + 1 < pattern.length()
 197.444 +                            && pattern.charAt(i+1) == '\'') {
 197.445 +                            segments[part].append(ch);  // handle doubles
 197.446 +                            ++i;
 197.447 +                        } else {
 197.448 +                            inQuote = !inQuote;
 197.449 +                        }
 197.450 +                    } else if (ch == '{' && !inQuote) {
 197.451 +                        part = SEG_INDEX;
 197.452 +                        if (segments[SEG_INDEX] == null) {
 197.453 +                            segments[SEG_INDEX] = new StringBuilder();
 197.454 +                        }
 197.455 +                    } else {
 197.456 +                        segments[part].append(ch);
 197.457 +                    }
 197.458 +                } else  {
 197.459 +                    if (inQuote) {              // just copy quotes in parts
 197.460 +                        segments[part].append(ch);
 197.461 +                        if (ch == '\'') {
 197.462 +                            inQuote = false;
 197.463 +                        }
 197.464 +                    } else {
 197.465 +                        switch (ch) {
 197.466 +                        case ',':
 197.467 +                            if (part < SEG_MODIFIER) {
 197.468 +                                if (segments[++part] == null) {
 197.469 +                                    segments[part] = new StringBuilder();
 197.470 +                                }
 197.471 +                            } else {
 197.472 +                                segments[part].append(ch);
 197.473 +                            }
 197.474 +                            break;
 197.475 +                        case '{':
 197.476 +                            ++braceStack;
 197.477 +                            segments[part].append(ch);
 197.478 +                            break;
 197.479 +                        case '}':
 197.480 +                            if (braceStack == 0) {
 197.481 +                                part = SEG_RAW;
 197.482 +                                makeFormat(i, formatNumber, segments);
 197.483 +                                formatNumber++;
 197.484 +                                // throw away other segments
 197.485 +                                segments[SEG_INDEX] = null;
 197.486 +                                segments[SEG_TYPE] = null;
 197.487 +                                segments[SEG_MODIFIER] = null;
 197.488 +                            } else {
 197.489 +                                --braceStack;
 197.490 +                                segments[part].append(ch);
 197.491 +                            }
 197.492 +                            break;
 197.493 +                        case ' ':
 197.494 +                            // Skip any leading space chars for SEG_TYPE.
 197.495 +                            if (part != SEG_TYPE || segments[SEG_TYPE].length() > 0) {
 197.496 +                                segments[part].append(ch);
 197.497 +                            }
 197.498 +                            break;
 197.499 +                        case '\'':
 197.500 +                            inQuote = true;
 197.501 +                            // fall through, so we keep quotes in other parts
 197.502 +                        default:
 197.503 +                            segments[part].append(ch);
 197.504 +                            break;
 197.505 +                        }
 197.506 +                    }
 197.507 +                }
 197.508 +            }
 197.509 +            if (braceStack == 0 && part != 0) {
 197.510 +                maxOffset = -1;
 197.511 +                throw new IllegalArgumentException("Unmatched braces in the pattern.");
 197.512 +            }
 197.513 +            this.pattern = segments[0].toString();
 197.514 +    }
 197.515 +
 197.516 +
 197.517 +    /**
 197.518 +     * Returns a pattern representing the current state of the message format.
 197.519 +     * The string is constructed from internal information and therefore
 197.520 +     * does not necessarily equal the previously applied pattern.
 197.521 +     *
 197.522 +     * @return a pattern representing the current state of the message format
 197.523 +     */
 197.524 +    public String toPattern() {
 197.525 +        // later, make this more extensible
 197.526 +        int lastOffset = 0;
 197.527 +        StringBuilder result = new StringBuilder();
 197.528 +        for (int i = 0; i <= maxOffset; ++i) {
 197.529 +            copyAndFixQuotes(pattern, lastOffset, offsets[i], result);
 197.530 +            lastOffset = offsets[i];
 197.531 +            result.append('{').append(argumentNumbers[i]);
 197.532 +            Format fmt = formats[i];
 197.533 +            if (fmt == null) {
 197.534 +                // do nothing, string format
 197.535 +            } else if (fmt instanceof NumberFormat) {
 197.536 +                if (fmt.equals(NumberFormat.getInstance(locale))) {
 197.537 +                    result.append(",number");
 197.538 +                } else if (fmt.equals(NumberFormat.getCurrencyInstance(locale))) {
 197.539 +                    result.append(",number,currency");
 197.540 +                } else if (fmt.equals(NumberFormat.getPercentInstance(locale))) {
 197.541 +                    result.append(",number,percent");
 197.542 +                } else if (fmt.equals(NumberFormat.getIntegerInstance(locale))) {
 197.543 +                    result.append(",number,integer");
 197.544 +                } else {
 197.545 +                    if (fmt instanceof DecimalFormat) {
 197.546 +                        result.append(",number,").append(((DecimalFormat)fmt).toPattern());
 197.547 +                    } else if (fmt instanceof ChoiceFormat) {
 197.548 +                        result.append(",choice,").append(((ChoiceFormat)fmt).toPattern());
 197.549 +                    } else {
 197.550 +                        // UNKNOWN
 197.551 +                    }
 197.552 +                }
 197.553 +            } else if (fmt instanceof DateFormat) {
 197.554 +                int index;
 197.555 +                for (index = MODIFIER_DEFAULT; index < DATE_TIME_MODIFIERS.length; index++) {
 197.556 +                    DateFormat df = DateFormat.getDateInstance(DATE_TIME_MODIFIERS[index],
 197.557 +                                                               locale);
 197.558 +                    if (fmt.equals(df)) {
 197.559 +                        result.append(",date");
 197.560 +                        break;
 197.561 +                    }
 197.562 +                    df = DateFormat.getTimeInstance(DATE_TIME_MODIFIERS[index],
 197.563 +                                                    locale);
 197.564 +                    if (fmt.equals(df)) {
 197.565 +                        result.append(",time");
 197.566 +                        break;
 197.567 +                    }
 197.568 +                }
 197.569 +                if (index >= DATE_TIME_MODIFIERS.length) {
 197.570 +                    if (fmt instanceof SimpleDateFormat) {
 197.571 +                        result.append(",date,").append(((SimpleDateFormat)fmt).toPattern());
 197.572 +                    } else {
 197.573 +                        // UNKNOWN
 197.574 +                    }
 197.575 +                } else if (index != MODIFIER_DEFAULT) {
 197.576 +                    result.append(',').append(DATE_TIME_MODIFIER_KEYWORDS[index]);
 197.577 +                }
 197.578 +            } else {
 197.579 +                //result.append(", unknown");
 197.580 +            }
 197.581 +            result.append('}');
 197.582 +        }
 197.583 +        copyAndFixQuotes(pattern, lastOffset, pattern.length(), result);
 197.584 +        return result.toString();
 197.585 +    }
 197.586 +
 197.587 +    /**
 197.588 +     * Sets the formats to use for the values passed into
 197.589 +     * <code>format</code> methods or returned from <code>parse</code>
 197.590 +     * methods. The indices of elements in <code>newFormats</code>
 197.591 +     * correspond to the argument indices used in the previously set
 197.592 +     * pattern string.
 197.593 +     * The order of formats in <code>newFormats</code> thus corresponds to
 197.594 +     * the order of elements in the <code>arguments</code> array passed
 197.595 +     * to the <code>format</code> methods or the result array returned
 197.596 +     * by the <code>parse</code> methods.
 197.597 +     * <p>
 197.598 +     * If an argument index is used for more than one format element
 197.599 +     * in the pattern string, then the corresponding new format is used
 197.600 +     * for all such format elements. If an argument index is not used
 197.601 +     * for any format element in the pattern string, then the
 197.602 +     * corresponding new format is ignored. If fewer formats are provided
 197.603 +     * than needed, then only the formats for argument indices less
 197.604 +     * than <code>newFormats.length</code> are replaced.
 197.605 +     *
 197.606 +     * @param newFormats the new formats to use
 197.607 +     * @exception NullPointerException if <code>newFormats</code> is null
 197.608 +     * @since 1.4
 197.609 +     */
 197.610 +    public void setFormatsByArgumentIndex(Format[] newFormats) {
 197.611 +        for (int i = 0; i <= maxOffset; i++) {
 197.612 +            int j = argumentNumbers[i];
 197.613 +            if (j < newFormats.length) {
 197.614 +                formats[i] = newFormats[j];
 197.615 +            }
 197.616 +        }
 197.617 +    }
 197.618 +
 197.619 +    /**
 197.620 +     * Sets the formats to use for the format elements in the
 197.621 +     * previously set pattern string.
 197.622 +     * The order of formats in <code>newFormats</code> corresponds to
 197.623 +     * the order of format elements in the pattern string.
 197.624 +     * <p>
 197.625 +     * If more formats are provided than needed by the pattern string,
 197.626 +     * the remaining ones are ignored. If fewer formats are provided
 197.627 +     * than needed, then only the first <code>newFormats.length</code>
 197.628 +     * formats are replaced.
 197.629 +     * <p>
 197.630 +     * Since the order of format elements in a pattern string often
 197.631 +     * changes during localization, it is generally better to use the
 197.632 +     * {@link #setFormatsByArgumentIndex setFormatsByArgumentIndex}
 197.633 +     * method, which assumes an order of formats corresponding to the
 197.634 +     * order of elements in the <code>arguments</code> array passed to
 197.635 +     * the <code>format</code> methods or the result array returned by
 197.636 +     * the <code>parse</code> methods.
 197.637 +     *
 197.638 +     * @param newFormats the new formats to use
 197.639 +     * @exception NullPointerException if <code>newFormats</code> is null
 197.640 +     */
 197.641 +    public void setFormats(Format[] newFormats) {
 197.642 +        int runsToCopy = newFormats.length;
 197.643 +        if (runsToCopy > maxOffset + 1) {
 197.644 +            runsToCopy = maxOffset + 1;
 197.645 +        }
 197.646 +        for (int i = 0; i < runsToCopy; i++) {
 197.647 +            formats[i] = newFormats[i];
 197.648 +        }
 197.649 +    }
 197.650 +
 197.651 +    /**
 197.652 +     * Sets the format to use for the format elements within the
 197.653 +     * previously set pattern string that use the given argument
 197.654 +     * index.
 197.655 +     * The argument index is part of the format element definition and
 197.656 +     * represents an index into the <code>arguments</code> array passed
 197.657 +     * to the <code>format</code> methods or the result array returned
 197.658 +     * by the <code>parse</code> methods.
 197.659 +     * <p>
 197.660 +     * If the argument index is used for more than one format element
 197.661 +     * in the pattern string, then the new format is used for all such
 197.662 +     * format elements. If the argument index is not used for any format
 197.663 +     * element in the pattern string, then the new format is ignored.
 197.664 +     *
 197.665 +     * @param argumentIndex the argument index for which to use the new format
 197.666 +     * @param newFormat the new format to use
 197.667 +     * @since 1.4
 197.668 +     */
 197.669 +    public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
 197.670 +        for (int j = 0; j <= maxOffset; j++) {
 197.671 +            if (argumentNumbers[j] == argumentIndex) {
 197.672 +                formats[j] = newFormat;
 197.673 +            }
 197.674 +        }
 197.675 +    }
 197.676 +
 197.677 +    /**
 197.678 +     * Sets the format to use for the format element with the given
 197.679 +     * format element index within the previously set pattern string.
 197.680 +     * The format element index is the zero-based number of the format
 197.681 +     * element counting from the start of the pattern string.
 197.682 +     * <p>
 197.683 +     * Since the order of format elements in a pattern string often
 197.684 +     * changes during localization, it is generally better to use the
 197.685 +     * {@link #setFormatByArgumentIndex setFormatByArgumentIndex}
 197.686 +     * method, which accesses format elements based on the argument
 197.687 +     * index they specify.
 197.688 +     *
 197.689 +     * @param formatElementIndex the index of a format element within the pattern
 197.690 +     * @param newFormat the format to use for the specified format element
 197.691 +     * @exception ArrayIndexOutOfBoundsException if {@code formatElementIndex} is equal to or
 197.692 +     *            larger than the number of format elements in the pattern string
 197.693 +     */
 197.694 +    public void setFormat(int formatElementIndex, Format newFormat) {
 197.695 +        formats[formatElementIndex] = newFormat;
 197.696 +    }
 197.697 +
 197.698 +    /**
 197.699 +     * Gets the formats used for the values passed into
 197.700 +     * <code>format</code> methods or returned from <code>parse</code>
 197.701 +     * methods. The indices of elements in the returned array
 197.702 +     * correspond to the argument indices used in the previously set
 197.703 +     * pattern string.
 197.704 +     * The order of formats in the returned array thus corresponds to
 197.705 +     * the order of elements in the <code>arguments</code> array passed
 197.706 +     * to the <code>format</code> methods or the result array returned
 197.707 +     * by the <code>parse</code> methods.
 197.708 +     * <p>
 197.709 +     * If an argument index is used for more than one format element
 197.710 +     * in the pattern string, then the format used for the last such
 197.711 +     * format element is returned in the array. If an argument index
 197.712 +     * is not used for any format element in the pattern string, then
 197.713 +     * null is returned in the array.
 197.714 +     *
 197.715 +     * @return the formats used for the arguments within the pattern
 197.716 +     * @since 1.4
 197.717 +     */
 197.718 +    public Format[] getFormatsByArgumentIndex() {
 197.719 +        int maximumArgumentNumber = -1;
 197.720 +        for (int i = 0; i <= maxOffset; i++) {
 197.721 +            if (argumentNumbers[i] > maximumArgumentNumber) {
 197.722 +                maximumArgumentNumber = argumentNumbers[i];
 197.723 +            }
 197.724 +        }
 197.725 +        Format[] resultArray = new Format[maximumArgumentNumber + 1];
 197.726 +        for (int i = 0; i <= maxOffset; i++) {
 197.727 +            resultArray[argumentNumbers[i]] = formats[i];
 197.728 +        }
 197.729 +        return resultArray;
 197.730 +    }
 197.731 +
 197.732 +    /**
 197.733 +     * Gets the formats used for the format elements in the
 197.734 +     * previously set pattern string.
 197.735 +     * The order of formats in the returned array corresponds to
 197.736 +     * the order of format elements in the pattern string.
 197.737 +     * <p>
 197.738 +     * Since the order of format elements in a pattern string often
 197.739 +     * changes during localization, it's generally better to use the
 197.740 +     * {@link #getFormatsByArgumentIndex getFormatsByArgumentIndex}
 197.741 +     * method, which assumes an order of formats corresponding to the
 197.742 +     * order of elements in the <code>arguments</code> array passed to
 197.743 +     * the <code>format</code> methods or the result array returned by
 197.744 +     * the <code>parse</code> methods.
 197.745 +     *
 197.746 +     * @return the formats used for the format elements in the pattern
 197.747 +     */
 197.748 +    public Format[] getFormats() {
 197.749 +        Format[] resultArray = new Format[maxOffset + 1];
 197.750 +        System.arraycopy(formats, 0, resultArray, 0, maxOffset + 1);
 197.751 +        return resultArray;
 197.752 +    }
 197.753 +
 197.754 +    /**
 197.755 +     * Formats an array of objects and appends the <code>MessageFormat</code>'s
 197.756 +     * pattern, with format elements replaced by the formatted objects, to the
 197.757 +     * provided <code>StringBuffer</code>.
 197.758 +     * <p>
 197.759 +     * The text substituted for the individual format elements is derived from
 197.760 +     * the current subformat of the format element and the
 197.761 +     * <code>arguments</code> element at the format element's argument index
 197.762 +     * as indicated by the first matching line of the following table. An
 197.763 +     * argument is <i>unavailable</i> if <code>arguments</code> is
 197.764 +     * <code>null</code> or has fewer than argumentIndex+1 elements.
 197.765 +     * <p>
 197.766 +     * <table border=1 summary="Examples of subformat,argument,and formatted text">
 197.767 +     *    <tr>
 197.768 +     *       <th>Subformat
 197.769 +     *       <th>Argument
 197.770 +     *       <th>Formatted Text
 197.771 +     *    <tr>
 197.772 +     *       <td><i>any</i>
 197.773 +     *       <td><i>unavailable</i>
 197.774 +     *       <td><code>"{" + argumentIndex + "}"</code>
 197.775 +     *    <tr>
 197.776 +     *       <td><i>any</i>
 197.777 +     *       <td><code>null</code>
 197.778 +     *       <td><code>"null"</code>
 197.779 +     *    <tr>
 197.780 +     *       <td><code>instanceof ChoiceFormat</code>
 197.781 +     *       <td><i>any</i>
 197.782 +     *       <td><code>subformat.format(argument).indexOf('{') >= 0 ?<br>
 197.783 +     *           (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
 197.784 +     *           subformat.format(argument)</code>
 197.785 +     *    <tr>
 197.786 +     *       <td><code>!= null</code>
 197.787 +     *       <td><i>any</i>
 197.788 +     *       <td><code>subformat.format(argument)</code>
 197.789 +     *    <tr>
 197.790 +     *       <td><code>null</code>
 197.791 +     *       <td><code>instanceof Number</code>
 197.792 +     *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
 197.793 +     *    <tr>
 197.794 +     *       <td><code>null</code>
 197.795 +     *       <td><code>instanceof Date</code>
 197.796 +     *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()).format(argument)</code>
 197.797 +     *    <tr>
 197.798 +     *       <td><code>null</code>
 197.799 +     *       <td><code>instanceof String</code>
 197.800 +     *       <td><code>argument</code>
 197.801 +     *    <tr>
 197.802 +     *       <td><code>null</code>
 197.803 +     *       <td><i>any</i>
 197.804 +     *       <td><code>argument.toString()</code>
 197.805 +     * </table>
 197.806 +     * <p>
 197.807 +     * If <code>pos</code> is non-null, and refers to
 197.808 +     * <code>Field.ARGUMENT</code>, the location of the first formatted
 197.809 +     * string will be returned.
 197.810 +     *
 197.811 +     * @param arguments an array of objects to be formatted and substituted.
 197.812 +     * @param result where text is appended.
 197.813 +     * @param pos On input: an alignment field, if desired.
 197.814 +     *            On output: the offsets of the alignment field.
 197.815 +     * @exception IllegalArgumentException if an argument in the
 197.816 +     *            <code>arguments</code> array is not of the type
 197.817 +     *            expected by the format element(s) that use it.
 197.818 +     */
 197.819 +    public final StringBuffer format(Object[] arguments, StringBuffer result,
 197.820 +                                     FieldPosition pos)
 197.821 +    {
 197.822 +        return subformat(arguments, result, pos, null);
 197.823 +    }
 197.824 +
 197.825 +    /**
 197.826 +     * Creates a MessageFormat with the given pattern and uses it
 197.827 +     * to format the given arguments. This is equivalent to
 197.828 +     * <blockquote>
 197.829 +     *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 197.830 +     * </blockquote>
 197.831 +     *
 197.832 +     * @exception IllegalArgumentException if the pattern is invalid,
 197.833 +     *            or if an argument in the <code>arguments</code> array
 197.834 +     *            is not of the type expected by the format element(s)
 197.835 +     *            that use it.
 197.836 +     */
 197.837 +    public static String format(String pattern, Object ... arguments) {
 197.838 +        MessageFormat temp = new MessageFormat(pattern);
 197.839 +        return temp.format(arguments);
 197.840 +    }
 197.841 +
 197.842 +    // Overrides
 197.843 +    /**
 197.844 +     * Formats an array of objects and appends the <code>MessageFormat</code>'s
 197.845 +     * pattern, with format elements replaced by the formatted objects, to the
 197.846 +     * provided <code>StringBuffer</code>.
 197.847 +     * This is equivalent to
 197.848 +     * <blockquote>
 197.849 +     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
 197.850 +     * </blockquote>
 197.851 +     *
 197.852 +     * @param arguments an array of objects to be formatted and substituted.
 197.853 +     * @param result where text is appended.
 197.854 +     * @param pos On input: an alignment field, if desired.
 197.855 +     *            On output: the offsets of the alignment field.
 197.856 +     * @exception IllegalArgumentException if an argument in the
 197.857 +     *            <code>arguments</code> array is not of the type
 197.858 +     *            expected by the format element(s) that use it.
 197.859 +     */
 197.860 +    public final StringBuffer format(Object arguments, StringBuffer result,
 197.861 +                                     FieldPosition pos)
 197.862 +    {
 197.863 +        return subformat((Object[]) arguments, result, pos, null);
 197.864 +    }
 197.865 +
 197.866 +    /**
 197.867 +     * Formats an array of objects and inserts them into the
 197.868 +     * <code>MessageFormat</code>'s pattern, producing an
 197.869 +     * <code>AttributedCharacterIterator</code>.
 197.870 +     * You can use the returned <code>AttributedCharacterIterator</code>
 197.871 +     * to build the resulting String, as well as to determine information
 197.872 +     * about the resulting String.
 197.873 +     * <p>
 197.874 +     * The text of the returned <code>AttributedCharacterIterator</code> is
 197.875 +     * the same that would be returned by
 197.876 +     * <blockquote>
 197.877 +     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 197.878 +     * </blockquote>
 197.879 +     * <p>
 197.880 +     * In addition, the <code>AttributedCharacterIterator</code> contains at
 197.881 +     * least attributes indicating where text was generated from an
 197.882 +     * argument in the <code>arguments</code> array. The keys of these attributes are of
 197.883 +     * type <code>MessageFormat.Field</code>, their values are
 197.884 +     * <code>Integer</code> objects indicating the index in the <code>arguments</code>
 197.885 +     * array of the argument from which the text was generated.
 197.886 +     * <p>
 197.887 +     * The attributes/value from the underlying <code>Format</code>
 197.888 +     * instances that <code>MessageFormat</code> uses will also be
 197.889 +     * placed in the resulting <code>AttributedCharacterIterator</code>.
 197.890 +     * This allows you to not only find where an argument is placed in the
 197.891 +     * resulting String, but also which fields it contains in turn.
 197.892 +     *
 197.893 +     * @param arguments an array of objects to be formatted and substituted.
 197.894 +     * @return AttributedCharacterIterator describing the formatted value.
 197.895 +     * @exception NullPointerException if <code>arguments</code> is null.
 197.896 +     * @exception IllegalArgumentException if an argument in the
 197.897 +     *            <code>arguments</code> array is not of the type
 197.898 +     *            expected by the format element(s) that use it.
 197.899 +     * @since 1.4
 197.900 +     */
 197.901 +    public AttributedCharacterIterator formatToCharacterIterator(Object arguments) {
 197.902 +        StringBuffer result = new StringBuffer();
 197.903 +        ArrayList iterators = new ArrayList();
 197.904 +
 197.905 +        if (arguments == null) {
 197.906 +            throw new NullPointerException(
 197.907 +                   "formatToCharacterIterator must be passed non-null object");
 197.908 +        }
 197.909 +        subformat((Object[]) arguments, result, null, iterators);
 197.910 +        if (iterators.size() == 0) {
 197.911 +            return createAttributedCharacterIterator("");
 197.912 +        }
 197.913 +        return createAttributedCharacterIterator(
 197.914 +                     (AttributedCharacterIterator[])iterators.toArray(
 197.915 +                     new AttributedCharacterIterator[iterators.size()]));
 197.916 +    }
 197.917 +
 197.918 +    /**
 197.919 +     * Parses the string.
 197.920 +     *
 197.921 +     * <p>Caveats: The parse may fail in a number of circumstances.
 197.922 +     * For example:
 197.923 +     * <ul>
 197.924 +     * <li>If one of the arguments does not occur in the pattern.
 197.925 +     * <li>If the format of an argument loses information, such as
 197.926 +     *     with a choice format where a large number formats to "many".
 197.927 +     * <li>Does not yet handle recursion (where
 197.928 +     *     the substituted strings contain {n} references.)
 197.929 +     * <li>Will not always find a match (or the correct match)
 197.930 +     *     if some part of the parse is ambiguous.
 197.931 +     *     For example, if the pattern "{1},{2}" is used with the
 197.932 +     *     string arguments {"a,b", "c"}, it will format as "a,b,c".
 197.933 +     *     When the result is parsed, it will return {"a", "b,c"}.
 197.934 +     * <li>If a single argument is parsed more than once in the string,
 197.935 +     *     then the later parse wins.
 197.936 +     * </ul>
 197.937 +     * When the parse fails, use ParsePosition.getErrorIndex() to find out
 197.938 +     * where in the string the parsing failed.  The returned error
 197.939 +     * index is the starting offset of the sub-patterns that the string
 197.940 +     * is comparing with.  For example, if the parsing string "AAA {0} BBB"
 197.941 +     * is comparing against the pattern "AAD {0} BBB", the error index is
 197.942 +     * 0. When an error occurs, the call to this method will return null.
 197.943 +     * If the source is null, return an empty array.
 197.944 +     */
 197.945 +    public Object[] parse(String source, ParsePosition pos) {
 197.946 +        if (source == null) {
 197.947 +            Object[] empty = {};
 197.948 +            return empty;
 197.949 +        }
 197.950 +
 197.951 +        int maximumArgumentNumber = -1;
 197.952 +        for (int i = 0; i <= maxOffset; i++) {
 197.953 +            if (argumentNumbers[i] > maximumArgumentNumber) {
 197.954 +                maximumArgumentNumber = argumentNumbers[i];
 197.955 +            }
 197.956 +        }
 197.957 +        Object[] resultArray = new Object[maximumArgumentNumber + 1];
 197.958 +
 197.959 +        int patternOffset = 0;
 197.960 +        int sourceOffset = pos.index;
 197.961 +        ParsePosition tempStatus = new ParsePosition(0);
 197.962 +        for (int i = 0; i <= maxOffset; ++i) {
 197.963 +            // match up to format
 197.964 +            int len = offsets[i] - patternOffset;
 197.965 +            if (len == 0 || pattern.regionMatches(patternOffset,
 197.966 +                                                  source, sourceOffset, len)) {
 197.967 +                sourceOffset += len;
 197.968 +                patternOffset += len;
 197.969 +            } else {
 197.970 +                pos.errorIndex = sourceOffset;
 197.971 +                return null; // leave index as is to signal error
 197.972 +            }
 197.973 +
 197.974 +            // now use format
 197.975 +            if (formats[i] == null) {   // string format
 197.976 +                // if at end, use longest possible match
 197.977 +                // otherwise uses first match to intervening string
 197.978 +                // does NOT recursively try all possibilities
 197.979 +                int tempLength = (i != maxOffset) ? offsets[i+1] : pattern.length();
 197.980 +
 197.981 +                int next;
 197.982 +                if (patternOffset >= tempLength) {
 197.983 +                    next = source.length();
 197.984 +                }else{
 197.985 +                    next = source.indexOf(pattern.substring(patternOffset, tempLength),
 197.986 +                                          sourceOffset);
 197.987 +                }
 197.988 +
 197.989 +                if (next < 0) {
 197.990 +                    pos.errorIndex = sourceOffset;
 197.991 +                    return null; // leave index as is to signal error
 197.992 +                } else {
 197.993 +                    String strValue= source.substring(sourceOffset,next);
 197.994 +                    if (!strValue.equals("{"+argumentNumbers[i]+"}"))
 197.995 +                        resultArray[argumentNumbers[i]]
 197.996 +                            = source.substring(sourceOffset,next);
 197.997 +                    sourceOffset = next;
 197.998 +                }
 197.999 +            } else {
197.1000 +                tempStatus.index = sourceOffset;
197.1001 +                resultArray[argumentNumbers[i]]
197.1002 +                    = formats[i].parseObject(source,tempStatus);
197.1003 +                if (tempStatus.index == sourceOffset) {
197.1004 +                    pos.errorIndex = sourceOffset;
197.1005 +                    return null; // leave index as is to signal error
197.1006 +                }
197.1007 +                sourceOffset = tempStatus.index; // update
197.1008 +            }
197.1009 +        }
197.1010 +        int len = pattern.length() - patternOffset;
197.1011 +        if (len == 0 || pattern.regionMatches(patternOffset,
197.1012 +                                              source, sourceOffset, len)) {
197.1013 +            pos.index = sourceOffset + len;
197.1014 +        } else {
197.1015 +            pos.errorIndex = sourceOffset;
197.1016 +            return null; // leave index as is to signal error
197.1017 +        }
197.1018 +        return resultArray;
197.1019 +    }
197.1020 +
197.1021 +    /**
197.1022 +     * Parses text from the beginning of the given string to produce an object
197.1023 +     * array.
197.1024 +     * The method may not use the entire text of the given string.
197.1025 +     * <p>
197.1026 +     * See the {@link #parse(String, ParsePosition)} method for more information
197.1027 +     * on message parsing.
197.1028 +     *
197.1029 +     * @param source A <code>String</code> whose beginning should be parsed.
197.1030 +     * @return An <code>Object</code> array parsed from the string.
197.1031 +     * @exception ParseException if the beginning of the specified string
197.1032 +     *            cannot be parsed.
197.1033 +     */
197.1034 +    public Object[] parse(String source) throws ParseException {
197.1035 +        ParsePosition pos  = new ParsePosition(0);
197.1036 +        Object[] result = parse(source, pos);
197.1037 +        if (pos.index == 0)  // unchanged, returned object is null
197.1038 +            throw new ParseException("MessageFormat parse error!", pos.errorIndex);
197.1039 +
197.1040 +        return result;
197.1041 +    }
197.1042 +
197.1043 +    /**
197.1044 +     * Parses text from a string to produce an object array.
197.1045 +     * <p>
197.1046 +     * The method attempts to parse text starting at the index given by
197.1047 +     * <code>pos</code>.
197.1048 +     * If parsing succeeds, then the index of <code>pos</code> is updated
197.1049 +     * to the index after the last character used (parsing does not necessarily
197.1050 +     * use all characters up to the end of the string), and the parsed
197.1051 +     * object array is returned. The updated <code>pos</code> can be used to
197.1052 +     * indicate the starting point for the next call to this method.
197.1053 +     * If an error occurs, then the index of <code>pos</code> is not
197.1054 +     * changed, the error index of <code>pos</code> is set to the index of
197.1055 +     * the character where the error occurred, and null is returned.
197.1056 +     * <p>
197.1057 +     * See the {@link #parse(String, ParsePosition)} method for more information
197.1058 +     * on message parsing.
197.1059 +     *
197.1060 +     * @param source A <code>String</code>, part of which should be parsed.
197.1061 +     * @param pos A <code>ParsePosition</code> object with index and error
197.1062 +     *            index information as described above.
197.1063 +     * @return An <code>Object</code> array parsed from the string. In case of
197.1064 +     *         error, returns null.
197.1065 +     * @exception NullPointerException if <code>pos</code> is null.
197.1066 +     */
197.1067 +    public Object parseObject(String source, ParsePosition pos) {
197.1068 +        return parse(source, pos);
197.1069 +    }
197.1070 +
197.1071 +    /**
197.1072 +     * Creates and returns a copy of this object.
197.1073 +     *
197.1074 +     * @return a clone of this instance.
197.1075 +     */
197.1076 +    public Object clone() {
197.1077 +        MessageFormat other = (MessageFormat) super.clone();
197.1078 +
197.1079 +        // clone arrays. Can't do with utility because of bug in Cloneable
197.1080 +        other.formats = (Format[]) formats.clone(); // shallow clone
197.1081 +        for (int i = 0; i < formats.length; ++i) {
197.1082 +            if (formats[i] != null)
197.1083 +                other.formats[i] = (Format)formats[i].clone();
197.1084 +        }
197.1085 +        // for primitives or immutables, shallow clone is enough
197.1086 +        other.offsets = (int[]) offsets.clone();
197.1087 +        other.argumentNumbers = (int[]) argumentNumbers.clone();
197.1088 +
197.1089 +        return other;
197.1090 +    }
197.1091 +
197.1092 +    /**
197.1093 +     * Equality comparison between two message format objects
197.1094 +     */
197.1095 +    public boolean equals(Object obj) {
197.1096 +        if (this == obj)                      // quick check
197.1097 +            return true;
197.1098 +        if (obj == null || getClass() != obj.getClass())
197.1099 +            return false;
197.1100 +        MessageFormat other = (MessageFormat) obj;
197.1101 +        return (maxOffset == other.maxOffset
197.1102 +                && pattern.equals(other.pattern)
197.1103 +                && ((locale != null && locale.equals(other.locale))
197.1104 +                 || (locale == null && other.locale == null))
197.1105 +                && Arrays.equals(offsets,other.offsets)
197.1106 +                && Arrays.equals(argumentNumbers,other.argumentNumbers)
197.1107 +                && Arrays.equals(formats,other.formats));
197.1108 +    }
197.1109 +
197.1110 +    /**
197.1111 +     * Generates a hash code for the message format object.
197.1112 +     */
197.1113 +    public int hashCode() {
197.1114 +        return pattern.hashCode(); // enough for reasonable distribution
197.1115 +    }
197.1116 +
197.1117 +
197.1118 +    /**
197.1119 +     * Defines constants that are used as attribute keys in the
197.1120 +     * <code>AttributedCharacterIterator</code> returned
197.1121 +     * from <code>MessageFormat.formatToCharacterIterator</code>.
197.1122 +     *
197.1123 +     * @since 1.4
197.1124 +     */
197.1125 +    public static class Field extends Format.Field {
197.1126 +
197.1127 +        // Proclaim serial compatibility with 1.4 FCS
197.1128 +        private static final long serialVersionUID = 7899943957617360810L;
197.1129 +
197.1130 +        /**
197.1131 +         * Creates a Field with the specified name.
197.1132 +         *
197.1133 +         * @param name Name of the attribute
197.1134 +         */
197.1135 +        protected Field(String name) {
197.1136 +            super(name);
197.1137 +        }
197.1138 +
197.1139 +        /**
197.1140 +         * Resolves instances being deserialized to the predefined constants.
197.1141 +         *
197.1142 +         * @throws InvalidObjectException if the constant could not be
197.1143 +         *         resolved.
197.1144 +         * @return resolved MessageFormat.Field constant
197.1145 +         */
197.1146 +        protected Object readResolve() throws InvalidObjectException {
197.1147 +            if (this.getClass() != MessageFormat.Field.class) {
197.1148 +                throw new InvalidObjectException("subclass didn't correctly implement readResolve");
197.1149 +            }
197.1150 +
197.1151 +            return ARGUMENT;
197.1152 +        }
197.1153 +
197.1154 +        //
197.1155 +        // The constants
197.1156 +        //
197.1157 +
197.1158 +        /**
197.1159 +         * Constant identifying a portion of a message that was generated
197.1160 +         * from an argument passed into <code>formatToCharacterIterator</code>.
197.1161 +         * The value associated with the key will be an <code>Integer</code>
197.1162 +         * indicating the index in the <code>arguments</code> array of the
197.1163 +         * argument from which the text was generated.
197.1164 +         */
197.1165 +        public final static Field ARGUMENT =
197.1166 +                           new Field("message argument field");
197.1167 +    }
197.1168 +
197.1169 +    // ===========================privates============================
197.1170 +
197.1171 +    /**
197.1172 +     * The locale to use for formatting numbers and dates.
197.1173 +     * @serial
197.1174 +     */
197.1175 +    private Locale locale;
197.1176 +
197.1177 +    /**
197.1178 +     * The string that the formatted values are to be plugged into.  In other words, this
197.1179 +     * is the pattern supplied on construction with all of the {} expressions taken out.
197.1180 +     * @serial
197.1181 +     */
197.1182 +    private String pattern = "";
197.1183 +
197.1184 +    /** The initially expected number of subformats in the format */
197.1185 +    private static final int INITIAL_FORMATS = 10;
197.1186 +
197.1187 +    /**
197.1188 +     * An array of formatters, which are used to format the arguments.
197.1189 +     * @serial
197.1190 +     */
197.1191 +    private Format[] formats = new Format[INITIAL_FORMATS];
197.1192 +
197.1193 +    /**
197.1194 +     * The positions where the results of formatting each argument are to be inserted
197.1195 +     * into the pattern.
197.1196 +     * @serial
197.1197 +     */
197.1198 +    private int[] offsets = new int[INITIAL_FORMATS];
197.1199 +
197.1200 +    /**
197.1201 +     * The argument numbers corresponding to each formatter.  (The formatters are stored
197.1202 +     * in the order they occur in the pattern, not in the order in which the arguments
197.1203 +     * are specified.)
197.1204 +     * @serial
197.1205 +     */
197.1206 +    private int[] argumentNumbers = new int[INITIAL_FORMATS];
197.1207 +
197.1208 +    /**
197.1209 +     * One less than the number of entries in <code>offsets</code>.  Can also be thought of
197.1210 +     * as the index of the highest-numbered element in <code>offsets</code> that is being used.
197.1211 +     * All of these arrays should have the same number of elements being used as <code>offsets</code>
197.1212 +     * does, and so this variable suffices to tell us how many entries are in all of them.
197.1213 +     * @serial
197.1214 +     */
197.1215 +    private int maxOffset = -1;
197.1216 +
197.1217 +    /**
197.1218 +     * Internal routine used by format. If <code>characterIterators</code> is
197.1219 +     * non-null, AttributedCharacterIterator will be created from the
197.1220 +     * subformats as necessary. If <code>characterIterators</code> is null
197.1221 +     * and <code>fp</code> is non-null and identifies
197.1222 +     * <code>Field.MESSAGE_ARGUMENT</code>, the location of
197.1223 +     * the first replaced argument will be set in it.
197.1224 +     *
197.1225 +     * @exception IllegalArgumentException if an argument in the
197.1226 +     *            <code>arguments</code> array is not of the type
197.1227 +     *            expected by the format element(s) that use it.
197.1228 +     */
197.1229 +    private StringBuffer subformat(Object[] arguments, StringBuffer result,
197.1230 +                                   FieldPosition fp, List characterIterators) {
197.1231 +        // note: this implementation assumes a fast substring & index.
197.1232 +        // if this is not true, would be better to append chars one by one.
197.1233 +        int lastOffset = 0;
197.1234 +        int last = result.length();
197.1235 +        for (int i = 0; i <= maxOffset; ++i) {
197.1236 +            result.append(pattern.substring(lastOffset, offsets[i]));
197.1237 +            lastOffset = offsets[i];
197.1238 +            int argumentNumber = argumentNumbers[i];
197.1239 +            if (arguments == null || argumentNumber >= arguments.length) {
197.1240 +                result.append('{').append(argumentNumber).append('}');
197.1241 +                continue;
197.1242 +            }
197.1243 +            // int argRecursion = ((recursionProtection >> (argumentNumber*2)) & 0x3);
197.1244 +            if (false) { // if (argRecursion == 3){
197.1245 +                // prevent loop!!!
197.1246 +                result.append('\uFFFD');
197.1247 +            } else {
197.1248 +                Object obj = arguments[argumentNumber];
197.1249 +                String arg = null;
197.1250 +                Format subFormatter = null;
197.1251 +                if (obj == null) {
197.1252 +                    arg = "null";
197.1253 +                } else if (formats[i] != null) {
197.1254 +                    subFormatter = formats[i];
197.1255 +                    if (subFormatter instanceof ChoiceFormat) {
197.1256 +                        arg = formats[i].format(obj);
197.1257 +                        if (arg.indexOf('{') >= 0) {
197.1258 +                            subFormatter = new MessageFormat(arg, locale);
197.1259 +                            obj = arguments;
197.1260 +                            arg = null;
197.1261 +                        }
197.1262 +                    }
197.1263 +                } else if (obj instanceof Number) {
197.1264 +                    // format number if can
197.1265 +                    subFormatter = NumberFormat.getInstance(locale);
197.1266 +                } else if (obj instanceof Date) {
197.1267 +                    // format a Date if can
197.1268 +                    subFormatter = DateFormat.getDateTimeInstance(
197.1269 +                             DateFormat.SHORT, DateFormat.SHORT, locale);//fix
197.1270 +                } else if (obj instanceof String) {
197.1271 +                    arg = (String) obj;
197.1272 +
197.1273 +                } else {
197.1274 +                    arg = obj.toString();
197.1275 +                    if (arg == null) arg = "null";
197.1276 +                }
197.1277 +
197.1278 +                // At this point we are in two states, either subFormatter
197.1279 +                // is non-null indicating we should format obj using it,
197.1280 +                // or arg is non-null and we should use it as the value.
197.1281 +
197.1282 +                if (characterIterators != null) {
197.1283 +                    // If characterIterators is non-null, it indicates we need
197.1284 +                    // to get the CharacterIterator from the child formatter.
197.1285 +                    if (last != result.length()) {
197.1286 +                        characterIterators.add(
197.1287 +                            createAttributedCharacterIterator(result.substring
197.1288 +                                                              (last)));
197.1289 +                        last = result.length();
197.1290 +                    }
197.1291 +                    if (subFormatter != null) {
197.1292 +                        AttributedCharacterIterator subIterator =
197.1293 +                                   subFormatter.formatToCharacterIterator(obj);
197.1294 +
197.1295 +                        append(result, subIterator);
197.1296 +                        if (last != result.length()) {
197.1297 +                            characterIterators.add(
197.1298 +                                         createAttributedCharacterIterator(
197.1299 +                                         subIterator, Field.ARGUMENT,
197.1300 +                                         Integer.valueOf(argumentNumber)));
197.1301 +                            last = result.length();
197.1302 +                        }
197.1303 +                        arg = null;
197.1304 +                    }
197.1305 +                    if (arg != null && arg.length() > 0) {
197.1306 +                        result.append(arg);
197.1307 +                        characterIterators.add(
197.1308 +                                 createAttributedCharacterIterator(
197.1309 +                                 arg, Field.ARGUMENT,
197.1310 +                                 Integer.valueOf(argumentNumber)));
197.1311 +                        last = result.length();
197.1312 +                    }
197.1313 +                }
197.1314 +                else {
197.1315 +                    if (subFormatter != null) {
197.1316 +                        arg = subFormatter.format(obj);
197.1317 +                    }
197.1318 +                    last = result.length();
197.1319 +                    result.append(arg);
197.1320 +                    if (i == 0 && fp != null && Field.ARGUMENT.equals(
197.1321 +                                  fp.getFieldAttribute())) {
197.1322 +                        fp.setBeginIndex(last);
197.1323 +                        fp.setEndIndex(result.length());
197.1324 +                    }
197.1325 +                    last = result.length();
197.1326 +                }
197.1327 +            }
197.1328 +        }
197.1329 +        result.append(pattern.substring(lastOffset, pattern.length()));
197.1330 +        if (characterIterators != null && last != result.length()) {
197.1331 +            characterIterators.add(createAttributedCharacterIterator(
197.1332 +                                   result.substring(last)));
197.1333 +        }
197.1334 +        return result;
197.1335 +    }
197.1336 +
197.1337 +    /**
197.1338 +     * Convenience method to append all the characters in
197.1339 +     * <code>iterator</code> to the StringBuffer <code>result</code>.
197.1340 +     */
197.1341 +    private void append(StringBuffer result, CharacterIterator iterator) {
197.1342 +        if (iterator.first() != CharacterIterator.DONE) {
197.1343 +            char aChar;
197.1344 +
197.1345 +            result.append(iterator.first());
197.1346 +            while ((aChar = iterator.next()) != CharacterIterator.DONE) {
197.1347 +                result.append(aChar);
197.1348 +            }
197.1349 +        }
197.1350 +    }
197.1351 +
197.1352 +    // Indices for segments
197.1353 +    private static final int SEG_RAW      = 0;
197.1354 +    private static final int SEG_INDEX    = 1;
197.1355 +    private static final int SEG_TYPE     = 2;
197.1356 +    private static final int SEG_MODIFIER = 3; // modifier or subformat
197.1357 +
197.1358 +    // Indices for type keywords
197.1359 +    private static final int TYPE_NULL    = 0;
197.1360 +    private static final int TYPE_NUMBER  = 1;
197.1361 +    private static final int TYPE_DATE    = 2;
197.1362 +    private static final int TYPE_TIME    = 3;
197.1363 +    private static final int TYPE_CHOICE  = 4;
197.1364 +
197.1365 +    private static final String[] TYPE_KEYWORDS = {
197.1366 +        "",
197.1367 +        "number",
197.1368 +        "date",
197.1369 +        "time",
197.1370 +        "choice"
197.1371 +    };
197.1372 +
197.1373 +    // Indices for number modifiers
197.1374 +    private static final int MODIFIER_DEFAULT  = 0; // common in number and date-time
197.1375 +    private static final int MODIFIER_CURRENCY = 1;
197.1376 +    private static final int MODIFIER_PERCENT  = 2;
197.1377 +    private static final int MODIFIER_INTEGER  = 3;
197.1378 +
197.1379 +    private static final String[] NUMBER_MODIFIER_KEYWORDS = {
197.1380 +        "",
197.1381 +        "currency",
197.1382 +        "percent",
197.1383 +        "integer"
197.1384 +    };
197.1385 +
197.1386 +    // Indices for date-time modifiers
197.1387 +    private static final int MODIFIER_SHORT   = 1;
197.1388 +    private static final int MODIFIER_MEDIUM  = 2;
197.1389 +    private static final int MODIFIER_LONG    = 3;
197.1390 +    private static final int MODIFIER_FULL    = 4;
197.1391 +
197.1392 +    private static final String[] DATE_TIME_MODIFIER_KEYWORDS = {
197.1393 +        "",
197.1394 +        "short",
197.1395 +        "medium",
197.1396 +        "long",
197.1397 +        "full"
197.1398 +    };
197.1399 +
197.1400 +    // Date-time style values corresponding to the date-time modifiers.
197.1401 +    private static final int[] DATE_TIME_MODIFIERS = {
197.1402 +        DateFormat.DEFAULT,
197.1403 +        DateFormat.SHORT,
197.1404 +        DateFormat.MEDIUM,
197.1405 +        DateFormat.LONG,
197.1406 +        DateFormat.FULL,
197.1407 +    };
197.1408 +
197.1409 +    private void makeFormat(int position, int offsetNumber,
197.1410 +                            StringBuilder[] textSegments)
197.1411 +    {
197.1412 +        String[] segments = new String[textSegments.length];
197.1413 +        for (int i = 0; i < textSegments.length; i++) {
197.1414 +            StringBuilder oneseg = textSegments[i];
197.1415 +            segments[i] = (oneseg != null) ? oneseg.toString() : "";
197.1416 +        }
197.1417 +
197.1418 +        // get the argument number
197.1419 +        int argumentNumber;
197.1420 +        try {
197.1421 +            argumentNumber = Integer.parseInt(segments[SEG_INDEX]); // always unlocalized!
197.1422 +        } catch (NumberFormatException e) {
197.1423 +            throw new IllegalArgumentException("can't parse argument number: "
197.1424 +                                               + segments[SEG_INDEX], e);
197.1425 +        }
197.1426 +        if (argumentNumber < 0) {
197.1427 +            throw new IllegalArgumentException("negative argument number: "
197.1428 +                                               + argumentNumber);
197.1429 +        }
197.1430 +
197.1431 +        // resize format information arrays if necessary
197.1432 +        if (offsetNumber >= formats.length) {
197.1433 +            int newLength = formats.length * 2;
197.1434 +            Format[] newFormats = new Format[newLength];
197.1435 +            int[] newOffsets = new int[newLength];
197.1436 +            int[] newArgumentNumbers = new int[newLength];
197.1437 +            System.arraycopy(formats, 0, newFormats, 0, maxOffset + 1);
197.1438 +            System.arraycopy(offsets, 0, newOffsets, 0, maxOffset + 1);
197.1439 +            System.arraycopy(argumentNumbers, 0, newArgumentNumbers, 0, maxOffset + 1);
197.1440 +            formats = newFormats;
197.1441 +            offsets = newOffsets;
197.1442 +            argumentNumbers = newArgumentNumbers;
197.1443 +        }
197.1444 +        int oldMaxOffset = maxOffset;
197.1445 +        maxOffset = offsetNumber;
197.1446 +        offsets[offsetNumber] = segments[SEG_RAW].length();
197.1447 +        argumentNumbers[offsetNumber] = argumentNumber;
197.1448 +
197.1449 +        // now get the format
197.1450 +        Format newFormat = null;
197.1451 +        if (segments[SEG_TYPE].length() != 0) {
197.1452 +            int type = findKeyword(segments[SEG_TYPE], TYPE_KEYWORDS);
197.1453 +            switch (type) {
197.1454 +            case TYPE_NULL:
197.1455 +                // Type "" is allowed. e.g., "{0,}", "{0,,}", and "{0,,#}"
197.1456 +                // are treated as "{0}".
197.1457 +                break;
197.1458 +
197.1459 +            case TYPE_NUMBER:
197.1460 +                switch (findKeyword(segments[SEG_MODIFIER], NUMBER_MODIFIER_KEYWORDS)) {
197.1461 +                case MODIFIER_DEFAULT:
197.1462 +                    newFormat = NumberFormat.getInstance(locale);
197.1463 +                    break;
197.1464 +                case MODIFIER_CURRENCY:
197.1465 +                    newFormat = NumberFormat.getCurrencyInstance(locale);
197.1466 +                    break;
197.1467 +                case MODIFIER_PERCENT:
197.1468 +                    newFormat = NumberFormat.getPercentInstance(locale);
197.1469 +                    break;
197.1470 +                case MODIFIER_INTEGER:
197.1471 +                    newFormat = NumberFormat.getIntegerInstance(locale);
197.1472 +                    break;
197.1473 +                default: // DecimalFormat pattern
197.1474 +                    try {
197.1475 +                        newFormat = new DecimalFormat(segments[SEG_MODIFIER],
197.1476 +                                                      DecimalFormatSymbols.getInstance(locale));
197.1477 +                    } catch (IllegalArgumentException e) {
197.1478 +                        maxOffset = oldMaxOffset;
197.1479 +                        throw e;
197.1480 +                    }
197.1481 +                    break;
197.1482 +                }
197.1483 +                break;
197.1484 +
197.1485 +            case TYPE_DATE:
197.1486 +            case TYPE_TIME:
197.1487 +                int mod = findKeyword(segments[SEG_MODIFIER], DATE_TIME_MODIFIER_KEYWORDS);
197.1488 +                if (mod >= 0 && mod < DATE_TIME_MODIFIER_KEYWORDS.length) {
197.1489 +                    if (type == TYPE_DATE) {
197.1490 +                        newFormat = DateFormat.getDateInstance(DATE_TIME_MODIFIERS[mod],
197.1491 +                                                               locale);
197.1492 +                    } else {
197.1493 +                        newFormat = DateFormat.getTimeInstance(DATE_TIME_MODIFIERS[mod],
197.1494 +                                                               locale);
197.1495 +                    }
197.1496 +                } else {
197.1497 +                    // SimpleDateFormat pattern
197.1498 +                    try {
197.1499 +                        newFormat = new SimpleDateFormat(segments[SEG_MODIFIER], locale);
197.1500 +                    } catch (IllegalArgumentException e) {
197.1501 +                        maxOffset = oldMaxOffset;
197.1502 +                        throw e;
197.1503 +                    }
197.1504 +                }
197.1505 +                break;
197.1506 +
197.1507 +            case TYPE_CHOICE:
197.1508 +                try {
197.1509 +                    // ChoiceFormat pattern
197.1510 +                    newFormat = new ChoiceFormat(segments[SEG_MODIFIER]);
197.1511 +                } catch (Exception e) {
197.1512 +                    maxOffset = oldMaxOffset;
197.1513 +                    throw new IllegalArgumentException("Choice Pattern incorrect: "
197.1514 +                                                       + segments[SEG_MODIFIER], e);
197.1515 +                }
197.1516 +                break;
197.1517 +
197.1518 +            default:
197.1519 +                maxOffset = oldMaxOffset;
197.1520 +                throw new IllegalArgumentException("unknown format type: " +
197.1521 +                                                   segments[SEG_TYPE]);
197.1522 +            }
197.1523 +        }
197.1524 +        formats[offsetNumber] = newFormat;
197.1525 +    }
197.1526 +
197.1527 +    private static final int findKeyword(String s, String[] list) {
197.1528 +        for (int i = 0; i < list.length; ++i) {
197.1529 +            if (s.equals(list[i]))
197.1530 +                return i;
197.1531 +        }
197.1532 +
197.1533 +        // Try trimmed lowercase.
197.1534 +        String ls = s.trim().toLowerCase(Locale.ROOT);
197.1535 +        if (ls != s) {
197.1536 +            for (int i = 0; i < list.length; ++i) {
197.1537 +                if (ls.equals(list[i]))
197.1538 +                    return i;
197.1539 +            }
197.1540 +        }
197.1541 +        return -1;
197.1542 +    }
197.1543 +
197.1544 +    private static final void copyAndFixQuotes(String source, int start, int end,
197.1545 +                                               StringBuilder target) {
197.1546 +        boolean quoted = false;
197.1547 +
197.1548 +        for (int i = start; i < end; ++i) {
197.1549 +            char ch = source.charAt(i);
197.1550 +            if (ch == '{') {
197.1551 +                if (!quoted) {
197.1552 +                    target.append('\'');
197.1553 +                    quoted = true;
197.1554 +                }
197.1555 +                target.append(ch);
197.1556 +            } else if (ch == '\'') {
197.1557 +                target.append("''");
197.1558 +            } else {
197.1559 +                if (quoted) {
197.1560 +                    target.append('\'');
197.1561 +                    quoted = false;
197.1562 +                }
197.1563 +                target.append(ch);
197.1564 +            }
197.1565 +        }
197.1566 +        if (quoted) {
197.1567 +            target.append('\'');
197.1568 +        }
197.1569 +    }
197.1570 +
197.1571 +    /**
197.1572 +     * After reading an object from the input stream, do a simple verification
197.1573 +     * to maintain class invariants.
197.1574 +     * @throws InvalidObjectException if the objects read from the stream is invalid.
197.1575 +     */
197.1576 +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
197.1577 +        in.defaultReadObject();
197.1578 +        boolean isValid = maxOffset >= -1
197.1579 +                && formats.length > maxOffset
197.1580 +                && offsets.length > maxOffset
197.1581 +                && argumentNumbers.length > maxOffset;
197.1582 +        if (isValid) {
197.1583 +            int lastOffset = pattern.length() + 1;
197.1584 +            for (int i = maxOffset; i >= 0; --i) {
197.1585 +                if ((offsets[i] < 0) || (offsets[i] > lastOffset)) {
197.1586 +                    isValid = false;
197.1587 +                    break;
197.1588 +                } else {
197.1589 +                    lastOffset = offsets[i];
197.1590 +                }
197.1591 +            }
197.1592 +        }
197.1593 +        if (!isValid) {
197.1594 +            throw new InvalidObjectException("Could not reconstruct MessageFormat from corrupt stream.");
197.1595 +        }
197.1596 +    }
197.1597 +}
   198.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.2 +++ b/rt/emul/compact/src/main/java/java/text/NumberFormat.java	Wed Apr 30 15:04:10 2014 +0200
   198.3 @@ -0,0 +1,1159 @@
   198.4 +/*
   198.5 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   198.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   198.7 + *
   198.8 + * This code is free software; you can redistribute it and/or modify it
   198.9 + * under the terms of the GNU General Public License version 2 only, as
  198.10 + * published by the Free Software Foundation.  Oracle designates this
  198.11 + * particular file as subject to the "Classpath" exception as provided
  198.12 + * by Oracle in the LICENSE file that accompanied this code.
  198.13 + *
  198.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  198.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  198.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  198.17 + * version 2 for more details (a copy is included in the LICENSE file that
  198.18 + * accompanied this code).
  198.19 + *
  198.20 + * You should have received a copy of the GNU General Public License version
  198.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  198.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  198.23 + *
  198.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  198.25 + * or visit www.oracle.com if you need additional information or have any
  198.26 + * questions.
  198.27 + */
  198.28 +
  198.29 +/*
  198.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  198.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  198.32 + *
  198.33 + *   The original version of this source code and documentation is copyrighted
  198.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  198.35 + * materials are provided under terms of a License Agreement between Taligent
  198.36 + * and Sun. This technology is protected by multiple US and International
  198.37 + * patents. This notice and attribution to Taligent may not be removed.
  198.38 + *   Taligent is a registered trademark of Taligent, Inc.
  198.39 + *
  198.40 + */
  198.41 +
  198.42 +package java.text;
  198.43 +
  198.44 +import java.io.InvalidObjectException;
  198.45 +import java.io.IOException;
  198.46 +import java.io.ObjectInputStream;
  198.47 +import java.io.ObjectOutputStream;
  198.48 +import java.math.BigInteger;
  198.49 +import java.math.RoundingMode;
  198.50 +import java.util.Currency;
  198.51 +import java.util.HashMap;
  198.52 +import java.util.Hashtable;
  198.53 +import java.util.Locale;
  198.54 +import java.util.Map;
  198.55 +import java.util.ResourceBundle;
  198.56 +import java.util.concurrent.atomic.AtomicInteger;
  198.57 +import java.util.concurrent.atomic.AtomicLong;
  198.58 +
  198.59 +/**
  198.60 + * <code>NumberFormat</code> is the abstract base class for all number
  198.61 + * formats. This class provides the interface for formatting and parsing
  198.62 + * numbers. <code>NumberFormat</code> also provides methods for determining
  198.63 + * which locales have number formats, and what their names are.
  198.64 + *
  198.65 + * <p>
  198.66 + * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
  198.67 + * Your code can be completely independent of the locale conventions for
  198.68 + * decimal points, thousands-separators, or even the particular decimal
  198.69 + * digits used, or whether the number format is even decimal.
  198.70 + *
  198.71 + * <p>
  198.72 + * To format a number for the current Locale, use one of the factory
  198.73 + * class methods:
  198.74 + * <blockquote>
  198.75 + * <pre>
  198.76 + *  myString = NumberFormat.getInstance().format(myNumber);
  198.77 + * </pre>
  198.78 + * </blockquote>
  198.79 + * If you are formatting multiple numbers, it is
  198.80 + * more efficient to get the format and use it multiple times so that
  198.81 + * the system doesn't have to fetch the information about the local
  198.82 + * language and country conventions multiple times.
  198.83 + * <blockquote>
  198.84 + * <pre>
  198.85 + * NumberFormat nf = NumberFormat.getInstance();
  198.86 + * for (int i = 0; i < myNumber.length; ++i) {
  198.87 + *     output.println(nf.format(myNumber[i]) + "; ");
  198.88 + * }
  198.89 + * </pre>
  198.90 + * </blockquote>
  198.91 + * To format a number for a different Locale, specify it in the
  198.92 + * call to <code>getInstance</code>.
  198.93 + * <blockquote>
  198.94 + * <pre>
  198.95 + * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
  198.96 + * </pre>
  198.97 + * </blockquote>
  198.98 + * You can also use a <code>NumberFormat</code> to parse numbers:
  198.99 + * <blockquote>
 198.100 + * <pre>
 198.101 + * myNumber = nf.parse(myString);
 198.102 + * </pre>
 198.103 + * </blockquote>
 198.104 + * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
 198.105 + * normal number format. Use <code>getIntegerInstance</code> to get an
 198.106 + * integer number format. Use <code>getCurrencyInstance</code> to get the
 198.107 + * currency number format. And use <code>getPercentInstance</code> to get a
 198.108 + * format for displaying percentages. With this format, a fraction like
 198.109 + * 0.53 is displayed as 53%.
 198.110 + *
 198.111 + * <p>
 198.112 + * You can also control the display of numbers with such methods as
 198.113 + * <code>setMinimumFractionDigits</code>.
 198.114 + * If you want even more control over the format or parsing,
 198.115 + * or want to give your users more control,
 198.116 + * you can try casting the <code>NumberFormat</code> you get from the factory methods
 198.117 + * to a <code>DecimalFormat</code>. This will work for the vast majority
 198.118 + * of locales; just remember to put it in a <code>try</code> block in case you
 198.119 + * encounter an unusual one.
 198.120 + *
 198.121 + * <p>
 198.122 + * NumberFormat and DecimalFormat are designed such that some controls
 198.123 + * work for formatting and others work for parsing.  The following is
 198.124 + * the detailed description for each these control methods,
 198.125 + * <p>
 198.126 + * setParseIntegerOnly : only affects parsing, e.g.
 198.127 + * if true,  "3456.78" -> 3456 (and leaves the parse position just after index 6)
 198.128 + * if false, "3456.78" -> 3456.78 (and leaves the parse position just after index 8)
 198.129 + * This is independent of formatting.  If you want to not show a decimal point
 198.130 + * where there might be no digits after the decimal point, use
 198.131 + * setDecimalSeparatorAlwaysShown.
 198.132 + * <p>
 198.133 + * setDecimalSeparatorAlwaysShown : only affects formatting, and only where
 198.134 + * there might be no digits after the decimal point, such as with a pattern
 198.135 + * like "#,##0.##", e.g.,
 198.136 + * if true,  3456.00 -> "3,456."
 198.137 + * if false, 3456.00 -> "3456"
 198.138 + * This is independent of parsing.  If you want parsing to stop at the decimal
 198.139 + * point, use setParseIntegerOnly.
 198.140 + *
 198.141 + * <p>
 198.142 + * You can also use forms of the <code>parse</code> and <code>format</code>
 198.143 + * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
 198.144 + * allow you to:
 198.145 + * <ul>
 198.146 + * <li> progressively parse through pieces of a string
 198.147 + * <li> align the decimal point and other areas
 198.148 + * </ul>
 198.149 + * For example, you can align numbers in two ways:
 198.150 + * <ol>
 198.151 + * <li> If you are using a monospaced font with spacing for alignment,
 198.152 + *      you can pass the <code>FieldPosition</code> in your format call, with
 198.153 + *      <code>field</code> = <code>INTEGER_FIELD</code>. On output,
 198.154 + *      <code>getEndIndex</code> will be set to the offset between the
 198.155 + *      last character of the integer and the decimal. Add
 198.156 + *      (desiredSpaceCount - getEndIndex) spaces at the front of the string.
 198.157 + *
 198.158 + * <li> If you are using proportional fonts,
 198.159 + *      instead of padding with spaces, measure the width
 198.160 + *      of the string in pixels from the start to <code>getEndIndex</code>.
 198.161 + *      Then move the pen by
 198.162 + *      (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
 198.163 + *      It also works where there is no decimal, but possibly additional
 198.164 + *      characters at the end, e.g., with parentheses in negative
 198.165 + *      numbers: "(12)" for -12.
 198.166 + * </ol>
 198.167 + *
 198.168 + * <h4><a name="synchronization">Synchronization</a></h4>
 198.169 + *
 198.170 + * <p>
 198.171 + * Number formats are generally not synchronized.
 198.172 + * It is recommended to create separate format instances for each thread.
 198.173 + * If multiple threads access a format concurrently, it must be synchronized
 198.174 + * externally.
 198.175 + *
 198.176 + * @see          DecimalFormat
 198.177 + * @see          ChoiceFormat
 198.178 + * @author       Mark Davis
 198.179 + * @author       Helena Shih
 198.180 + */
 198.181 +public abstract class NumberFormat extends Format  {
 198.182 +
 198.183 +    /**
 198.184 +     * Field constant used to construct a FieldPosition object. Signifies that
 198.185 +     * the position of the integer part of a formatted number should be returned.
 198.186 +     * @see java.text.FieldPosition
 198.187 +     */
 198.188 +    public static final int INTEGER_FIELD = 0;
 198.189 +
 198.190 +    /**
 198.191 +     * Field constant used to construct a FieldPosition object. Signifies that
 198.192 +     * the position of the fraction part of a formatted number should be returned.
 198.193 +     * @see java.text.FieldPosition
 198.194 +     */
 198.195 +    public static final int FRACTION_FIELD = 1;
 198.196 +
 198.197 +    /**
 198.198 +     * Sole constructor.  (For invocation by subclass constructors, typically
 198.199 +     * implicit.)
 198.200 +     */
 198.201 +    protected NumberFormat() {
 198.202 +    }
 198.203 +
 198.204 +    /**
 198.205 +     * Formats a number and appends the resulting text to the given string
 198.206 +     * buffer.
 198.207 +     * The number can be of any subclass of {@link java.lang.Number}.
 198.208 +     * <p>
 198.209 +     * This implementation extracts the number's value using
 198.210 +     * {@link java.lang.Number#longValue()} for all integral type values that
 198.211 +     * can be converted to <code>long</code> without loss of information,
 198.212 +     * including <code>BigInteger</code> values with a
 198.213 +     * {@link java.math.BigInteger#bitLength() bit length} of less than 64,
 198.214 +     * and {@link java.lang.Number#doubleValue()} for all other types. It
 198.215 +     * then calls
 198.216 +     * {@link #format(long,java.lang.StringBuffer,java.text.FieldPosition)}
 198.217 +     * or {@link #format(double,java.lang.StringBuffer,java.text.FieldPosition)}.
 198.218 +     * This may result in loss of magnitude information and precision for
 198.219 +     * <code>BigInteger</code> and <code>BigDecimal</code> values.
 198.220 +     * @param number     the number to format
 198.221 +     * @param toAppendTo the <code>StringBuffer</code> to which the formatted
 198.222 +     *                   text is to be appended
 198.223 +     * @param pos        On input: an alignment field, if desired.
 198.224 +     *                   On output: the offsets of the alignment field.
 198.225 +     * @return           the value passed in as <code>toAppendTo</code>
 198.226 +     * @exception        IllegalArgumentException if <code>number</code> is
 198.227 +     *                   null or not an instance of <code>Number</code>.
 198.228 +     * @exception        NullPointerException if <code>toAppendTo</code> or
 198.229 +     *                   <code>pos</code> is null
 198.230 +     * @exception        ArithmeticException if rounding is needed with rounding
 198.231 +     *                   mode being set to RoundingMode.UNNECESSARY
 198.232 +     * @see              java.text.FieldPosition
 198.233 +     */
 198.234 +    public StringBuffer format(Object number,
 198.235 +                               StringBuffer toAppendTo,
 198.236 +                               FieldPosition pos) {
 198.237 +        if (number instanceof Long || number instanceof Integer ||
 198.238 +            number instanceof Short || number instanceof Byte ||
 198.239 +            number instanceof AtomicInteger || number instanceof AtomicLong ||
 198.240 +            (number instanceof BigInteger &&
 198.241 +             ((BigInteger)number).bitLength() < 64)) {
 198.242 +            return format(((Number)number).longValue(), toAppendTo, pos);
 198.243 +        } else if (number instanceof Number) {
 198.244 +            return format(((Number)number).doubleValue(), toAppendTo, pos);
 198.245 +        } else {
 198.246 +            throw new IllegalArgumentException("Cannot format given Object as a Number");
 198.247 +        }
 198.248 +    }
 198.249 +
 198.250 +    /**
 198.251 +     * Parses text from a string to produce a <code>Number</code>.
 198.252 +     * <p>
 198.253 +     * The method attempts to parse text starting at the index given by
 198.254 +     * <code>pos</code>.
 198.255 +     * If parsing succeeds, then the index of <code>pos</code> is updated
 198.256 +     * to the index after the last character used (parsing does not necessarily
 198.257 +     * use all characters up to the end of the string), and the parsed
 198.258 +     * number is returned. The updated <code>pos</code> can be used to
 198.259 +     * indicate the starting point for the next call to this method.
 198.260 +     * If an error occurs, then the index of <code>pos</code> is not
 198.261 +     * changed, the error index of <code>pos</code> is set to the index of
 198.262 +     * the character where the error occurred, and null is returned.
 198.263 +     * <p>
 198.264 +     * See the {@link #parse(String, ParsePosition)} method for more information
 198.265 +     * on number parsing.
 198.266 +     *
 198.267 +     * @param source A <code>String</code>, part of which should be parsed.
 198.268 +     * @param pos A <code>ParsePosition</code> object with index and error
 198.269 +     *            index information as described above.
 198.270 +     * @return A <code>Number</code> parsed from the string. In case of
 198.271 +     *         error, returns null.
 198.272 +     * @exception NullPointerException if <code>pos</code> is null.
 198.273 +     */
 198.274 +    public final Object parseObject(String source, ParsePosition pos) {
 198.275 +        return parse(source, pos);
 198.276 +    }
 198.277 +
 198.278 +   /**
 198.279 +     * Specialization of format.
 198.280 +     * @exception        ArithmeticException if rounding is needed with rounding
 198.281 +     *                   mode being set to RoundingMode.UNNECESSARY
 198.282 +     * @see java.text.Format#format
 198.283 +     */
 198.284 +    public final String format(double number) {
 198.285 +        return format(number, new StringBuffer(),
 198.286 +                      DontCareFieldPosition.INSTANCE).toString();
 198.287 +    }
 198.288 +
 198.289 +   /**
 198.290 +     * Specialization of format.
 198.291 +     * @exception        ArithmeticException if rounding is needed with rounding
 198.292 +     *                   mode being set to RoundingMode.UNNECESSARY
 198.293 +     * @see java.text.Format#format
 198.294 +     */
 198.295 +    public final String format(long number) {
 198.296 +        return format(number, new StringBuffer(),
 198.297 +                      DontCareFieldPosition.INSTANCE).toString();
 198.298 +    }
 198.299 +
 198.300 +   /**
 198.301 +     * Specialization of format.
 198.302 +     * @exception        ArithmeticException if rounding is needed with rounding
 198.303 +     *                   mode being set to RoundingMode.UNNECESSARY
 198.304 +     * @see java.text.Format#format
 198.305 +     */
 198.306 +    public abstract StringBuffer format(double number,
 198.307 +                                        StringBuffer toAppendTo,
 198.308 +                                        FieldPosition pos);
 198.309 +
 198.310 +   /**
 198.311 +     * Specialization of format.
 198.312 +     * @exception        ArithmeticException if rounding is needed with rounding
 198.313 +     *                   mode being set to RoundingMode.UNNECESSARY
 198.314 +     * @see java.text.Format#format
 198.315 +     */
 198.316 +    public abstract StringBuffer format(long number,
 198.317 +                                        StringBuffer toAppendTo,
 198.318 +                                        FieldPosition pos);
 198.319 +
 198.320 +   /**
 198.321 +     * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
 198.322 +     * Long.MAX_VALUE] and with no decimals), otherwise a Double.
 198.323 +     * If IntegerOnly is set, will stop at a decimal
 198.324 +     * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
 198.325 +     * after the 1).
 198.326 +     * Does not throw an exception; if no object can be parsed, index is
 198.327 +     * unchanged!
 198.328 +     * @see java.text.NumberFormat#isParseIntegerOnly
 198.329 +     * @see java.text.Format#parseObject
 198.330 +     */
 198.331 +    public abstract Number parse(String source, ParsePosition parsePosition);
 198.332 +
 198.333 +    /**
 198.334 +     * Parses text from the beginning of the given string to produce a number.
 198.335 +     * The method may not use the entire text of the given string.
 198.336 +     * <p>
 198.337 +     * See the {@link #parse(String, ParsePosition)} method for more information
 198.338 +     * on number parsing.
 198.339 +     *
 198.340 +     * @param source A <code>String</code> whose beginning should be parsed.
 198.341 +     * @return A <code>Number</code> parsed from the string.
 198.342 +     * @exception ParseException if the beginning of the specified string
 198.343 +     *            cannot be parsed.
 198.344 +     */
 198.345 +    public Number parse(String source) throws ParseException {
 198.346 +        ParsePosition parsePosition = new ParsePosition(0);
 198.347 +        Number result = parse(source, parsePosition);
 198.348 +        if (parsePosition.index == 0) {
 198.349 +            throw new ParseException("Unparseable number: \"" + source + "\"",
 198.350 +                                     parsePosition.errorIndex);
 198.351 +        }
 198.352 +        return result;
 198.353 +    }
 198.354 +
 198.355 +    /**
 198.356 +     * Returns true if this format will parse numbers as integers only.
 198.357 +     * For example in the English locale, with ParseIntegerOnly true, the
 198.358 +     * string "1234." would be parsed as the integer value 1234 and parsing
 198.359 +     * would stop at the "." character.  Of course, the exact format accepted
 198.360 +     * by the parse operation is locale dependant and determined by sub-classes
 198.361 +     * of NumberFormat.
 198.362 +     */
 198.363 +    public boolean isParseIntegerOnly() {
 198.364 +        return parseIntegerOnly;
 198.365 +    }
 198.366 +
 198.367 +    /**
 198.368 +     * Sets whether or not numbers should be parsed as integers only.
 198.369 +     * @see #isParseIntegerOnly
 198.370 +     */
 198.371 +    public void setParseIntegerOnly(boolean value) {
 198.372 +        parseIntegerOnly = value;
 198.373 +    }
 198.374 +
 198.375 +    //============== Locale Stuff =====================
 198.376 +
 198.377 +    /**
 198.378 +     * Returns a general-purpose number format for the current default locale.
 198.379 +     * This is the same as calling
 198.380 +     * {@link #getNumberInstance() getNumberInstance()}.
 198.381 +     */
 198.382 +    public final static NumberFormat getInstance() {
 198.383 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
 198.384 +    }
 198.385 +
 198.386 +    /**
 198.387 +     * Returns a general-purpose number format for the specified locale.
 198.388 +     * This is the same as calling
 198.389 +     * {@link #getNumberInstance(java.util.Locale) getNumberInstance(inLocale)}.
 198.390 +     */
 198.391 +    public static NumberFormat getInstance(Locale inLocale) {
 198.392 +        return getInstance(inLocale, NUMBERSTYLE);
 198.393 +    }
 198.394 +
 198.395 +    /**     * Returns a general-purpose number format for the current default locale.
 198.396 +     */
 198.397 +    public final static NumberFormat getNumberInstance() {
 198.398 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
 198.399 +    }
 198.400 +
 198.401 +    /**
 198.402 +     * Returns a general-purpose number format for the specified locale.
 198.403 +     */
 198.404 +    public static NumberFormat getNumberInstance(Locale inLocale) {
 198.405 +        return getInstance(inLocale, NUMBERSTYLE);
 198.406 +    }
 198.407 +
 198.408 +    /**
 198.409 +     * Returns an integer number format for the current default locale. The
 198.410 +     * returned number format is configured to round floating point numbers
 198.411 +     * to the nearest integer using half-even rounding (see {@link
 198.412 +     * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
 198.413 +     * and to parse only the integer part of an input string (see {@link
 198.414 +     * #isParseIntegerOnly isParseIntegerOnly}).
 198.415 +     *
 198.416 +     * @see #getRoundingMode()
 198.417 +     * @return a number format for integer values
 198.418 +     * @since 1.4
 198.419 +     */
 198.420 +    public final static NumberFormat getIntegerInstance() {
 198.421 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
 198.422 +    }
 198.423 +
 198.424 +    /**
 198.425 +     * Returns an integer number format for the specified locale. The
 198.426 +     * returned number format is configured to round floating point numbers
 198.427 +     * to the nearest integer using half-even rounding (see {@link
 198.428 +     * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
 198.429 +     * and to parse only the integer part of an input string (see {@link
 198.430 +     * #isParseIntegerOnly isParseIntegerOnly}).
 198.431 +     *
 198.432 +     * @see #getRoundingMode()
 198.433 +     * @return a number format for integer values
 198.434 +     * @since 1.4
 198.435 +     */
 198.436 +    public static NumberFormat getIntegerInstance(Locale inLocale) {
 198.437 +        return getInstance(inLocale, INTEGERSTYLE);
 198.438 +    }
 198.439 +
 198.440 +    /**
 198.441 +     * Returns a currency format for the current default locale.
 198.442 +     */
 198.443 +    public final static NumberFormat getCurrencyInstance() {
 198.444 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
 198.445 +    }
 198.446 +
 198.447 +    /**
 198.448 +     * Returns a currency format for the specified locale.
 198.449 +     */
 198.450 +    public static NumberFormat getCurrencyInstance(Locale inLocale) {
 198.451 +        return getInstance(inLocale, CURRENCYSTYLE);
 198.452 +    }
 198.453 +
 198.454 +    /**
 198.455 +     * Returns a percentage format for the current default locale.
 198.456 +     */
 198.457 +    public final static NumberFormat getPercentInstance() {
 198.458 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
 198.459 +    }
 198.460 +
 198.461 +    /**
 198.462 +     * Returns a percentage format for the specified locale.
 198.463 +     */
 198.464 +    public static NumberFormat getPercentInstance(Locale inLocale) {
 198.465 +        return getInstance(inLocale, PERCENTSTYLE);
 198.466 +    }
 198.467 +
 198.468 +    /**
 198.469 +     * Returns a scientific format for the current default locale.
 198.470 +     */
 198.471 +    /*public*/ final static NumberFormat getScientificInstance() {
 198.472 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), SCIENTIFICSTYLE);
 198.473 +    }
 198.474 +
 198.475 +    /**
 198.476 +     * Returns a scientific format for the specified locale.
 198.477 +     */
 198.478 +    /*public*/ static NumberFormat getScientificInstance(Locale inLocale) {
 198.479 +        return getInstance(inLocale, SCIENTIFICSTYLE);
 198.480 +    }
 198.481 +
 198.482 +    /**
 198.483 +     * Returns an array of all locales for which the
 198.484 +     * <code>get*Instance</code> methods of this class can return
 198.485 +     * localized instances.
 198.486 +     * The returned array represents the union of locales supported by the Java
 198.487 +     * runtime and by installed
 198.488 +     * {@link java.text.spi.NumberFormatProvider NumberFormatProvider} implementations.
 198.489 +     * It must contain at least a <code>Locale</code> instance equal to
 198.490 +     * {@link java.util.Locale#US Locale.US}.
 198.491 +     *
 198.492 +     * @return An array of locales for which localized
 198.493 +     *         <code>NumberFormat</code> instances are available.
 198.494 +     */
 198.495 +    public static Locale[] getAvailableLocales() {
 198.496 +        return new Locale[] { Locale.US };
 198.497 +//        LocaleServiceProviderPool pool =
 198.498 +//            LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
 198.499 +//        return pool.getAvailableLocales();
 198.500 +    }
 198.501 +
 198.502 +    /**
 198.503 +     * Overrides hashCode
 198.504 +     */
 198.505 +    public int hashCode() {
 198.506 +        return maximumIntegerDigits * 37 + maxFractionDigits;
 198.507 +        // just enough fields for a reasonable distribution
 198.508 +    }
 198.509 +
 198.510 +    /**
 198.511 +     * Overrides equals
 198.512 +     */
 198.513 +    public boolean equals(Object obj) {
 198.514 +        if (obj == null) {
 198.515 +            return false;
 198.516 +        }
 198.517 +        if (this == obj) {
 198.518 +            return true;
 198.519 +        }
 198.520 +        if (getClass() != obj.getClass()) {
 198.521 +            return false;
 198.522 +        }
 198.523 +        NumberFormat other = (NumberFormat) obj;
 198.524 +        return (maximumIntegerDigits == other.maximumIntegerDigits
 198.525 +            && minimumIntegerDigits == other.minimumIntegerDigits
 198.526 +            && maximumFractionDigits == other.maximumFractionDigits
 198.527 +            && minimumFractionDigits == other.minimumFractionDigits
 198.528 +            && groupingUsed == other.groupingUsed
 198.529 +            && parseIntegerOnly == other.parseIntegerOnly);
 198.530 +    }
 198.531 +
 198.532 +    /**
 198.533 +     * Overrides Cloneable
 198.534 +     */
 198.535 +    public Object clone() {
 198.536 +        NumberFormat other = (NumberFormat) super.clone();
 198.537 +        return other;
 198.538 +    }
 198.539 +
 198.540 +    /**
 198.541 +     * Returns true if grouping is used in this format. For example, in the
 198.542 +     * English locale, with grouping on, the number 1234567 might be formatted
 198.543 +     * as "1,234,567". The grouping separator as well as the size of each group
 198.544 +     * is locale dependant and is determined by sub-classes of NumberFormat.
 198.545 +     * @see #setGroupingUsed
 198.546 +     */
 198.547 +    public boolean isGroupingUsed() {
 198.548 +        return groupingUsed;
 198.549 +    }
 198.550 +
 198.551 +    /**
 198.552 +     * Set whether or not grouping will be used in this format.
 198.553 +     * @see #isGroupingUsed
 198.554 +     */
 198.555 +    public void setGroupingUsed(boolean newValue) {
 198.556 +        groupingUsed = newValue;
 198.557 +    }
 198.558 +
 198.559 +    /**
 198.560 +     * Returns the maximum number of digits allowed in the integer portion of a
 198.561 +     * number.
 198.562 +     * @see #setMaximumIntegerDigits
 198.563 +     */
 198.564 +    public int getMaximumIntegerDigits() {
 198.565 +        return maximumIntegerDigits;
 198.566 +    }
 198.567 +
 198.568 +    /**
 198.569 +     * Sets the maximum number of digits allowed in the integer portion of a
 198.570 +     * number. maximumIntegerDigits must be >= minimumIntegerDigits.  If the
 198.571 +     * new value for maximumIntegerDigits is less than the current value
 198.572 +     * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
 198.573 +     * the new value.
 198.574 +     * @param newValue the maximum number of integer digits to be shown; if
 198.575 +     * less than zero, then zero is used. The concrete subclass may enforce an
 198.576 +     * upper limit to this value appropriate to the numeric type being formatted.
 198.577 +     * @see #getMaximumIntegerDigits
 198.578 +     */
 198.579 +    public void setMaximumIntegerDigits(int newValue) {
 198.580 +        maximumIntegerDigits = Math.max(0,newValue);
 198.581 +        if (minimumIntegerDigits > maximumIntegerDigits) {
 198.582 +            minimumIntegerDigits = maximumIntegerDigits;
 198.583 +        }
 198.584 +    }
 198.585 +
 198.586 +    /**
 198.587 +     * Returns the minimum number of digits allowed in the integer portion of a
 198.588 +     * number.
 198.589 +     * @see #setMinimumIntegerDigits
 198.590 +     */
 198.591 +    public int getMinimumIntegerDigits() {
 198.592 +        return minimumIntegerDigits;
 198.593 +    }
 198.594 +
 198.595 +    /**
 198.596 +     * Sets the minimum number of digits allowed in the integer portion of a
 198.597 +     * number. minimumIntegerDigits must be <= maximumIntegerDigits.  If the
 198.598 +     * new value for minimumIntegerDigits exceeds the current value
 198.599 +     * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
 198.600 +     * the new value
 198.601 +     * @param newValue the minimum number of integer digits to be shown; if
 198.602 +     * less than zero, then zero is used. The concrete subclass may enforce an
 198.603 +     * upper limit to this value appropriate to the numeric type being formatted.
 198.604 +     * @see #getMinimumIntegerDigits
 198.605 +     */
 198.606 +    public void setMinimumIntegerDigits(int newValue) {
 198.607 +        minimumIntegerDigits = Math.max(0,newValue);
 198.608 +        if (minimumIntegerDigits > maximumIntegerDigits) {
 198.609 +            maximumIntegerDigits = minimumIntegerDigits;
 198.610 +        }
 198.611 +    }
 198.612 +
 198.613 +    /**
 198.614 +     * Returns the maximum number of digits allowed in the fraction portion of a
 198.615 +     * number.
 198.616 +     * @see #setMaximumFractionDigits
 198.617 +     */
 198.618 +    public int getMaximumFractionDigits() {
 198.619 +        return maximumFractionDigits;
 198.620 +    }
 198.621 +
 198.622 +    /**
 198.623 +     * Sets the maximum number of digits allowed in the fraction portion of a
 198.624 +     * number. maximumFractionDigits must be >= minimumFractionDigits.  If the
 198.625 +     * new value for maximumFractionDigits is less than the current value
 198.626 +     * of minimumFractionDigits, then minimumFractionDigits will also be set to
 198.627 +     * the new value.
 198.628 +     * @param newValue the maximum number of fraction digits to be shown; if
 198.629 +     * less than zero, then zero is used. The concrete subclass may enforce an
 198.630 +     * upper limit to this value appropriate to the numeric type being formatted.
 198.631 +     * @see #getMaximumFractionDigits
 198.632 +     */
 198.633 +    public void setMaximumFractionDigits(int newValue) {
 198.634 +        maximumFractionDigits = Math.max(0,newValue);
 198.635 +        if (maximumFractionDigits < minimumFractionDigits) {
 198.636 +            minimumFractionDigits = maximumFractionDigits;
 198.637 +        }
 198.638 +    }
 198.639 +
 198.640 +    /**
 198.641 +     * Returns the minimum number of digits allowed in the fraction portion of a
 198.642 +     * number.
 198.643 +     * @see #setMinimumFractionDigits
 198.644 +     */
 198.645 +    public int getMinimumFractionDigits() {
 198.646 +        return minimumFractionDigits;
 198.647 +    }
 198.648 +
 198.649 +    /**
 198.650 +     * Sets the minimum number of digits allowed in the fraction portion of a
 198.651 +     * number. minimumFractionDigits must be <= maximumFractionDigits.  If the
 198.652 +     * new value for minimumFractionDigits exceeds the current value
 198.653 +     * of maximumFractionDigits, then maximumIntegerDigits will also be set to
 198.654 +     * the new value
 198.655 +     * @param newValue the minimum number of fraction digits to be shown; if
 198.656 +     * less than zero, then zero is used. The concrete subclass may enforce an
 198.657 +     * upper limit to this value appropriate to the numeric type being formatted.
 198.658 +     * @see #getMinimumFractionDigits
 198.659 +     */
 198.660 +    public void setMinimumFractionDigits(int newValue) {
 198.661 +        minimumFractionDigits = Math.max(0,newValue);
 198.662 +        if (maximumFractionDigits < minimumFractionDigits) {
 198.663 +            maximumFractionDigits = minimumFractionDigits;
 198.664 +        }
 198.665 +    }
 198.666 +
 198.667 +    /**
 198.668 +     * Gets the currency used by this number format when formatting
 198.669 +     * currency values. The initial value is derived in a locale dependent
 198.670 +     * way. The returned value may be null if no valid
 198.671 +     * currency could be determined and no currency has been set using
 198.672 +     * {@link #setCurrency(java.util.Currency) setCurrency}.
 198.673 +     * <p>
 198.674 +     * The default implementation throws
 198.675 +     * <code>UnsupportedOperationException</code>.
 198.676 +     *
 198.677 +     * @return the currency used by this number format, or <code>null</code>
 198.678 +     * @exception UnsupportedOperationException if the number format class
 198.679 +     * doesn't implement currency formatting
 198.680 +     * @since 1.4
 198.681 +     */
 198.682 +    public Currency getCurrency() {
 198.683 +        throw new UnsupportedOperationException();
 198.684 +    }
 198.685 +
 198.686 +    /**
 198.687 +     * Sets the currency used by this number format when formatting
 198.688 +     * currency values. This does not update the minimum or maximum
 198.689 +     * number of fraction digits used by the number format.
 198.690 +     * <p>
 198.691 +     * The default implementation throws
 198.692 +     * <code>UnsupportedOperationException</code>.
 198.693 +     *
 198.694 +     * @param currency the new currency to be used by this number format
 198.695 +     * @exception UnsupportedOperationException if the number format class
 198.696 +     * doesn't implement currency formatting
 198.697 +     * @exception NullPointerException if <code>currency</code> is null
 198.698 +     * @since 1.4
 198.699 +     */
 198.700 +    public void setCurrency(Currency currency) {
 198.701 +        throw new UnsupportedOperationException();
 198.702 +    }
 198.703 +
 198.704 +    /**
 198.705 +     * Gets the {@link java.math.RoundingMode} used in this NumberFormat.
 198.706 +     * The default implementation of this method in NumberFormat
 198.707 +     * always throws {@link java.lang.UnsupportedOperationException}.
 198.708 +     * Subclasses which handle different rounding modes should override
 198.709 +     * this method.
 198.710 +     *
 198.711 +     * @exception UnsupportedOperationException The default implementation
 198.712 +     *     always throws this exception
 198.713 +     * @return The <code>RoundingMode</code> used for this NumberFormat.
 198.714 +     * @see #setRoundingMode(RoundingMode)
 198.715 +     * @since 1.6
 198.716 +     */
 198.717 +    public RoundingMode getRoundingMode() {
 198.718 +        throw new UnsupportedOperationException();
 198.719 +    }
 198.720 +
 198.721 +    /**
 198.722 +     * Sets the {@link java.math.RoundingMode} used in this NumberFormat.
 198.723 +     * The default implementation of this method in NumberFormat always
 198.724 +     * throws {@link java.lang.UnsupportedOperationException}.
 198.725 +     * Subclasses which handle different rounding modes should override
 198.726 +     * this method.
 198.727 +     *
 198.728 +     * @exception UnsupportedOperationException The default implementation
 198.729 +     *     always throws this exception
 198.730 +     * @exception NullPointerException if <code>roundingMode</code> is null
 198.731 +     * @param roundingMode The <code>RoundingMode</code> to be used
 198.732 +     * @see #getRoundingMode()
 198.733 +     * @since 1.6
 198.734 +     */
 198.735 +    public void setRoundingMode(RoundingMode roundingMode) {
 198.736 +        throw new UnsupportedOperationException();
 198.737 +    }
 198.738 +
 198.739 +    // =======================privates===============================
 198.740 +
 198.741 +    private static NumberFormat getInstance(Locale desiredLocale,
 198.742 +                                           int choice) {
 198.743 +        // Check whether a provider can provide an implementation that's closer
 198.744 +        // to the requested locale than what the Java runtime itself can provide.
 198.745 +//        LocaleServiceProviderPool pool =
 198.746 +//            LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
 198.747 +//        if (pool.hasProviders()) {
 198.748 +//            NumberFormat providersInstance = pool.getLocalizedObject(
 198.749 +//                                    NumberFormatGetter.INSTANCE,
 198.750 +//                                    desiredLocale,
 198.751 +//                                    choice);
 198.752 +//            if (providersInstance != null) {
 198.753 +//                return providersInstance;
 198.754 +//            }
 198.755 +//        }
 198.756 +
 198.757 +        /* try the cache first */
 198.758 +        String[] numberPatterns = (String[])cachedLocaleData.get(desiredLocale);
 198.759 +//        if (numberPatterns == null) { /* cache miss */
 198.760 +//            ResourceBundle resource = LocaleData.getNumberFormatData(desiredLocale);
 198.761 +//            numberPatterns = resource.getStringArray("NumberPatterns");
 198.762 +//            /* update cache */
 198.763 +//            cachedLocaleData.put(desiredLocale, numberPatterns);
 198.764 +//        }
 198.765 +
 198.766 +        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
 198.767 +        int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
 198.768 +        DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
 198.769 +
 198.770 +        if (choice == INTEGERSTYLE) {
 198.771 +            format.setMaximumFractionDigits(0);
 198.772 +            format.setDecimalSeparatorAlwaysShown(false);
 198.773 +            format.setParseIntegerOnly(true);
 198.774 +        } else if (choice == CURRENCYSTYLE) {
 198.775 +            format.adjustForCurrencyDefaultFractionDigits();
 198.776 +        }
 198.777 +
 198.778 +        return format;
 198.779 +    }
 198.780 +
 198.781 +    /**
 198.782 +     * First, read in the default serializable data.
 198.783 +     *
 198.784 +     * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
 198.785 +     * the stream was written by JDK 1.1,
 198.786 +     * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
 198.787 +     * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
 198.788 +     * since the <code>int</code> fields were not present in JDK 1.1.
 198.789 +     * Finally, set serialVersionOnStream back to the maximum allowed value so that
 198.790 +     * default serialization will work properly if this object is streamed out again.
 198.791 +     *
 198.792 +     * <p>If <code>minimumIntegerDigits</code> is greater than
 198.793 +     * <code>maximumIntegerDigits</code> or <code>minimumFractionDigits</code>
 198.794 +     * is greater than <code>maximumFractionDigits</code>, then the stream data
 198.795 +     * is invalid and this method throws an <code>InvalidObjectException</code>.
 198.796 +     * In addition, if any of these values is negative, then this method throws
 198.797 +     * an <code>InvalidObjectException</code>.
 198.798 +     *
 198.799 +     * @since 1.2
 198.800 +     */
 198.801 +    private void readObject(ObjectInputStream stream)
 198.802 +         throws IOException, ClassNotFoundException
 198.803 +    {
 198.804 +        stream.defaultReadObject();
 198.805 +        if (serialVersionOnStream < 1) {
 198.806 +            // Didn't have additional int fields, reassign to use them.
 198.807 +            maximumIntegerDigits = maxIntegerDigits;
 198.808 +            minimumIntegerDigits = minIntegerDigits;
 198.809 +            maximumFractionDigits = maxFractionDigits;
 198.810 +            minimumFractionDigits = minFractionDigits;
 198.811 +        }
 198.812 +        if (minimumIntegerDigits > maximumIntegerDigits ||
 198.813 +            minimumFractionDigits > maximumFractionDigits ||
 198.814 +            minimumIntegerDigits < 0 || minimumFractionDigits < 0) {
 198.815 +            throw new InvalidObjectException("Digit count range invalid");
 198.816 +        }
 198.817 +        serialVersionOnStream = currentSerialVersion;
 198.818 +    }
 198.819 +
 198.820 +    /**
 198.821 +     * Write out the default serializable data, after first setting
 198.822 +     * the <code>byte</code> fields such as <code>maxIntegerDigits</code> to be
 198.823 +     * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
 198.824 +     * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
 198.825 +     * with the JDK 1.1 version of the stream format.
 198.826 +     *
 198.827 +     * @since 1.2
 198.828 +     */
 198.829 +    private void writeObject(ObjectOutputStream stream)
 198.830 +         throws IOException
 198.831 +    {
 198.832 +        maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ?
 198.833 +                           Byte.MAX_VALUE : (byte)maximumIntegerDigits;
 198.834 +        minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
 198.835 +                           Byte.MAX_VALUE : (byte)minimumIntegerDigits;
 198.836 +        maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
 198.837 +                            Byte.MAX_VALUE : (byte)maximumFractionDigits;
 198.838 +        minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
 198.839 +                            Byte.MAX_VALUE : (byte)minimumFractionDigits;
 198.840 +        stream.defaultWriteObject();
 198.841 +    }
 198.842 +
 198.843 +    /**
 198.844 +     * Cache to hold the NumberPatterns of a Locale.
 198.845 +     */
 198.846 +    private static final Hashtable cachedLocaleData = new Hashtable(3);
 198.847 +
 198.848 +    // Constants used by factory methods to specify a style of format.
 198.849 +    private static final int NUMBERSTYLE = 0;
 198.850 +    private static final int CURRENCYSTYLE = 1;
 198.851 +    private static final int PERCENTSTYLE = 2;
 198.852 +    private static final int SCIENTIFICSTYLE = 3;
 198.853 +    private static final int INTEGERSTYLE = 4;
 198.854 +
 198.855 +    /**
 198.856 +     * True if the grouping (i.e. thousands) separator is used when
 198.857 +     * formatting and parsing numbers.
 198.858 +     *
 198.859 +     * @serial
 198.860 +     * @see #isGroupingUsed
 198.861 +     */
 198.862 +    private boolean groupingUsed = true;
 198.863 +
 198.864 +    /**
 198.865 +     * The maximum number of digits allowed in the integer portion of a
 198.866 +     * number.  <code>maxIntegerDigits</code> must be greater than or equal to
 198.867 +     * <code>minIntegerDigits</code>.
 198.868 +     * <p>
 198.869 +     * <strong>Note:</strong> This field exists only for serialization
 198.870 +     * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
 198.871 +     * <code>int</code> field <code>maximumIntegerDigits</code> is used instead.
 198.872 +     * When writing to a stream, <code>maxIntegerDigits</code> is set to
 198.873 +     * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
 198.874 +     * whichever is smaller.  When reading from a stream, this field is used
 198.875 +     * only if <code>serialVersionOnStream</code> is less than 1.
 198.876 +     *
 198.877 +     * @serial
 198.878 +     * @see #getMaximumIntegerDigits
 198.879 +     */
 198.880 +    private byte    maxIntegerDigits = 40;
 198.881 +
 198.882 +    /**
 198.883 +     * The minimum number of digits allowed in the integer portion of a
 198.884 +     * number.  <code>minimumIntegerDigits</code> must be less than or equal to
 198.885 +     * <code>maximumIntegerDigits</code>.
 198.886 +     * <p>
 198.887 +     * <strong>Note:</strong> This field exists only for serialization
 198.888 +     * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
 198.889 +     * <code>int</code> field <code>minimumIntegerDigits</code> is used instead.
 198.890 +     * When writing to a stream, <code>minIntegerDigits</code> is set to
 198.891 +     * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
 198.892 +     * whichever is smaller.  When reading from a stream, this field is used
 198.893 +     * only if <code>serialVersionOnStream</code> is less than 1.
 198.894 +     *
 198.895 +     * @serial
 198.896 +     * @see #getMinimumIntegerDigits
 198.897 +     */
 198.898 +    private byte    minIntegerDigits = 1;
 198.899 +
 198.900 +    /**
 198.901 +     * The maximum number of digits allowed in the fractional portion of a
 198.902 +     * number.  <code>maximumFractionDigits</code> must be greater than or equal to
 198.903 +     * <code>minimumFractionDigits</code>.
 198.904 +     * <p>
 198.905 +     * <strong>Note:</strong> This field exists only for serialization
 198.906 +     * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
 198.907 +     * <code>int</code> field <code>maximumFractionDigits</code> is used instead.
 198.908 +     * When writing to a stream, <code>maxFractionDigits</code> is set to
 198.909 +     * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
 198.910 +     * whichever is smaller.  When reading from a stream, this field is used
 198.911 +     * only if <code>serialVersionOnStream</code> is less than 1.
 198.912 +     *
 198.913 +     * @serial
 198.914 +     * @see #getMaximumFractionDigits
 198.915 +     */
 198.916 +    private byte    maxFractionDigits = 3;    // invariant, >= minFractionDigits
 198.917 +
 198.918 +    /**
 198.919 +     * The minimum number of digits allowed in the fractional portion of a
 198.920 +     * number.  <code>minimumFractionDigits</code> must be less than or equal to
 198.921 +     * <code>maximumFractionDigits</code>.
 198.922 +     * <p>
 198.923 +     * <strong>Note:</strong> This field exists only for serialization
 198.924 +     * compatibility with JDK 1.1.  In Java platform 2 v1.2 and higher, the new
 198.925 +     * <code>int</code> field <code>minimumFractionDigits</code> is used instead.
 198.926 +     * When writing to a stream, <code>minFractionDigits</code> is set to
 198.927 +     * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
 198.928 +     * whichever is smaller.  When reading from a stream, this field is used
 198.929 +     * only if <code>serialVersionOnStream</code> is less than 1.
 198.930 +     *
 198.931 +     * @serial
 198.932 +     * @see #getMinimumFractionDigits
 198.933 +     */
 198.934 +    private byte    minFractionDigits = 0;
 198.935 +
 198.936 +    /**
 198.937 +     * True if this format will parse numbers as integers only.
 198.938 +     *
 198.939 +     * @serial
 198.940 +     * @see #isParseIntegerOnly
 198.941 +     */
 198.942 +    private boolean parseIntegerOnly = false;
 198.943 +
 198.944 +    // new fields for 1.2.  byte is too small for integer digits.
 198.945 +
 198.946 +    /**
 198.947 +     * The maximum number of digits allowed in the integer portion of a
 198.948 +     * number.  <code>maximumIntegerDigits</code> must be greater than or equal to
 198.949 +     * <code>minimumIntegerDigits</code>.
 198.950 +     *
 198.951 +     * @serial
 198.952 +     * @since 1.2
 198.953 +     * @see #getMaximumIntegerDigits
 198.954 +     */
 198.955 +    private int    maximumIntegerDigits = 40;
 198.956 +
 198.957 +    /**
 198.958 +     * The minimum number of digits allowed in the integer portion of a
 198.959 +     * number.  <code>minimumIntegerDigits</code> must be less than or equal to
 198.960 +     * <code>maximumIntegerDigits</code>.
 198.961 +     *
 198.962 +     * @serial
 198.963 +     * @since 1.2
 198.964 +     * @see #getMinimumIntegerDigits
 198.965 +     */
 198.966 +    private int    minimumIntegerDigits = 1;
 198.967 +
 198.968 +    /**
 198.969 +     * The maximum number of digits allowed in the fractional portion of a
 198.970 +     * number.  <code>maximumFractionDigits</code> must be greater than or equal to
 198.971 +     * <code>minimumFractionDigits</code>.
 198.972 +     *
 198.973 +     * @serial
 198.974 +     * @since 1.2
 198.975 +     * @see #getMaximumFractionDigits
 198.976 +     */
 198.977 +    private int    maximumFractionDigits = 3;    // invariant, >= minFractionDigits
 198.978 +
 198.979 +    /**
 198.980 +     * The minimum number of digits allowed in the fractional portion of a
 198.981 +     * number.  <code>minimumFractionDigits</code> must be less than or equal to
 198.982 +     * <code>maximumFractionDigits</code>.
 198.983 +     *
 198.984 +     * @serial
 198.985 +     * @since 1.2
 198.986 +     * @see #getMinimumFractionDigits
 198.987 +     */
 198.988 +    private int    minimumFractionDigits = 0;
 198.989 +
 198.990 +    static final int currentSerialVersion = 1;
 198.991 +
 198.992 +    /**
 198.993 +     * Describes the version of <code>NumberFormat</code> present on the stream.
 198.994 +     * Possible values are:
 198.995 +     * <ul>
 198.996 +     * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format.
 198.997 +     *     In this version, the <code>int</code> fields such as
 198.998 +     *     <code>maximumIntegerDigits</code> were not present, and the <code>byte</code>
 198.999 +     *     fields such as <code>maxIntegerDigits</code> are used instead.
198.1000 +     *
198.1001 +     * <li><b>1</b>: the 1.2 version of the stream format.  The values of the
198.1002 +     *     <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored,
198.1003 +     *     and the <code>int</code> fields such as <code>maximumIntegerDigits</code>
198.1004 +     *     are used instead.
198.1005 +     * </ul>
198.1006 +     * When streaming out a <code>NumberFormat</code>, the most recent format
198.1007 +     * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
198.1008 +     * is always written.
198.1009 +     *
198.1010 +     * @serial
198.1011 +     * @since 1.2
198.1012 +     */
198.1013 +    private int serialVersionOnStream = currentSerialVersion;
198.1014 +
198.1015 +    // Removed "implements Cloneable" clause.  Needs to update serialization
198.1016 +    // ID for backward compatibility.
198.1017 +    static final long serialVersionUID = -2308460125733713944L;
198.1018 +
198.1019 +
198.1020 +    //
198.1021 +    // class for AttributedCharacterIterator attributes
198.1022 +    //
198.1023 +    /**
198.1024 +     * Defines constants that are used as attribute keys in the
198.1025 +     * <code>AttributedCharacterIterator</code> returned
198.1026 +     * from <code>NumberFormat.formatToCharacterIterator</code> and as
198.1027 +     * field identifiers in <code>FieldPosition</code>.
198.1028 +     *
198.1029 +     * @since 1.4
198.1030 +     */
198.1031 +    public static class Field extends Format.Field {
198.1032 +
198.1033 +        // Proclaim serial compatibility with 1.4 FCS
198.1034 +        private static final long serialVersionUID = 7494728892700160890L;
198.1035 +
198.1036 +        // table of all instances in this class, used by readResolve
198.1037 +        private static final Map instanceMap = new HashMap(11);
198.1038 +
198.1039 +        /**
198.1040 +         * Creates a Field instance with the specified
198.1041 +         * name.
198.1042 +         *
198.1043 +         * @param name Name of the attribute
198.1044 +         */
198.1045 +        protected Field(String name) {
198.1046 +            super(name);
198.1047 +            if (this.getClass() == NumberFormat.Field.class) {
198.1048 +                instanceMap.put(name, this);
198.1049 +            }
198.1050 +        }
198.1051 +
198.1052 +        /**
198.1053 +         * Resolves instances being deserialized to the predefined constants.
198.1054 +         *
198.1055 +         * @throws InvalidObjectException if the constant could not be resolved.
198.1056 +         * @return resolved NumberFormat.Field constant
198.1057 +         */
198.1058 +        protected Object readResolve() throws InvalidObjectException {
198.1059 +            if (this.getClass() != NumberFormat.Field.class) {
198.1060 +                throw new InvalidObjectException("subclass didn't correctly implement readResolve");
198.1061 +            }
198.1062 +
198.1063 +            Object instance = instanceMap.get(getName());
198.1064 +            if (instance != null) {
198.1065 +                return instance;
198.1066 +            } else {
198.1067 +                throw new InvalidObjectException("unknown attribute name");
198.1068 +            }
198.1069 +        }
198.1070 +
198.1071 +        /**
198.1072 +         * Constant identifying the integer field.
198.1073 +         */
198.1074 +        public static final Field INTEGER = new Field("integer");
198.1075 +
198.1076 +        /**
198.1077 +         * Constant identifying the fraction field.
198.1078 +         */
198.1079 +        public static final Field FRACTION = new Field("fraction");
198.1080 +
198.1081 +        /**
198.1082 +         * Constant identifying the exponent field.
198.1083 +         */
198.1084 +        public static final Field EXPONENT = new Field("exponent");
198.1085 +
198.1086 +        /**
198.1087 +         * Constant identifying the decimal separator field.
198.1088 +         */
198.1089 +        public static final Field DECIMAL_SEPARATOR =
198.1090 +                            new Field("decimal separator");
198.1091 +
198.1092 +        /**
198.1093 +         * Constant identifying the sign field.
198.1094 +         */
198.1095 +        public static final Field SIGN = new Field("sign");
198.1096 +
198.1097 +        /**
198.1098 +         * Constant identifying the grouping separator field.
198.1099 +         */
198.1100 +        public static final Field GROUPING_SEPARATOR =
198.1101 +                            new Field("grouping separator");
198.1102 +
198.1103 +        /**
198.1104 +         * Constant identifying the exponent symbol field.
198.1105 +         */
198.1106 +        public static final Field EXPONENT_SYMBOL = new
198.1107 +                            Field("exponent symbol");
198.1108 +
198.1109 +        /**
198.1110 +         * Constant identifying the percent field.
198.1111 +         */
198.1112 +        public static final Field PERCENT = new Field("percent");
198.1113 +
198.1114 +        /**
198.1115 +         * Constant identifying the permille field.
198.1116 +         */
198.1117 +        public static final Field PERMILLE = new Field("per mille");
198.1118 +
198.1119 +        /**
198.1120 +         * Constant identifying the currency field.
198.1121 +         */
198.1122 +        public static final Field CURRENCY = new Field("currency");
198.1123 +
198.1124 +        /**
198.1125 +         * Constant identifying the exponent sign field.
198.1126 +         */
198.1127 +        public static final Field EXPONENT_SIGN = new Field("exponent sign");
198.1128 +    }
198.1129 +
198.1130 +    /**
198.1131 +     * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
198.1132 +     *
198.1133 +    private static class NumberFormatGetter
198.1134 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
198.1135 +                                                                   NumberFormat> {
198.1136 +        private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
198.1137 +
198.1138 +        public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
198.1139 +                                Locale locale,
198.1140 +                                String key,
198.1141 +                                Object... params) {
198.1142 +            assert params.length == 1;
198.1143 +            int choice = (Integer)params[0];
198.1144 +
198.1145 +            switch (choice) {
198.1146 +            case NUMBERSTYLE:
198.1147 +                return numberFormatProvider.getNumberInstance(locale);
198.1148 +            case PERCENTSTYLE:
198.1149 +                return numberFormatProvider.getPercentInstance(locale);
198.1150 +            case CURRENCYSTYLE:
198.1151 +                return numberFormatProvider.getCurrencyInstance(locale);
198.1152 +            case INTEGERSTYLE:
198.1153 +                return numberFormatProvider.getIntegerInstance(locale);
198.1154 +            default:
198.1155 +                assert false : choice;
198.1156 +            }
198.1157 +
198.1158 +            return null;
198.1159 +        }
198.1160 +    }
198.1161 +    */
198.1162 +}
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/rt/emul/compact/src/main/java/java/text/ParseException.java	Wed Apr 30 15:04:10 2014 +0200
   199.3 @@ -0,0 +1,78 @@
   199.4 +/*
   199.5 + * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
   199.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   199.7 + *
   199.8 + * This code is free software; you can redistribute it and/or modify it
   199.9 + * under the terms of the GNU General Public License version 2 only, as
  199.10 + * published by the Free Software Foundation.  Oracle designates this
  199.11 + * particular file as subject to the "Classpath" exception as provided
  199.12 + * by Oracle in the LICENSE file that accompanied this code.
  199.13 + *
  199.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  199.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  199.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  199.17 + * version 2 for more details (a copy is included in the LICENSE file that
  199.18 + * accompanied this code).
  199.19 + *
  199.20 + * You should have received a copy of the GNU General Public License version
  199.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  199.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  199.23 + *
  199.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  199.25 + * or visit www.oracle.com if you need additional information or have any
  199.26 + * questions.
  199.27 + */
  199.28 +
  199.29 +/*
  199.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  199.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  199.32 + *
  199.33 + *   The original version of this source code and documentation is copyrighted
  199.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  199.35 + * materials are provided under terms of a License Agreement between Taligent
  199.36 + * and Sun. This technology is protected by multiple US and International
  199.37 + * patents. This notice and attribution to Taligent may not be removed.
  199.38 + *   Taligent is a registered trademark of Taligent, Inc.
  199.39 + *
  199.40 + */
  199.41 +
  199.42 +package java.text;
  199.43 +
  199.44 +/**
  199.45 + * Signals that an error has been reached unexpectedly
  199.46 + * while parsing.
  199.47 + * @see java.lang.Exception
  199.48 + * @see java.text.Format
  199.49 + * @see java.text.FieldPosition
  199.50 + * @author      Mark Davis
  199.51 + */
  199.52 +public
  199.53 +class ParseException extends Exception {
  199.54 +
  199.55 +    /**
  199.56 +     * Constructs a ParseException with the specified detail message and
  199.57 +     * offset.
  199.58 +     * A detail message is a String that describes this particular exception.
  199.59 +     * @param s the detail message
  199.60 +     * @param errorOffset the position where the error is found while parsing.
  199.61 +     */
  199.62 +    public ParseException(String s, int errorOffset) {
  199.63 +        super(s);
  199.64 +        this.errorOffset = errorOffset;
  199.65 +    }
  199.66 +
  199.67 +    /**
  199.68 +     * Returns the position where the error was found.
  199.69 +     */
  199.70 +    public int getErrorOffset () {
  199.71 +        return errorOffset;
  199.72 +    }
  199.73 +
  199.74 +    //============ privates ============
  199.75 +    /**
  199.76 +     * The zero-based character offset into the string being parsed at which
  199.77 +     * the error was found during parsing.
  199.78 +     * @serial
  199.79 +     */
  199.80 +    private int errorOffset;
  199.81 +}
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/rt/emul/compact/src/main/java/java/text/ParsePosition.java	Wed Apr 30 15:04:10 2014 +0200
   200.3 @@ -0,0 +1,139 @@
   200.4 +/*
   200.5 + * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
   200.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   200.7 + *
   200.8 + * This code is free software; you can redistribute it and/or modify it
   200.9 + * under the terms of the GNU General Public License version 2 only, as
  200.10 + * published by the Free Software Foundation.  Oracle designates this
  200.11 + * particular file as subject to the "Classpath" exception as provided
  200.12 + * by Oracle in the LICENSE file that accompanied this code.
  200.13 + *
  200.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  200.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  200.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  200.17 + * version 2 for more details (a copy is included in the LICENSE file that
  200.18 + * accompanied this code).
  200.19 + *
  200.20 + * You should have received a copy of the GNU General Public License version
  200.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  200.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  200.23 + *
  200.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  200.25 + * or visit www.oracle.com if you need additional information or have any
  200.26 + * questions.
  200.27 + */
  200.28 +
  200.29 +/*
  200.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  200.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  200.32 + *
  200.33 + *   The original version of this source code and documentation is copyrighted
  200.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  200.35 + * materials are provided under terms of a License Agreement between Taligent
  200.36 + * and Sun. This technology is protected by multiple US and International
  200.37 + * patents. This notice and attribution to Taligent may not be removed.
  200.38 + *   Taligent is a registered trademark of Taligent, Inc.
  200.39 + *
  200.40 + */
  200.41 +
  200.42 +package java.text;
  200.43 +
  200.44 +
  200.45 +/**
  200.46 + * <code>ParsePosition</code> is a simple class used by <code>Format</code>
  200.47 + * and its subclasses to keep track of the current position during parsing.
  200.48 + * The <code>parseObject</code> method in the various <code>Format</code>
  200.49 + * classes requires a <code>ParsePosition</code> object as an argument.
  200.50 + *
  200.51 + * <p>
  200.52 + * By design, as you parse through a string with different formats,
  200.53 + * you can use the same <code>ParsePosition</code>, since the index parameter
  200.54 + * records the current position.
  200.55 + *
  200.56 + * @author      Mark Davis
  200.57 + * @see         java.text.Format
  200.58 + */
  200.59 +
  200.60 +public class ParsePosition {
  200.61 +
  200.62 +    /**
  200.63 +     * Input: the place you start parsing.
  200.64 +     * <br>Output: position where the parse stopped.
  200.65 +     * This is designed to be used serially,
  200.66 +     * with each call setting index up for the next one.
  200.67 +     */
  200.68 +    int index = 0;
  200.69 +    int errorIndex = -1;
  200.70 +
  200.71 +    /**
  200.72 +     * Retrieve the current parse position.  On input to a parse method, this
  200.73 +     * is the index of the character at which parsing will begin; on output, it
  200.74 +     * is the index of the character following the last character parsed.
  200.75 +     */
  200.76 +    public int getIndex() {
  200.77 +        return index;
  200.78 +    }
  200.79 +
  200.80 +    /**
  200.81 +     * Set the current parse position.
  200.82 +     */
  200.83 +    public void setIndex(int index) {
  200.84 +        this.index = index;
  200.85 +    }
  200.86 +
  200.87 +    /**
  200.88 +     * Create a new ParsePosition with the given initial index.
  200.89 +     */
  200.90 +    public ParsePosition(int index) {
  200.91 +        this.index = index;
  200.92 +    }
  200.93 +    /**
  200.94 +     * Set the index at which a parse error occurred.  Formatters
  200.95 +     * should set this before returning an error code from their
  200.96 +     * parseObject method.  The default value is -1 if this is not set.
  200.97 +     * @since 1.2
  200.98 +     */
  200.99 +    public void setErrorIndex(int ei)
 200.100 +    {
 200.101 +        errorIndex = ei;
 200.102 +    }
 200.103 +
 200.104 +    /**
 200.105 +     * Retrieve the index at which an error occurred, or -1 if the
 200.106 +     * error index has not been set.
 200.107 +     * @since 1.2
 200.108 +     */
 200.109 +    public int getErrorIndex()
 200.110 +    {
 200.111 +        return errorIndex;
 200.112 +    }
 200.113 +    /**
 200.114 +     * Overrides equals
 200.115 +     */
 200.116 +    public boolean equals(Object obj)
 200.117 +    {
 200.118 +        if (obj == null) return false;
 200.119 +        if (!(obj instanceof ParsePosition))
 200.120 +            return false;
 200.121 +        ParsePosition other = (ParsePosition) obj;
 200.122 +        return (index == other.index && errorIndex == other.errorIndex);
 200.123 +    }
 200.124 +
 200.125 +    /**
 200.126 +     * Returns a hash code for this ParsePosition.
 200.127 +     * @return a hash code value for this object
 200.128 +     */
 200.129 +    public int hashCode() {
 200.130 +        return (errorIndex << 16) | index;
 200.131 +    }
 200.132 +
 200.133 +    /**
 200.134 +     * Return a string representation of this ParsePosition.
 200.135 +     * @return  a string representation of this object
 200.136 +     */
 200.137 +    public String toString() {
 200.138 +        return getClass().getName() +
 200.139 +            "[index=" + index +
 200.140 +            ",errorIndex=" + errorIndex + ']';
 200.141 +    }
 200.142 +}
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/rt/emul/compact/src/main/java/java/text/SimpleDateFormat.java	Wed Apr 30 15:04:10 2014 +0200
   201.3 @@ -0,0 +1,2383 @@
   201.4 +/*
   201.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   201.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   201.7 + *
   201.8 + * This code is free software; you can redistribute it and/or modify it
   201.9 + * under the terms of the GNU General Public License version 2 only, as
  201.10 + * published by the Free Software Foundation.  Oracle designates this
  201.11 + * particular file as subject to the "Classpath" exception as provided
  201.12 + * by Oracle in the LICENSE file that accompanied this code.
  201.13 + *
  201.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  201.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  201.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  201.17 + * version 2 for more details (a copy is included in the LICENSE file that
  201.18 + * accompanied this code).
  201.19 + *
  201.20 + * You should have received a copy of the GNU General Public License version
  201.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  201.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  201.23 + *
  201.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  201.25 + * or visit www.oracle.com if you need additional information or have any
  201.26 + * questions.
  201.27 + */
  201.28 +
  201.29 +/*
  201.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  201.31 + * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
  201.32 + *
  201.33 + *   The original version of this source code and documentation is copyrighted
  201.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  201.35 + * materials are provided under terms of a License Agreement between Taligent
  201.36 + * and Sun. This technology is protected by multiple US and International
  201.37 + * patents. This notice and attribution to Taligent may not be removed.
  201.38 + *   Taligent is a registered trademark of Taligent, Inc.
  201.39 + *
  201.40 + */
  201.41 +
  201.42 +package java.text;
  201.43 +
  201.44 +import java.io.IOException;
  201.45 +import java.io.InvalidObjectException;
  201.46 +import java.io.ObjectInputStream;
  201.47 +import java.util.Calendar;
  201.48 +import java.util.Date;
  201.49 +import java.util.Locale;
  201.50 +import java.util.Map;
  201.51 +import java.util.MissingResourceException;
  201.52 +import java.util.ResourceBundle;
  201.53 +import java.util.SimpleTimeZone;
  201.54 +import java.util.TimeZone;
  201.55 +import java.util.concurrent.ConcurrentHashMap;
  201.56 +import java.util.concurrent.ConcurrentMap;
  201.57 +
  201.58 +import static java.text.DateFormatSymbols.*;
  201.59 +
  201.60 +/**
  201.61 + * <code>SimpleDateFormat</code> is a concrete class for formatting and
  201.62 + * parsing dates in a locale-sensitive manner. It allows for formatting
  201.63 + * (date -> text), parsing (text -> date), and normalization.
  201.64 + *
  201.65 + * <p>
  201.66 + * <code>SimpleDateFormat</code> allows you to start by choosing
  201.67 + * any user-defined patterns for date-time formatting. However, you
  201.68 + * are encouraged to create a date-time formatter with either
  201.69 + * <code>getTimeInstance</code>, <code>getDateInstance</code>, or
  201.70 + * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
  201.71 + * of these class methods can return a date/time formatter initialized
  201.72 + * with a default format pattern. You may modify the format pattern
  201.73 + * using the <code>applyPattern</code> methods as desired.
  201.74 + * For more information on using these methods, see
  201.75 + * {@link DateFormat}.
  201.76 + *
  201.77 + * <h4>Date and Time Patterns</h4>
  201.78 + * <p>
  201.79 + * Date and time formats are specified by <em>date and time pattern</em>
  201.80 + * strings.
  201.81 + * Within date and time pattern strings, unquoted letters from
  201.82 + * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
  201.83 + * <code>'z'</code> are interpreted as pattern letters representing the
  201.84 + * components of a date or time string.
  201.85 + * Text can be quoted using single quotes (<code>'</code>) to avoid
  201.86 + * interpretation.
  201.87 + * <code>"''"</code> represents a single quote.
  201.88 + * All other characters are not interpreted; they're simply copied into the
  201.89 + * output string during formatting or matched against the input string
  201.90 + * during parsing.
  201.91 + * <p>
  201.92 + * The following pattern letters are defined (all other characters from
  201.93 + * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
  201.94 + * <code>'z'</code> are reserved):
  201.95 + * <blockquote>
  201.96 + * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component, presentation, and examples.">
  201.97 + *     <tr bgcolor="#ccccff">
  201.98 + *         <th align=left>Letter
  201.99 + *         <th align=left>Date or Time Component
 201.100 + *         <th align=left>Presentation
 201.101 + *         <th align=left>Examples
 201.102 + *     <tr>
 201.103 + *         <td><code>G</code>
 201.104 + *         <td>Era designator
 201.105 + *         <td><a href="#text">Text</a>
 201.106 + *         <td><code>AD</code>
 201.107 + *     <tr bgcolor="#eeeeff">
 201.108 + *         <td><code>y</code>
 201.109 + *         <td>Year
 201.110 + *         <td><a href="#year">Year</a>
 201.111 + *         <td><code>1996</code>; <code>96</code>
 201.112 + *     <tr>
 201.113 + *         <td><code>Y</code>
 201.114 + *         <td>Week year
 201.115 + *         <td><a href="#year">Year</a>
 201.116 + *         <td><code>2009</code>; <code>09</code>
 201.117 + *     <tr bgcolor="#eeeeff">
 201.118 + *         <td><code>M</code>
 201.119 + *         <td>Month in year
 201.120 + *         <td><a href="#month">Month</a>
 201.121 + *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
 201.122 + *     <tr>
 201.123 + *         <td><code>w</code>
 201.124 + *         <td>Week in year
 201.125 + *         <td><a href="#number">Number</a>
 201.126 + *         <td><code>27</code>
 201.127 + *     <tr bgcolor="#eeeeff">
 201.128 + *         <td><code>W</code>
 201.129 + *         <td>Week in month
 201.130 + *         <td><a href="#number">Number</a>
 201.131 + *         <td><code>2</code>
 201.132 + *     <tr>
 201.133 + *         <td><code>D</code>
 201.134 + *         <td>Day in year
 201.135 + *         <td><a href="#number">Number</a>
 201.136 + *         <td><code>189</code>
 201.137 + *     <tr bgcolor="#eeeeff">
 201.138 + *         <td><code>d</code>
 201.139 + *         <td>Day in month
 201.140 + *         <td><a href="#number">Number</a>
 201.141 + *         <td><code>10</code>
 201.142 + *     <tr>
 201.143 + *         <td><code>F</code>
 201.144 + *         <td>Day of week in month
 201.145 + *         <td><a href="#number">Number</a>
 201.146 + *         <td><code>2</code>
 201.147 + *     <tr bgcolor="#eeeeff">
 201.148 + *         <td><code>E</code>
 201.149 + *         <td>Day name in week
 201.150 + *         <td><a href="#text">Text</a>
 201.151 + *         <td><code>Tuesday</code>; <code>Tue</code>
 201.152 + *     <tr>
 201.153 + *         <td><code>u</code>
 201.154 + *         <td>Day number of week (1 = Monday, ..., 7 = Sunday)
 201.155 + *         <td><a href="#number">Number</a>
 201.156 + *         <td><code>1</code>
 201.157 + *     <tr bgcolor="#eeeeff">
 201.158 + *         <td><code>a</code>
 201.159 + *         <td>Am/pm marker
 201.160 + *         <td><a href="#text">Text</a>
 201.161 + *         <td><code>PM</code>
 201.162 + *     <tr>
 201.163 + *         <td><code>H</code>
 201.164 + *         <td>Hour in day (0-23)
 201.165 + *         <td><a href="#number">Number</a>
 201.166 + *         <td><code>0</code>
 201.167 + *     <tr bgcolor="#eeeeff">
 201.168 + *         <td><code>k</code>
 201.169 + *         <td>Hour in day (1-24)
 201.170 + *         <td><a href="#number">Number</a>
 201.171 + *         <td><code>24</code>
 201.172 + *     <tr>
 201.173 + *         <td><code>K</code>
 201.174 + *         <td>Hour in am/pm (0-11)
 201.175 + *         <td><a href="#number">Number</a>
 201.176 + *         <td><code>0</code>
 201.177 + *     <tr bgcolor="#eeeeff">
 201.178 + *         <td><code>h</code>
 201.179 + *         <td>Hour in am/pm (1-12)
 201.180 + *         <td><a href="#number">Number</a>
 201.181 + *         <td><code>12</code>
 201.182 + *     <tr>
 201.183 + *         <td><code>m</code>
 201.184 + *         <td>Minute in hour
 201.185 + *         <td><a href="#number">Number</a>
 201.186 + *         <td><code>30</code>
 201.187 + *     <tr bgcolor="#eeeeff">
 201.188 + *         <td><code>s</code>
 201.189 + *         <td>Second in minute
 201.190 + *         <td><a href="#number">Number</a>
 201.191 + *         <td><code>55</code>
 201.192 + *     <tr>
 201.193 + *         <td><code>S</code>
 201.194 + *         <td>Millisecond
 201.195 + *         <td><a href="#number">Number</a>
 201.196 + *         <td><code>978</code>
 201.197 + *     <tr bgcolor="#eeeeff">
 201.198 + *         <td><code>z</code>
 201.199 + *         <td>Time zone
 201.200 + *         <td><a href="#timezone">General time zone</a>
 201.201 + *         <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
 201.202 + *     <tr>
 201.203 + *         <td><code>Z</code>
 201.204 + *         <td>Time zone
 201.205 + *         <td><a href="#rfc822timezone">RFC 822 time zone</a>
 201.206 + *         <td><code>-0800</code>
 201.207 + *     <tr bgcolor="#eeeeff">
 201.208 + *         <td><code>X</code>
 201.209 + *         <td>Time zone
 201.210 + *         <td><a href="#iso8601timezone">ISO 8601 time zone</a>
 201.211 + *         <td><code>-08</code>; <code>-0800</code>;  <code>-08:00</code>
 201.212 + * </table>
 201.213 + * </blockquote>
 201.214 + * Pattern letters are usually repeated, as their number determines the
 201.215 + * exact presentation:
 201.216 + * <ul>
 201.217 + * <li><strong><a name="text">Text:</a></strong>
 201.218 + *     For formatting, if the number of pattern letters is 4 or more,
 201.219 + *     the full form is used; otherwise a short or abbreviated form
 201.220 + *     is used if available.
 201.221 + *     For parsing, both forms are accepted, independent of the number
 201.222 + *     of pattern letters.<br><br></li>
 201.223 + * <li><strong><a name="number">Number:</a></strong>
 201.224 + *     For formatting, the number of pattern letters is the minimum
 201.225 + *     number of digits, and shorter numbers are zero-padded to this amount.
 201.226 + *     For parsing, the number of pattern letters is ignored unless
 201.227 + *     it's needed to separate two adjacent fields.<br><br></li>
 201.228 + * <li><strong><a name="year">Year:</a></strong>
 201.229 + *     If the formatter's {@link #getCalendar() Calendar} is the Gregorian
 201.230 + *     calendar, the following rules are applied.<br>
 201.231 + *     <ul>
 201.232 + *     <li>For formatting, if the number of pattern letters is 2, the year
 201.233 + *         is truncated to 2 digits; otherwise it is interpreted as a
 201.234 + *         <a href="#number">number</a>.
 201.235 + *     <li>For parsing, if the number of pattern letters is more than 2,
 201.236 + *         the year is interpreted literally, regardless of the number of
 201.237 + *         digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to
 201.238 + *         Jan 11, 12 A.D.
 201.239 + *     <li>For parsing with the abbreviated year pattern ("y" or "yy"),
 201.240 + *         <code>SimpleDateFormat</code> must interpret the abbreviated year
 201.241 + *         relative to some century.  It does this by adjusting dates to be
 201.242 + *         within 80 years before and 20 years after the time the <code>SimpleDateFormat</code>
 201.243 + *         instance is created. For example, using a pattern of "MM/dd/yy" and a
 201.244 + *         <code>SimpleDateFormat</code> instance created on Jan 1, 1997,  the string
 201.245 + *         "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
 201.246 + *         would be interpreted as May 4, 1964.
 201.247 + *         During parsing, only strings consisting of exactly two digits, as defined by
 201.248 + *         {@link Character#isDigit(char)}, will be parsed into the default century.
 201.249 + *         Any other numeric string, such as a one digit string, a three or more digit
 201.250 + *         string, or a two digit string that isn't all digits (for example, "-1"), is
 201.251 + *         interpreted literally.  So "01/02/3" or "01/02/003" are parsed, using the
 201.252 + *         same pattern, as Jan 2, 3 AD.  Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
 201.253 + *     </ul>
 201.254 + *     Otherwise, calendar system specific forms are applied.
 201.255 + *     For both formatting and parsing, if the number of pattern
 201.256 + *     letters is 4 or more, a calendar specific {@linkplain
 201.257 + *     Calendar#LONG long form} is used. Otherwise, a calendar
 201.258 + *     specific {@linkplain Calendar#SHORT short or abbreviated form}
 201.259 + *     is used.<br>
 201.260 + *     <br>
 201.261 + *     If week year {@code 'Y'} is specified and the {@linkplain
 201.262 + *     #getCalendar() calendar} doesn't support any <a
 201.263 + *     href="../util/GregorianCalendar.html#week_year"> week
 201.264 + *     years</a>, the calendar year ({@code 'y'}) is used instead. The
 201.265 + *     support of week years can be tested with a call to {@link
 201.266 + *     DateFormat#getCalendar() getCalendar()}.{@link
 201.267 + *     java.util.Calendar#isWeekDateSupported()
 201.268 + *     isWeekDateSupported()}.<br><br></li>
 201.269 + * <li><strong><a name="month">Month:</a></strong>
 201.270 + *     If the number of pattern letters is 3 or more, the month is
 201.271 + *     interpreted as <a href="#text">text</a>; otherwise,
 201.272 + *     it is interpreted as a <a href="#number">number</a>.<br><br></li>
 201.273 + * <li><strong><a name="timezone">General time zone:</a></strong>
 201.274 + *     Time zones are interpreted as <a href="#text">text</a> if they have
 201.275 + *     names. For time zones representing a GMT offset value, the
 201.276 + *     following syntax is used:
 201.277 + *     <pre>
 201.278 + *     <a name="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
 201.279 + *             <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
 201.280 + *     <i>Sign:</i> one of
 201.281 + *             <code>+ -</code>
 201.282 + *     <i>Hours:</i>
 201.283 + *             <i>Digit</i>
 201.284 + *             <i>Digit</i> <i>Digit</i>
 201.285 + *     <i>Minutes:</i>
 201.286 + *             <i>Digit</i> <i>Digit</i>
 201.287 + *     <i>Digit:</i> one of
 201.288 + *             <code>0 1 2 3 4 5 6 7 8 9</code></pre>
 201.289 + *     <i>Hours</i> must be between 0 and 23, and <i>Minutes</i> must be between
 201.290 + *     00 and 59. The format is locale independent and digits must be taken
 201.291 + *     from the Basic Latin block of the Unicode standard.
 201.292 + *     <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
 201.293 + *     accepted.<br><br></li>
 201.294 + * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
 201.295 + *     For formatting, the RFC 822 4-digit time zone format is used:
 201.296 + *
 201.297 + *     <pre>
 201.298 + *     <i>RFC822TimeZone:</i>
 201.299 + *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
 201.300 + *     <i>TwoDigitHours:</i>
 201.301 + *             <i>Digit Digit</i></pre>
 201.302 + *     <i>TwoDigitHours</i> must be between 00 and 23. Other definitions
 201.303 + *     are as for <a href="#timezone">general time zones</a>.
 201.304 + *
 201.305 + *     <p>For parsing, <a href="#timezone">general time zones</a> are also
 201.306 + *     accepted.
 201.307 + * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
 201.308 + *     The number of pattern letters designates the format for both formatting
 201.309 + *     and parsing as follows:
 201.310 + *     <pre>
 201.311 + *     <i>ISO8601TimeZone:</i>
 201.312 + *             <i>OneLetterISO8601TimeZone</i>
 201.313 + *             <i>TwoLetterISO8601TimeZone</i>
 201.314 + *             <i>ThreeLetterISO8601TimeZone</i>
 201.315 + *     <i>OneLetterISO8601TimeZone:</i>
 201.316 + *             <i>Sign</i> <i>TwoDigitHours</i>
 201.317 + *             {@code Z}
 201.318 + *     <i>TwoLetterISO8601TimeZone:</i>
 201.319 + *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
 201.320 + *             {@code Z}
 201.321 + *     <i>ThreeLetterISO8601TimeZone:</i>
 201.322 + *             <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
 201.323 + *             {@code Z}</pre>
 201.324 + *     Other definitions are as for <a href="#timezone">general time zones</a> or
 201.325 + *     <a href="#rfc822timezone">RFC 822 time zones</a>.
 201.326 + *
 201.327 + *     <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is
 201.328 + *     produced. If the number of pattern letters is 1, any fraction of an hour
 201.329 + *     is ignored. For example, if the pattern is {@code "X"} and the time zone is
 201.330 + *     {@code "GMT+05:30"}, {@code "+05"} is produced.
 201.331 + *
 201.332 + *     <p>For parsing, {@code "Z"} is parsed as the UTC time zone designator.
 201.333 + *     <a href="#timezone">General time zones</a> are <em>not</em> accepted.
 201.334 + *
 201.335 + *     <p>If the number of pattern letters is 4 or more, {@link
 201.336 + *     IllegalArgumentException} is thrown when constructing a {@code
 201.337 + *     SimpleDateFormat} or {@linkplain #applyPattern(String) applying a
 201.338 + *     pattern}.
 201.339 + * </ul>
 201.340 + * <code>SimpleDateFormat</code> also supports <em>localized date and time
 201.341 + * pattern</em> strings. In these strings, the pattern letters described above
 201.342 + * may be replaced with other, locale dependent, pattern letters.
 201.343 + * <code>SimpleDateFormat</code> does not deal with the localization of text
 201.344 + * other than the pattern letters; that's up to the client of the class.
 201.345 + * <p>
 201.346 + *
 201.347 + * <h4>Examples</h4>
 201.348 + *
 201.349 + * The following examples show how date and time patterns are interpreted in
 201.350 + * the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
 201.351 + * in the U.S. Pacific Time time zone.
 201.352 + * <blockquote>
 201.353 + * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S. locale">
 201.354 + *     <tr bgcolor="#ccccff">
 201.355 + *         <th align=left>Date and Time Pattern
 201.356 + *         <th align=left>Result
 201.357 + *     <tr>
 201.358 + *         <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
 201.359 + *         <td><code>2001.07.04 AD at 12:08:56 PDT</code>
 201.360 + *     <tr bgcolor="#eeeeff">
 201.361 + *         <td><code>"EEE, MMM d, ''yy"</code>
 201.362 + *         <td><code>Wed, Jul 4, '01</code>
 201.363 + *     <tr>
 201.364 + *         <td><code>"h:mm a"</code>
 201.365 + *         <td><code>12:08 PM</code>
 201.366 + *     <tr bgcolor="#eeeeff">
 201.367 + *         <td><code>"hh 'o''clock' a, zzzz"</code>
 201.368 + *         <td><code>12 o'clock PM, Pacific Daylight Time</code>
 201.369 + *     <tr>
 201.370 + *         <td><code>"K:mm a, z"</code>
 201.371 + *         <td><code>0:08 PM, PDT</code>
 201.372 + *     <tr bgcolor="#eeeeff">
 201.373 + *         <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code>
 201.374 + *         <td><code>02001.July.04 AD 12:08 PM</code>
 201.375 + *     <tr>
 201.376 + *         <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
 201.377 + *         <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code>
 201.378 + *     <tr bgcolor="#eeeeff">
 201.379 + *         <td><code>"yyMMddHHmmssZ"</code>
 201.380 + *         <td><code>010704120856-0700</code>
 201.381 + *     <tr>
 201.382 + *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
 201.383 + *         <td><code>2001-07-04T12:08:56.235-0700</code>
 201.384 + *     <tr bgcolor="#eeeeff">
 201.385 + *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
 201.386 + *         <td><code>2001-07-04T12:08:56.235-07:00</code>
 201.387 + *     <tr>
 201.388 + *         <td><code>"YYYY-'W'ww-u"</code>
 201.389 + *         <td><code>2001-W27-3</code>
 201.390 + * </table>
 201.391 + * </blockquote>
 201.392 + *
 201.393 + * <h4><a name="synchronization">Synchronization</a></h4>
 201.394 + *
 201.395 + * <p>
 201.396 + * Date formats are not synchronized.
 201.397 + * It is recommended to create separate format instances for each thread.
 201.398 + * If multiple threads access a format concurrently, it must be synchronized
 201.399 + * externally.
 201.400 + *
 201.401 + * @see          <a href="http://java.sun.com/docs/books/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
 201.402 + * @see          java.util.Calendar
 201.403 + * @see          java.util.TimeZone
 201.404 + * @see          DateFormat
 201.405 + * @see          DateFormatSymbols
 201.406 + * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
 201.407 + */
 201.408 +public class SimpleDateFormat extends DateFormat {
 201.409 +
 201.410 +    // the official serial version ID which says cryptically
 201.411 +    // which version we're compatible with
 201.412 +    static final long serialVersionUID = 4774881970558875024L;
 201.413 +
 201.414 +    // the internal serial version which says which version was written
 201.415 +    // - 0 (default) for version up to JDK 1.1.3
 201.416 +    // - 1 for version from JDK 1.1.4, which includes a new field
 201.417 +    static final int currentSerialVersion = 1;
 201.418 +
 201.419 +    /**
 201.420 +     * The version of the serialized data on the stream.  Possible values:
 201.421 +     * <ul>
 201.422 +     * <li><b>0</b> or not present on stream: JDK 1.1.3.  This version
 201.423 +     * has no <code>defaultCenturyStart</code> on stream.
 201.424 +     * <li><b>1</b> JDK 1.1.4 or later.  This version adds
 201.425 +     * <code>defaultCenturyStart</code>.
 201.426 +     * </ul>
 201.427 +     * When streaming out this class, the most recent format
 201.428 +     * and the highest allowable <code>serialVersionOnStream</code>
 201.429 +     * is written.
 201.430 +     * @serial
 201.431 +     * @since JDK1.1.4
 201.432 +     */
 201.433 +    private int serialVersionOnStream = currentSerialVersion;
 201.434 +
 201.435 +    /**
 201.436 +     * The pattern string of this formatter.  This is always a non-localized
 201.437 +     * pattern.  May not be null.  See class documentation for details.
 201.438 +     * @serial
 201.439 +     */
 201.440 +    private String pattern;
 201.441 +
 201.442 +    /**
 201.443 +     * Saved numberFormat and pattern.
 201.444 +     * @see SimpleDateFormat#checkNegativeNumberExpression
 201.445 +     */
 201.446 +    transient private NumberFormat originalNumberFormat;
 201.447 +    transient private String originalNumberPattern;
 201.448 +
 201.449 +    /**
 201.450 +     * The minus sign to be used with format and parse.
 201.451 +     */
 201.452 +    transient private char minusSign = '-';
 201.453 +
 201.454 +    /**
 201.455 +     * True when a negative sign follows a number.
 201.456 +     * (True as default in Arabic.)
 201.457 +     */
 201.458 +    transient private boolean hasFollowingMinusSign = false;
 201.459 +
 201.460 +    /**
 201.461 +     * The compiled pattern.
 201.462 +     */
 201.463 +    transient private char[] compiledPattern;
 201.464 +
 201.465 +    /**
 201.466 +     * Tags for the compiled pattern.
 201.467 +     */
 201.468 +    private final static int TAG_QUOTE_ASCII_CHAR       = 100;
 201.469 +    private final static int TAG_QUOTE_CHARS            = 101;
 201.470 +
 201.471 +    /**
 201.472 +     * Locale dependent digit zero.
 201.473 +     * @see #zeroPaddingNumber
 201.474 +     * @see java.text.DecimalFormatSymbols#getZeroDigit
 201.475 +     */
 201.476 +    transient private char zeroDigit;
 201.477 +
 201.478 +    /**
 201.479 +     * The symbols used by this formatter for week names, month names,
 201.480 +     * etc.  May not be null.
 201.481 +     * @serial
 201.482 +     * @see java.text.DateFormatSymbols
 201.483 +     */
 201.484 +    private DateFormatSymbols formatData;
 201.485 +
 201.486 +    /**
 201.487 +     * We map dates with two-digit years into the century starting at
 201.488 +     * <code>defaultCenturyStart</code>, which may be any date.  May
 201.489 +     * not be null.
 201.490 +     * @serial
 201.491 +     * @since JDK1.1.4
 201.492 +     */
 201.493 +    private Date defaultCenturyStart;
 201.494 +
 201.495 +    transient private int defaultCenturyStartYear;
 201.496 +
 201.497 +    private static final int MILLIS_PER_MINUTE = 60 * 1000;
 201.498 +
 201.499 +    // For time zones that have no names, use strings GMT+minutes and
 201.500 +    // GMT-minutes. For instance, in France the time zone is GMT+60.
 201.501 +    private static final String GMT = "GMT";
 201.502 +
 201.503 +    /**
 201.504 +     * Cache to hold the DateTimePatterns of a Locale.
 201.505 +     */
 201.506 +    private static final ConcurrentMap<Locale, String[]> cachedLocaleData
 201.507 +        = new ConcurrentHashMap<Locale, String[]>(3);
 201.508 +
 201.509 +    /**
 201.510 +     * Cache NumberFormat instances with Locale key.
 201.511 +     */
 201.512 +    private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
 201.513 +        = new ConcurrentHashMap<Locale, NumberFormat>(3);
 201.514 +
 201.515 +    /**
 201.516 +     * The Locale used to instantiate this
 201.517 +     * <code>SimpleDateFormat</code>. The value may be null if this object
 201.518 +     * has been created by an older <code>SimpleDateFormat</code> and
 201.519 +     * deserialized.
 201.520 +     *
 201.521 +     * @serial
 201.522 +     * @since 1.6
 201.523 +     */
 201.524 +    private Locale locale;
 201.525 +
 201.526 +    /**
 201.527 +     * Indicates whether this <code>SimpleDateFormat</code> should use
 201.528 +     * the DateFormatSymbols. If true, the format and parse methods
 201.529 +     * use the DateFormatSymbols values. If false, the format and
 201.530 +     * parse methods call Calendar.getDisplayName or
 201.531 +     * Calendar.getDisplayNames.
 201.532 +     */
 201.533 +    transient boolean useDateFormatSymbols;
 201.534 +
 201.535 +    /**
 201.536 +     * Constructs a <code>SimpleDateFormat</code> using the default pattern and
 201.537 +     * date format symbols for the default locale.
 201.538 +     * <b>Note:</b> This constructor may not support all locales.
 201.539 +     * For full coverage, use the factory methods in the {@link DateFormat}
 201.540 +     * class.
 201.541 +     */
 201.542 +    public SimpleDateFormat() {
 201.543 +        this(SHORT, SHORT, Locale.getDefault(Locale.Category.FORMAT));
 201.544 +    }
 201.545 +
 201.546 +    /**
 201.547 +     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 201.548 +     * the default date format symbols for the default locale.
 201.549 +     * <b>Note:</b> This constructor may not support all locales.
 201.550 +     * For full coverage, use the factory methods in the {@link DateFormat}
 201.551 +     * class.
 201.552 +     *
 201.553 +     * @param pattern the pattern describing the date and time format
 201.554 +     * @exception NullPointerException if the given pattern is null
 201.555 +     * @exception IllegalArgumentException if the given pattern is invalid
 201.556 +     */
 201.557 +    public SimpleDateFormat(String pattern)
 201.558 +    {
 201.559 +        this(pattern, Locale.getDefault(Locale.Category.FORMAT));
 201.560 +    }
 201.561 +
 201.562 +    /**
 201.563 +     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 201.564 +     * the default date format symbols for the given locale.
 201.565 +     * <b>Note:</b> This constructor may not support all locales.
 201.566 +     * For full coverage, use the factory methods in the {@link DateFormat}
 201.567 +     * class.
 201.568 +     *
 201.569 +     * @param pattern the pattern describing the date and time format
 201.570 +     * @param locale the locale whose date format symbols should be used
 201.571 +     * @exception NullPointerException if the given pattern or locale is null
 201.572 +     * @exception IllegalArgumentException if the given pattern is invalid
 201.573 +     */
 201.574 +    public SimpleDateFormat(String pattern, Locale locale)
 201.575 +    {
 201.576 +        if (pattern == null || locale == null) {
 201.577 +            throw new NullPointerException();
 201.578 +        }
 201.579 +
 201.580 +        initializeCalendar(locale);
 201.581 +        this.pattern = pattern;
 201.582 +        this.formatData = DateFormatSymbols.getInstanceRef(locale);
 201.583 +        this.locale = locale;
 201.584 +        initialize(locale);
 201.585 +    }
 201.586 +
 201.587 +    /**
 201.588 +     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
 201.589 +     * date format symbols.
 201.590 +     *
 201.591 +     * @param pattern the pattern describing the date and time format
 201.592 +     * @param formatSymbols the date format symbols to be used for formatting
 201.593 +     * @exception NullPointerException if the given pattern or formatSymbols is null
 201.594 +     * @exception IllegalArgumentException if the given pattern is invalid
 201.595 +     */
 201.596 +    public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols)
 201.597 +    {
 201.598 +        if (pattern == null || formatSymbols == null) {
 201.599 +            throw new NullPointerException();
 201.600 +        }
 201.601 +
 201.602 +        this.pattern = pattern;
 201.603 +        this.formatData = (DateFormatSymbols) formatSymbols.clone();
 201.604 +        this.locale = Locale.getDefault(Locale.Category.FORMAT);
 201.605 +        initializeCalendar(this.locale);
 201.606 +        initialize(this.locale);
 201.607 +        useDateFormatSymbols = true;
 201.608 +    }
 201.609 +
 201.610 +    /* Package-private, called by DateFormat factory methods */
 201.611 +    SimpleDateFormat(int timeStyle, int dateStyle, Locale loc) {
 201.612 +        if (loc == null) {
 201.613 +            throw new NullPointerException();
 201.614 +        }
 201.615 +
 201.616 +        this.locale = loc;
 201.617 +        // initialize calendar and related fields
 201.618 +        initializeCalendar(loc);
 201.619 +
 201.620 +        /* try the cache first */
 201.621 +        String[] dateTimePatterns = cachedLocaleData.get(loc);
 201.622 +        if (dateTimePatterns == null) { /* cache miss */
 201.623 +            ResourceBundle r = null; // LocaleData.getDateFormatData(loc);
 201.624 +            if (!isGregorianCalendar()) {
 201.625 +                try {
 201.626 +                    dateTimePatterns = r.getStringArray(getCalendarName() + ".DateTimePatterns");
 201.627 +                } catch (MissingResourceException e) {
 201.628 +                }
 201.629 +            }
 201.630 +            if (dateTimePatterns == null) {
 201.631 +                dateTimePatterns = r.getStringArray("DateTimePatterns");
 201.632 +            }
 201.633 +            /* update cache */
 201.634 +            cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
 201.635 +        }
 201.636 +        formatData = DateFormatSymbols.getInstanceRef(loc);
 201.637 +        if ((timeStyle >= 0) && (dateStyle >= 0)) {
 201.638 +            Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
 201.639 +                                     dateTimePatterns[dateStyle + 4]};
 201.640 +            pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
 201.641 +        }
 201.642 +        else if (timeStyle >= 0) {
 201.643 +            pattern = dateTimePatterns[timeStyle];
 201.644 +        }
 201.645 +        else if (dateStyle >= 0) {
 201.646 +            pattern = dateTimePatterns[dateStyle + 4];
 201.647 +        }
 201.648 +        else {
 201.649 +            throw new IllegalArgumentException("No date or time style specified");
 201.650 +        }
 201.651 +
 201.652 +        initialize(loc);
 201.653 +    }
 201.654 +
 201.655 +    /* Initialize compiledPattern and numberFormat fields */
 201.656 +    private void initialize(Locale loc) {
 201.657 +        // Verify and compile the given pattern.
 201.658 +        compiledPattern = compile(pattern);
 201.659 +
 201.660 +        /* try the cache first */
 201.661 +        numberFormat = cachedNumberFormatData.get(loc);
 201.662 +        if (numberFormat == null) { /* cache miss */
 201.663 +            numberFormat = NumberFormat.getIntegerInstance(loc);
 201.664 +            numberFormat.setGroupingUsed(false);
 201.665 +
 201.666 +            /* update cache */
 201.667 +            cachedNumberFormatData.putIfAbsent(loc, numberFormat);
 201.668 +        }
 201.669 +        numberFormat = (NumberFormat) numberFormat.clone();
 201.670 +
 201.671 +        initializeDefaultCentury();
 201.672 +    }
 201.673 +
 201.674 +    private void initializeCalendar(Locale loc) {
 201.675 +        if (calendar == null) {
 201.676 +            assert loc != null;
 201.677 +            // The format object must be constructed using the symbols for this zone.
 201.678 +            // However, the calendar should use the current default TimeZone.
 201.679 +            // If this is not contained in the locale zone strings, then the zone
 201.680 +            // will be formatted using generic GMT+/-H:MM nomenclature.
 201.681 +            calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
 201.682 +        }
 201.683 +    }
 201.684 +
 201.685 +    /**
 201.686 +     * Returns the compiled form of the given pattern. The syntax of
 201.687 +     * the compiled pattern is:
 201.688 +     * <blockquote>
 201.689 +     * CompiledPattern:
 201.690 +     *     EntryList
 201.691 +     * EntryList:
 201.692 +     *     Entry
 201.693 +     *     EntryList Entry
 201.694 +     * Entry:
 201.695 +     *     TagField
 201.696 +     *     TagField data
 201.697 +     * TagField:
 201.698 +     *     Tag Length
 201.699 +     *     TaggedData
 201.700 +     * Tag:
 201.701 +     *     pattern_char_index
 201.702 +     *     TAG_QUOTE_CHARS
 201.703 +     * Length:
 201.704 +     *     short_length
 201.705 +     *     long_length
 201.706 +     * TaggedData:
 201.707 +     *     TAG_QUOTE_ASCII_CHAR ascii_char
 201.708 +     *
 201.709 +     * </blockquote>
 201.710 +     *
 201.711 +     * where `short_length' is an 8-bit unsigned integer between 0 and
 201.712 +     * 254.  `long_length' is a sequence of an 8-bit integer 255 and a
 201.713 +     * 32-bit signed integer value which is split into upper and lower
 201.714 +     * 16-bit fields in two char's. `pattern_char_index' is an 8-bit
 201.715 +     * integer between 0 and 18. `ascii_char' is an 7-bit ASCII
 201.716 +     * character value. `data' depends on its Tag value.
 201.717 +     * <p>
 201.718 +     * If Length is short_length, Tag and short_length are packed in a
 201.719 +     * single char, as illustrated below.
 201.720 +     * <blockquote>
 201.721 +     *     char[0] = (Tag << 8) | short_length;
 201.722 +     * </blockquote>
 201.723 +     *
 201.724 +     * If Length is long_length, Tag and 255 are packed in the first
 201.725 +     * char and a 32-bit integer, as illustrated below.
 201.726 +     * <blockquote>
 201.727 +     *     char[0] = (Tag << 8) | 255;
 201.728 +     *     char[1] = (char) (long_length >>> 16);
 201.729 +     *     char[2] = (char) (long_length & 0xffff);
 201.730 +     * </blockquote>
 201.731 +     * <p>
 201.732 +     * If Tag is a pattern_char_index, its Length is the number of
 201.733 +     * pattern characters. For example, if the given pattern is
 201.734 +     * "yyyy", Tag is 1 and Length is 4, followed by no data.
 201.735 +     * <p>
 201.736 +     * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's
 201.737 +     * following the TagField. For example, if the given pattern is
 201.738 +     * "'o''clock'", Length is 7 followed by a char sequence of
 201.739 +     * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>.
 201.740 +     * <p>
 201.741 +     * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII
 201.742 +     * character in place of Length. For example, if the given pattern
 201.743 +     * is "'o'", the TaggedData entry is
 201.744 +     * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>.
 201.745 +     *
 201.746 +     * @exception NullPointerException if the given pattern is null
 201.747 +     * @exception IllegalArgumentException if the given pattern is invalid
 201.748 +     */
 201.749 +    private char[] compile(String pattern) {
 201.750 +        int length = pattern.length();
 201.751 +        boolean inQuote = false;
 201.752 +        StringBuilder compiledPattern = new StringBuilder(length * 2);
 201.753 +        StringBuilder tmpBuffer = null;
 201.754 +        int count = 0;
 201.755 +        int lastTag = -1;
 201.756 +
 201.757 +        for (int i = 0; i < length; i++) {
 201.758 +            char c = pattern.charAt(i);
 201.759 +
 201.760 +            if (c == '\'') {
 201.761 +                // '' is treated as a single quote regardless of being
 201.762 +                // in a quoted section.
 201.763 +                if ((i + 1) < length) {
 201.764 +                    c = pattern.charAt(i + 1);
 201.765 +                    if (c == '\'') {
 201.766 +                        i++;
 201.767 +                        if (count != 0) {
 201.768 +                            encode(lastTag, count, compiledPattern);
 201.769 +                            lastTag = -1;
 201.770 +                            count = 0;
 201.771 +                        }
 201.772 +                        if (inQuote) {
 201.773 +                            tmpBuffer.append(c);
 201.774 +                        } else {
 201.775 +                            compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c));
 201.776 +                        }
 201.777 +                        continue;
 201.778 +                    }
 201.779 +                }
 201.780 +                if (!inQuote) {
 201.781 +                    if (count != 0) {
 201.782 +                        encode(lastTag, count, compiledPattern);
 201.783 +                        lastTag = -1;
 201.784 +                        count = 0;
 201.785 +                    }
 201.786 +                    if (tmpBuffer == null) {
 201.787 +                        tmpBuffer = new StringBuilder(length);
 201.788 +                    } else {
 201.789 +                        tmpBuffer.setLength(0);
 201.790 +                    }
 201.791 +                    inQuote = true;
 201.792 +                } else {
 201.793 +                    int len = tmpBuffer.length();
 201.794 +                    if (len == 1) {
 201.795 +                        char ch = tmpBuffer.charAt(0);
 201.796 +                        if (ch < 128) {
 201.797 +                            compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | ch));
 201.798 +                        } else {
 201.799 +                            compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | 1));
 201.800 +                            compiledPattern.append(ch);
 201.801 +                        }
 201.802 +                    } else {
 201.803 +                        encode(TAG_QUOTE_CHARS, len, compiledPattern);
 201.804 +                        compiledPattern.append(tmpBuffer);
 201.805 +                    }
 201.806 +                    inQuote = false;
 201.807 +                }
 201.808 +                continue;
 201.809 +            }
 201.810 +            if (inQuote) {
 201.811 +                tmpBuffer.append(c);
 201.812 +                continue;
 201.813 +            }
 201.814 +            if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
 201.815 +                if (count != 0) {
 201.816 +                    encode(lastTag, count, compiledPattern);
 201.817 +                    lastTag = -1;
 201.818 +                    count = 0;
 201.819 +                }
 201.820 +                if (c < 128) {
 201.821 +                    // In most cases, c would be a delimiter, such as ':'.
 201.822 +                    compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c));
 201.823 +                } else {
 201.824 +                    // Take any contiguous non-ASCII alphabet characters and
 201.825 +                    // put them in a single TAG_QUOTE_CHARS.
 201.826 +                    int j;
 201.827 +                    for (j = i + 1; j < length; j++) {
 201.828 +                        char d = pattern.charAt(j);
 201.829 +                        if (d == '\'' || (d >= 'a' && d <= 'z' || d >= 'A' && d <= 'Z')) {
 201.830 +                            break;
 201.831 +                        }
 201.832 +                    }
 201.833 +                    compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | (j - i)));
 201.834 +                    for (; i < j; i++) {
 201.835 +                        compiledPattern.append(pattern.charAt(i));
 201.836 +                    }
 201.837 +                    i--;
 201.838 +                }
 201.839 +                continue;
 201.840 +            }
 201.841 +
 201.842 +            int tag;
 201.843 +            if ((tag = DateFormatSymbols.patternChars.indexOf(c)) == -1) {
 201.844 +                throw new IllegalArgumentException("Illegal pattern character " +
 201.845 +                                                   "'" + c + "'");
 201.846 +            }
 201.847 +            if (lastTag == -1 || lastTag == tag) {
 201.848 +                lastTag = tag;
 201.849 +                count++;
 201.850 +                continue;
 201.851 +            }
 201.852 +            encode(lastTag, count, compiledPattern);
 201.853 +            lastTag = tag;
 201.854 +            count = 1;
 201.855 +        }
 201.856 +
 201.857 +        if (inQuote) {
 201.858 +            throw new IllegalArgumentException("Unterminated quote");
 201.859 +        }
 201.860 +
 201.861 +        if (count != 0) {
 201.862 +            encode(lastTag, count, compiledPattern);
 201.863 +        }
 201.864 +
 201.865 +        // Copy the compiled pattern to a char array
 201.866 +        int len = compiledPattern.length();
 201.867 +        char[] r = new char[len];
 201.868 +        compiledPattern.getChars(0, len, r, 0);
 201.869 +        return r;
 201.870 +    }
 201.871 +
 201.872 +    /**
 201.873 +     * Encodes the given tag and length and puts encoded char(s) into buffer.
 201.874 +     */
 201.875 +    private static final void encode(int tag, int length, StringBuilder buffer) {
 201.876 +        if (tag == PATTERN_ISO_ZONE && length >= 4) {
 201.877 +            throw new IllegalArgumentException("invalid ISO 8601 format: length=" + length);
 201.878 +        }
 201.879 +        if (length < 255) {
 201.880 +            buffer.append((char)(tag << 8 | length));
 201.881 +        } else {
 201.882 +            buffer.append((char)((tag << 8) | 0xff));
 201.883 +            buffer.append((char)(length >>> 16));
 201.884 +            buffer.append((char)(length & 0xffff));
 201.885 +        }
 201.886 +    }
 201.887 +
 201.888 +    /* Initialize the fields we use to disambiguate ambiguous years. Separate
 201.889 +     * so we can call it from readObject().
 201.890 +     */
 201.891 +    private void initializeDefaultCentury() {
 201.892 +        calendar.setTimeInMillis(System.currentTimeMillis());
 201.893 +        calendar.add( Calendar.YEAR, -80 );
 201.894 +        parseAmbiguousDatesAsAfter(calendar.getTime());
 201.895 +    }
 201.896 +
 201.897 +    /* Define one-century window into which to disambiguate dates using
 201.898 +     * two-digit years.
 201.899 +     */
 201.900 +    private void parseAmbiguousDatesAsAfter(Date startDate) {
 201.901 +        defaultCenturyStart = startDate;
 201.902 +        calendar.setTime(startDate);
 201.903 +        defaultCenturyStartYear = calendar.get(Calendar.YEAR);
 201.904 +    }
 201.905 +
 201.906 +    /**
 201.907 +     * Sets the 100-year period 2-digit years will be interpreted as being in
 201.908 +     * to begin on the date the user specifies.
 201.909 +     *
 201.910 +     * @param startDate During parsing, two digit years will be placed in the range
 201.911 +     * <code>startDate</code> to <code>startDate + 100 years</code>.
 201.912 +     * @see #get2DigitYearStart
 201.913 +     * @since 1.2
 201.914 +     */
 201.915 +    public void set2DigitYearStart(Date startDate) {
 201.916 +        parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
 201.917 +    }
 201.918 +
 201.919 +    /**
 201.920 +     * Returns the beginning date of the 100-year period 2-digit years are interpreted
 201.921 +     * as being within.
 201.922 +     *
 201.923 +     * @return the start of the 100-year period into which two digit years are
 201.924 +     * parsed
 201.925 +     * @see #set2DigitYearStart
 201.926 +     * @since 1.2
 201.927 +     */
 201.928 +    public Date get2DigitYearStart() {
 201.929 +        return (Date) defaultCenturyStart.clone();
 201.930 +    }
 201.931 +
 201.932 +    /**
 201.933 +     * Formats the given <code>Date</code> into a date/time string and appends
 201.934 +     * the result to the given <code>StringBuffer</code>.
 201.935 +     *
 201.936 +     * @param date the date-time value to be formatted into a date-time string.
 201.937 +     * @param toAppendTo where the new date-time text is to be appended.
 201.938 +     * @param pos the formatting position. On input: an alignment field,
 201.939 +     * if desired. On output: the offsets of the alignment field.
 201.940 +     * @return the formatted date-time string.
 201.941 +     * @exception NullPointerException if the given {@code date} is {@code null}.
 201.942 +     */
 201.943 +    public StringBuffer format(Date date, StringBuffer toAppendTo,
 201.944 +                               FieldPosition pos)
 201.945 +    {
 201.946 +        pos.beginIndex = pos.endIndex = 0;
 201.947 +        return format(date, toAppendTo, pos.getFieldDelegate());
 201.948 +    }
 201.949 +
 201.950 +    // Called from Format after creating a FieldDelegate
 201.951 +    private StringBuffer format(Date date, StringBuffer toAppendTo,
 201.952 +                                FieldDelegate delegate) {
 201.953 +        // Convert input date to time field list
 201.954 +        calendar.setTime(date);
 201.955 +
 201.956 +        boolean useDateFormatSymbols = useDateFormatSymbols();
 201.957 +
 201.958 +        for (int i = 0; i < compiledPattern.length; ) {
 201.959 +            int tag = compiledPattern[i] >>> 8;
 201.960 +            int count = compiledPattern[i++] & 0xff;
 201.961 +            if (count == 255) {
 201.962 +                count = compiledPattern[i++] << 16;
 201.963 +                count |= compiledPattern[i++];
 201.964 +            }
 201.965 +
 201.966 +            switch (tag) {
 201.967 +            case TAG_QUOTE_ASCII_CHAR:
 201.968 +                toAppendTo.append((char)count);
 201.969 +                break;
 201.970 +
 201.971 +            case TAG_QUOTE_CHARS:
 201.972 +                toAppendTo.append(compiledPattern, i, count);
 201.973 +                i += count;
 201.974 +                break;
 201.975 +
 201.976 +            default:
 201.977 +                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
 201.978 +                break;
 201.979 +            }
 201.980 +        }
 201.981 +        return toAppendTo;
 201.982 +    }
 201.983 +
 201.984 +    /**
 201.985 +     * Formats an Object producing an <code>AttributedCharacterIterator</code>.
 201.986 +     * You can use the returned <code>AttributedCharacterIterator</code>
 201.987 +     * to build the resulting String, as well as to determine information
 201.988 +     * about the resulting String.
 201.989 +     * <p>
 201.990 +     * Each attribute key of the AttributedCharacterIterator will be of type
 201.991 +     * <code>DateFormat.Field</code>, with the corresponding attribute value
 201.992 +     * being the same as the attribute key.
 201.993 +     *
 201.994 +     * @exception NullPointerException if obj is null.
 201.995 +     * @exception IllegalArgumentException if the Format cannot format the
 201.996 +     *            given object, or if the Format's pattern string is invalid.
 201.997 +     * @param obj The object to format
 201.998 +     * @return AttributedCharacterIterator describing the formatted value.
 201.999 +     * @since 1.4
201.1000 +     */
201.1001 +    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
201.1002 +        StringBuffer sb = new StringBuffer();
201.1003 +        CharacterIteratorFieldDelegate delegate = new
201.1004 +                         CharacterIteratorFieldDelegate();
201.1005 +
201.1006 +        if (obj instanceof Date) {
201.1007 +            format((Date)obj, sb, delegate);
201.1008 +        }
201.1009 +        else if (obj instanceof Number) {
201.1010 +            format(new Date(((Number)obj).longValue()), sb, delegate);
201.1011 +        }
201.1012 +        else if (obj == null) {
201.1013 +            throw new NullPointerException(
201.1014 +                   "formatToCharacterIterator must be passed non-null object");
201.1015 +        }
201.1016 +        else {
201.1017 +            throw new IllegalArgumentException(
201.1018 +                             "Cannot format given Object as a Date");
201.1019 +        }
201.1020 +        return delegate.getIterator(sb.toString());
201.1021 +    }
201.1022 +
201.1023 +    // Map index into pattern character string to Calendar field number
201.1024 +    private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD =
201.1025 +    {
201.1026 +        Calendar.ERA, Calendar.YEAR, Calendar.MONTH, Calendar.DATE,
201.1027 +        Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY, Calendar.MINUTE,
201.1028 +        Calendar.SECOND, Calendar.MILLISECOND, Calendar.DAY_OF_WEEK,
201.1029 +        Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH,
201.1030 +        Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH,
201.1031 +        Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET,
201.1032 +        Calendar.ZONE_OFFSET,
201.1033 +        // Pseudo Calendar fields
201.1034 +        CalendarBuilder.WEEK_YEAR,
201.1035 +        CalendarBuilder.ISO_DAY_OF_WEEK,
201.1036 +        Calendar.ZONE_OFFSET
201.1037 +    };
201.1038 +
201.1039 +    // Map index into pattern character string to DateFormat field number
201.1040 +    private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = {
201.1041 +        DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
201.1042 +        DateFormat.DATE_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
201.1043 +        DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.MINUTE_FIELD,
201.1044 +        DateFormat.SECOND_FIELD, DateFormat.MILLISECOND_FIELD,
201.1045 +        DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_YEAR_FIELD,
201.1046 +        DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, DateFormat.WEEK_OF_YEAR_FIELD,
201.1047 +        DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
201.1048 +        DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD,
201.1049 +        DateFormat.TIMEZONE_FIELD, DateFormat.TIMEZONE_FIELD,
201.1050 +        DateFormat.YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD,
201.1051 +        DateFormat.TIMEZONE_FIELD
201.1052 +    };
201.1053 +
201.1054 +    // Maps from DecimalFormatSymbols index to Field constant
201.1055 +    private static final Field[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID = {
201.1056 +        Field.ERA, Field.YEAR, Field.MONTH, Field.DAY_OF_MONTH,
201.1057 +        Field.HOUR_OF_DAY1, Field.HOUR_OF_DAY0, Field.MINUTE,
201.1058 +        Field.SECOND, Field.MILLISECOND, Field.DAY_OF_WEEK,
201.1059 +        Field.DAY_OF_YEAR, Field.DAY_OF_WEEK_IN_MONTH,
201.1060 +        Field.WEEK_OF_YEAR, Field.WEEK_OF_MONTH,
201.1061 +        Field.AM_PM, Field.HOUR1, Field.HOUR0, Field.TIME_ZONE,
201.1062 +        Field.TIME_ZONE,
201.1063 +        Field.YEAR, Field.DAY_OF_WEEK,
201.1064 +        Field.TIME_ZONE
201.1065 +    };
201.1066 +
201.1067 +    /**
201.1068 +     * Private member function that does the real date/time formatting.
201.1069 +     */
201.1070 +    private void subFormat(int patternCharIndex, int count,
201.1071 +                           FieldDelegate delegate, StringBuffer buffer,
201.1072 +                           boolean useDateFormatSymbols)
201.1073 +    {
201.1074 +        int     maxIntCount = Integer.MAX_VALUE;
201.1075 +        String  current = null;
201.1076 +        int     beginOffset = buffer.length();
201.1077 +
201.1078 +        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
201.1079 +        int value;
201.1080 +        if (field == CalendarBuilder.WEEK_YEAR) {
201.1081 +            if (calendar.isWeekDateSupported()) {
201.1082 +                value = calendar.getWeekYear();
201.1083 +            } else {
201.1084 +                // use calendar year 'y' instead
201.1085 +                patternCharIndex = PATTERN_YEAR;
201.1086 +                field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
201.1087 +                value = calendar.get(field);
201.1088 +            }
201.1089 +        } else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) {
201.1090 +            value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK));
201.1091 +        } else {
201.1092 +            value = calendar.get(field);
201.1093 +        }
201.1094 +
201.1095 +        int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
201.1096 +        if (!useDateFormatSymbols && field != CalendarBuilder.ISO_DAY_OF_WEEK) {
201.1097 +            current = calendar.getDisplayName(field, style, locale);
201.1098 +        }
201.1099 +
201.1100 +        // Note: zeroPaddingNumber() assumes that maxDigits is either
201.1101 +        // 2 or maxIntCount. If we make any changes to this,
201.1102 +        // zeroPaddingNumber() must be fixed.
201.1103 +
201.1104 +        switch (patternCharIndex) {
201.1105 +        case PATTERN_ERA: // 'G'
201.1106 +            if (useDateFormatSymbols) {
201.1107 +                String[] eras = formatData.getEras();
201.1108 +                if (value < eras.length)
201.1109 +                    current = eras[value];
201.1110 +            }
201.1111 +            if (current == null)
201.1112 +                current = "";
201.1113 +            break;
201.1114 +
201.1115 +        case PATTERN_WEEK_YEAR: // 'Y'
201.1116 +        case PATTERN_YEAR:      // 'y'
201.1117 +            if (calendar instanceof GregorianCalendar) {
201.1118 +                if (count != 2)
201.1119 +                    zeroPaddingNumber(value, count, maxIntCount, buffer);
201.1120 +                else // count == 2
201.1121 +                    zeroPaddingNumber(value, 2, 2, buffer); // clip 1996 to 96
201.1122 +            } else {
201.1123 +                if (current == null) {
201.1124 +                    zeroPaddingNumber(value, style == Calendar.LONG ? 1 : count,
201.1125 +                                      maxIntCount, buffer);
201.1126 +                }
201.1127 +            }
201.1128 +            break;
201.1129 +
201.1130 +        case PATTERN_MONTH: // 'M'
201.1131 +            if (useDateFormatSymbols) {
201.1132 +                String[] months;
201.1133 +                if (count >= 4) {
201.1134 +                    months = formatData.getMonths();
201.1135 +                    current = months[value];
201.1136 +                } else if (count == 3) {
201.1137 +                    months = formatData.getShortMonths();
201.1138 +                    current = months[value];
201.1139 +                }
201.1140 +            } else {
201.1141 +                if (count < 3) {
201.1142 +                    current = null;
201.1143 +                }
201.1144 +            }
201.1145 +            if (current == null) {
201.1146 +                zeroPaddingNumber(value+1, count, maxIntCount, buffer);
201.1147 +            }
201.1148 +            break;
201.1149 +
201.1150 +        case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
201.1151 +            if (current == null) {
201.1152 +                if (value == 0)
201.1153 +                    zeroPaddingNumber(calendar.getMaximum(Calendar.HOUR_OF_DAY)+1,
201.1154 +                                      count, maxIntCount, buffer);
201.1155 +                else
201.1156 +                    zeroPaddingNumber(value, count, maxIntCount, buffer);
201.1157 +            }
201.1158 +            break;
201.1159 +
201.1160 +        case PATTERN_DAY_OF_WEEK: // 'E'
201.1161 +            if (useDateFormatSymbols) {
201.1162 +                String[] weekdays;
201.1163 +                if (count >= 4) {
201.1164 +                    weekdays = formatData.getWeekdays();
201.1165 +                    current = weekdays[value];
201.1166 +                } else { // count < 4, use abbreviated form if exists
201.1167 +                    weekdays = formatData.getShortWeekdays();
201.1168 +                    current = weekdays[value];
201.1169 +                }
201.1170 +            }
201.1171 +            break;
201.1172 +
201.1173 +        case PATTERN_AM_PM:    // 'a'
201.1174 +            if (useDateFormatSymbols) {
201.1175 +                String[] ampm = formatData.getAmPmStrings();
201.1176 +                current = ampm[value];
201.1177 +            }
201.1178 +            break;
201.1179 +
201.1180 +        case PATTERN_HOUR1:    // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
201.1181 +            if (current == null) {
201.1182 +                if (value == 0)
201.1183 +                    zeroPaddingNumber(calendar.getLeastMaximum(Calendar.HOUR)+1,
201.1184 +                                      count, maxIntCount, buffer);
201.1185 +                else
201.1186 +                    zeroPaddingNumber(value, count, maxIntCount, buffer);
201.1187 +            }
201.1188 +            break;
201.1189 +
201.1190 +        case PATTERN_ZONE_NAME: // 'z'
201.1191 +            if (current == null) {
201.1192 +                if (formatData.locale == null || formatData.isZoneStringsSet) {
201.1193 +                    int zoneIndex =
201.1194 +                        formatData.getZoneIndex(calendar.getTimeZone().getID());
201.1195 +                    if (zoneIndex == -1) {
201.1196 +                        value = calendar.get(Calendar.ZONE_OFFSET) +
201.1197 +                            calendar.get(Calendar.DST_OFFSET);
201.1198 +//                        buffer.append(ZoneInfoFile.toCustomID(value));
201.1199 +                    } else {
201.1200 +                        int index = (calendar.get(Calendar.DST_OFFSET) == 0) ? 1: 3;
201.1201 +                        if (count < 4) {
201.1202 +                            // Use the short name
201.1203 +                            index++;
201.1204 +                        }
201.1205 +                        String[][] zoneStrings = formatData.getZoneStringsWrapper();
201.1206 +                        buffer.append(zoneStrings[zoneIndex][index]);
201.1207 +                    }
201.1208 +                } else {
201.1209 +                    TimeZone tz = calendar.getTimeZone();
201.1210 +                    boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
201.1211 +                    int tzstyle = (count < 4 ? TimeZone.SHORT : TimeZone.LONG);
201.1212 +                    buffer.append(tz.getDisplayName(daylight, tzstyle, formatData.locale));
201.1213 +                }
201.1214 +            }
201.1215 +            break;
201.1216 +
201.1217 +        case PATTERN_ZONE_VALUE: // 'Z' ("-/+hhmm" form)
201.1218 +            value = (calendar.get(Calendar.ZONE_OFFSET) +
201.1219 +                     calendar.get(Calendar.DST_OFFSET)) / 60000;
201.1220 +
201.1221 +            int width = 4;
201.1222 +            if (value >= 0) {
201.1223 +                buffer.append('+');
201.1224 +            } else {
201.1225 +                width++;
201.1226 +            }
201.1227 +
201.1228 +            int num = (value / 60) * 100 + (value % 60);
201.1229 +//            CalendarUtils.sprintf0d(buffer, num, width);
201.1230 +            break;
201.1231 +
201.1232 +        case PATTERN_ISO_ZONE:   // 'X'
201.1233 +            value = calendar.get(Calendar.ZONE_OFFSET)
201.1234 +                    + calendar.get(Calendar.DST_OFFSET);
201.1235 +
201.1236 +            if (value == 0) {
201.1237 +                buffer.append('Z');
201.1238 +                break;
201.1239 +            }
201.1240 +
201.1241 +            value /=  60000;
201.1242 +            if (value >= 0) {
201.1243 +                buffer.append('+');
201.1244 +            } else {
201.1245 +                buffer.append('-');
201.1246 +                value = -value;
201.1247 +            }
201.1248 +
201.1249 +//            CalendarUtils.sprintf0d(buffer, value / 60, 2);
201.1250 +            if (count == 1) {
201.1251 +                break;
201.1252 +            }
201.1253 +
201.1254 +            if (count == 3) {
201.1255 +                buffer.append(':');
201.1256 +            }
201.1257 +//            CalendarUtils.sprintf0d(buffer, value % 60, 2);
201.1258 +            break;
201.1259 +
201.1260 +        default:
201.1261 +     // case PATTERN_DAY_OF_MONTH:         // 'd'
201.1262 +     // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
201.1263 +     // case PATTERN_MINUTE:               // 'm'
201.1264 +     // case PATTERN_SECOND:               // 's'
201.1265 +     // case PATTERN_MILLISECOND:          // 'S'
201.1266 +     // case PATTERN_DAY_OF_YEAR:          // 'D'
201.1267 +     // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
201.1268 +     // case PATTERN_WEEK_OF_YEAR:         // 'w'
201.1269 +     // case PATTERN_WEEK_OF_MONTH:        // 'W'
201.1270 +     // case PATTERN_HOUR0:                // 'K' eg, 11PM + 1 hour =>> 0 AM
201.1271 +     // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' pseudo field, Monday = 1, ..., Sunday = 7
201.1272 +            if (current == null) {
201.1273 +                zeroPaddingNumber(value, count, maxIntCount, buffer);
201.1274 +            }
201.1275 +            break;
201.1276 +        } // switch (patternCharIndex)
201.1277 +
201.1278 +        if (current != null) {
201.1279 +            buffer.append(current);
201.1280 +        }
201.1281 +
201.1282 +        int fieldID = PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex];
201.1283 +        Field f = PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID[patternCharIndex];
201.1284 +
201.1285 +        delegate.formatted(fieldID, f, f, beginOffset, buffer.length(), buffer);
201.1286 +    }
201.1287 +
201.1288 +    /**
201.1289 +     * Formats a number with the specified minimum and maximum number of digits.
201.1290 +     */
201.1291 +    private final void zeroPaddingNumber(int value, int minDigits, int maxDigits, StringBuffer buffer)
201.1292 +    {
201.1293 +        // Optimization for 1, 2 and 4 digit numbers. This should
201.1294 +        // cover most cases of formatting date/time related items.
201.1295 +        // Note: This optimization code assumes that maxDigits is
201.1296 +        // either 2 or Integer.MAX_VALUE (maxIntCount in format()).
201.1297 +        try {
201.1298 +            if (zeroDigit == 0) {
201.1299 +                zeroDigit = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getZeroDigit();
201.1300 +            }
201.1301 +            if (value >= 0) {
201.1302 +                if (value < 100 && minDigits >= 1 && minDigits <= 2) {
201.1303 +                    if (value < 10) {
201.1304 +                        if (minDigits == 2) {
201.1305 +                            buffer.append(zeroDigit);
201.1306 +                        }
201.1307 +                        buffer.append((char)(zeroDigit + value));
201.1308 +                    } else {
201.1309 +                        buffer.append((char)(zeroDigit + value / 10));
201.1310 +                        buffer.append((char)(zeroDigit + value % 10));
201.1311 +                    }
201.1312 +                    return;
201.1313 +                } else if (value >= 1000 && value < 10000) {
201.1314 +                    if (minDigits == 4) {
201.1315 +                        buffer.append((char)(zeroDigit + value / 1000));
201.1316 +                        value %= 1000;
201.1317 +                        buffer.append((char)(zeroDigit + value / 100));
201.1318 +                        value %= 100;
201.1319 +                        buffer.append((char)(zeroDigit + value / 10));
201.1320 +                        buffer.append((char)(zeroDigit + value % 10));
201.1321 +                        return;
201.1322 +                    }
201.1323 +                    if (minDigits == 2 && maxDigits == 2) {
201.1324 +                        zeroPaddingNumber(value % 100, 2, 2, buffer);
201.1325 +                        return;
201.1326 +                    }
201.1327 +                }
201.1328 +            }
201.1329 +        } catch (Exception e) {
201.1330 +        }
201.1331 +
201.1332 +        numberFormat.setMinimumIntegerDigits(minDigits);
201.1333 +        numberFormat.setMaximumIntegerDigits(maxDigits);
201.1334 +        numberFormat.format((long)value, buffer, DontCareFieldPosition.INSTANCE);
201.1335 +    }
201.1336 +
201.1337 +
201.1338 +    /**
201.1339 +     * Parses text from a string to produce a <code>Date</code>.
201.1340 +     * <p>
201.1341 +     * The method attempts to parse text starting at the index given by
201.1342 +     * <code>pos</code>.
201.1343 +     * If parsing succeeds, then the index of <code>pos</code> is updated
201.1344 +     * to the index after the last character used (parsing does not necessarily
201.1345 +     * use all characters up to the end of the string), and the parsed
201.1346 +     * date is returned. The updated <code>pos</code> can be used to
201.1347 +     * indicate the starting point for the next call to this method.
201.1348 +     * If an error occurs, then the index of <code>pos</code> is not
201.1349 +     * changed, the error index of <code>pos</code> is set to the index of
201.1350 +     * the character where the error occurred, and null is returned.
201.1351 +     *
201.1352 +     * <p>This parsing operation uses the {@link DateFormat#calendar
201.1353 +     * calendar} to produce a {@code Date}. All of the {@code
201.1354 +     * calendar}'s date-time fields are {@linkplain Calendar#clear()
201.1355 +     * cleared} before parsing, and the {@code calendar}'s default
201.1356 +     * values of the date-time fields are used for any missing
201.1357 +     * date-time information. For example, the year value of the
201.1358 +     * parsed {@code Date} is 1970 with {@link GregorianCalendar} if
201.1359 +     * no year value is given from the parsing operation.  The {@code
201.1360 +     * TimeZone} value may be overwritten, depending on the given
201.1361 +     * pattern and the time zone value in {@code text}. Any {@code
201.1362 +     * TimeZone} value that has previously been set by a call to
201.1363 +     * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
201.1364 +     * to be restored for further operations.
201.1365 +     *
201.1366 +     * @param text  A <code>String</code>, part of which should be parsed.
201.1367 +     * @param pos   A <code>ParsePosition</code> object with index and error
201.1368 +     *              index information as described above.
201.1369 +     * @return A <code>Date</code> parsed from the string. In case of
201.1370 +     *         error, returns null.
201.1371 +     * @exception NullPointerException if <code>text</code> or <code>pos</code> is null.
201.1372 +     */
201.1373 +    public Date parse(String text, ParsePosition pos)
201.1374 +    {
201.1375 +        checkNegativeNumberExpression();
201.1376 +
201.1377 +        int start = pos.index;
201.1378 +        int oldStart = start;
201.1379 +        int textLength = text.length();
201.1380 +
201.1381 +        boolean[] ambiguousYear = {false};
201.1382 +
201.1383 +        CalendarBuilder calb = new CalendarBuilder();
201.1384 +
201.1385 +        for (int i = 0; i < compiledPattern.length; ) {
201.1386 +            int tag = compiledPattern[i] >>> 8;
201.1387 +            int count = compiledPattern[i++] & 0xff;
201.1388 +            if (count == 255) {
201.1389 +                count = compiledPattern[i++] << 16;
201.1390 +                count |= compiledPattern[i++];
201.1391 +            }
201.1392 +
201.1393 +            switch (tag) {
201.1394 +            case TAG_QUOTE_ASCII_CHAR:
201.1395 +                if (start >= textLength || text.charAt(start) != (char)count) {
201.1396 +                    pos.index = oldStart;
201.1397 +                    pos.errorIndex = start;
201.1398 +                    return null;
201.1399 +                }
201.1400 +                start++;
201.1401 +                break;
201.1402 +
201.1403 +            case TAG_QUOTE_CHARS:
201.1404 +                while (count-- > 0) {
201.1405 +                    if (start >= textLength || text.charAt(start) != compiledPattern[i++]) {
201.1406 +                        pos.index = oldStart;
201.1407 +                        pos.errorIndex = start;
201.1408 +                        return null;
201.1409 +                    }
201.1410 +                    start++;
201.1411 +                }
201.1412 +                break;
201.1413 +
201.1414 +            default:
201.1415 +                // Peek the next pattern to determine if we need to
201.1416 +                // obey the number of pattern letters for
201.1417 +                // parsing. It's required when parsing contiguous
201.1418 +                // digit text (e.g., "20010704") with a pattern which
201.1419 +                // has no delimiters between fields, like "yyyyMMdd".
201.1420 +                boolean obeyCount = false;
201.1421 +
201.1422 +                // In Arabic, a minus sign for a negative number is put after
201.1423 +                // the number. Even in another locale, a minus sign can be
201.1424 +                // put after a number using DateFormat.setNumberFormat().
201.1425 +                // If both the minus sign and the field-delimiter are '-',
201.1426 +                // subParse() needs to determine whether a '-' after a number
201.1427 +                // in the given text is a delimiter or is a minus sign for the
201.1428 +                // preceding number. We give subParse() a clue based on the
201.1429 +                // information in compiledPattern.
201.1430 +                boolean useFollowingMinusSignAsDelimiter = false;
201.1431 +
201.1432 +                if (i < compiledPattern.length) {
201.1433 +                    int nextTag = compiledPattern[i] >>> 8;
201.1434 +                    if (!(nextTag == TAG_QUOTE_ASCII_CHAR ||
201.1435 +                          nextTag == TAG_QUOTE_CHARS)) {
201.1436 +                        obeyCount = true;
201.1437 +                    }
201.1438 +
201.1439 +                    if (hasFollowingMinusSign &&
201.1440 +                        (nextTag == TAG_QUOTE_ASCII_CHAR ||
201.1441 +                         nextTag == TAG_QUOTE_CHARS)) {
201.1442 +                        int c;
201.1443 +                        if (nextTag == TAG_QUOTE_ASCII_CHAR) {
201.1444 +                            c = compiledPattern[i] & 0xff;
201.1445 +                        } else {
201.1446 +                            c = compiledPattern[i+1];
201.1447 +                        }
201.1448 +
201.1449 +                        if (c == minusSign) {
201.1450 +                            useFollowingMinusSignAsDelimiter = true;
201.1451 +                        }
201.1452 +                    }
201.1453 +                }
201.1454 +                start = subParse(text, start, tag, count, obeyCount,
201.1455 +                                 ambiguousYear, pos,
201.1456 +                                 useFollowingMinusSignAsDelimiter, calb);
201.1457 +                if (start < 0) {
201.1458 +                    pos.index = oldStart;
201.1459 +                    return null;
201.1460 +                }
201.1461 +            }
201.1462 +        }
201.1463 +
201.1464 +        // At this point the fields of Calendar have been set.  Calendar
201.1465 +        // will fill in default values for missing fields when the time
201.1466 +        // is computed.
201.1467 +
201.1468 +        pos.index = start;
201.1469 +
201.1470 +        Date parsedDate;
201.1471 +        try {
201.1472 +            parsedDate = calb.establish(calendar).getTime();
201.1473 +            // If the year value is ambiguous,
201.1474 +            // then the two-digit year == the default start year
201.1475 +            if (ambiguousYear[0]) {
201.1476 +                if (parsedDate.before(defaultCenturyStart)) {
201.1477 +                    parsedDate = calb.addYear(100).establish(calendar).getTime();
201.1478 +                }
201.1479 +            }
201.1480 +        }
201.1481 +        // An IllegalArgumentException will be thrown by Calendar.getTime()
201.1482 +        // if any fields are out of range, e.g., MONTH == 17.
201.1483 +        catch (IllegalArgumentException e) {
201.1484 +            pos.errorIndex = start;
201.1485 +            pos.index = oldStart;
201.1486 +            return null;
201.1487 +        }
201.1488 +
201.1489 +        return parsedDate;
201.1490 +    }
201.1491 +
201.1492 +    /**
201.1493 +     * Private code-size reduction function used by subParse.
201.1494 +     * @param text the time text being parsed.
201.1495 +     * @param start where to start parsing.
201.1496 +     * @param field the date field being parsed.
201.1497 +     * @param data the string array to parsed.
201.1498 +     * @return the new start position if matching succeeded; a negative number
201.1499 +     * indicating matching failure, otherwise.
201.1500 +     */
201.1501 +    private int matchString(String text, int start, int field, String[] data, CalendarBuilder calb)
201.1502 +    {
201.1503 +        int i = 0;
201.1504 +        int count = data.length;
201.1505 +
201.1506 +        if (field == Calendar.DAY_OF_WEEK) i = 1;
201.1507 +
201.1508 +        // There may be multiple strings in the data[] array which begin with
201.1509 +        // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
201.1510 +        // We keep track of the longest match, and return that.  Note that this
201.1511 +        // unfortunately requires us to test all array elements.
201.1512 +        int bestMatchLength = 0, bestMatch = -1;
201.1513 +        for (; i<count; ++i)
201.1514 +        {
201.1515 +            int length = data[i].length();
201.1516 +            // Always compare if we have no match yet; otherwise only compare
201.1517 +            // against potentially better matches (longer strings).
201.1518 +            if (length > bestMatchLength &&
201.1519 +                text.regionMatches(true, start, data[i], 0, length))
201.1520 +            {
201.1521 +                bestMatch = i;
201.1522 +                bestMatchLength = length;
201.1523 +            }
201.1524 +        }
201.1525 +        if (bestMatch >= 0)
201.1526 +        {
201.1527 +            calb.set(field, bestMatch);
201.1528 +            return start + bestMatchLength;
201.1529 +        }
201.1530 +        return -start;
201.1531 +    }
201.1532 +
201.1533 +    /**
201.1534 +     * Performs the same thing as matchString(String, int, int,
201.1535 +     * String[]). This method takes a Map<String, Integer> instead of
201.1536 +     * String[].
201.1537 +     */
201.1538 +    private int matchString(String text, int start, int field,
201.1539 +                            Map<String,Integer> data, CalendarBuilder calb) {
201.1540 +        if (data != null) {
201.1541 +            String bestMatch = null;
201.1542 +
201.1543 +            for (String name : data.keySet()) {
201.1544 +                int length = name.length();
201.1545 +                if (bestMatch == null || length > bestMatch.length()) {
201.1546 +                    if (text.regionMatches(true, start, name, 0, length)) {
201.1547 +                        bestMatch = name;
201.1548 +                    }
201.1549 +                }
201.1550 +            }
201.1551 +
201.1552 +            if (bestMatch != null) {
201.1553 +                calb.set(field, data.get(bestMatch));
201.1554 +                return start + bestMatch.length();
201.1555 +            }
201.1556 +        }
201.1557 +        return -start;
201.1558 +    }
201.1559 +
201.1560 +    private int matchZoneString(String text, int start, String[] zoneNames) {
201.1561 +        for (int i = 1; i <= 4; ++i) {
201.1562 +            // Checking long and short zones [1 & 2],
201.1563 +            // and long and short daylight [3 & 4].
201.1564 +            String zoneName = zoneNames[i];
201.1565 +            if (text.regionMatches(true, start,
201.1566 +                                   zoneName, 0, zoneName.length())) {
201.1567 +                return i;
201.1568 +            }
201.1569 +        }
201.1570 +        return -1;
201.1571 +    }
201.1572 +
201.1573 +    private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex,
201.1574 +                                   String[][] zoneStrings) {
201.1575 +        int index = standardIndex + 2;
201.1576 +        String zoneName  = zoneStrings[zoneIndex][index];
201.1577 +        if (text.regionMatches(true, start,
201.1578 +                               zoneName, 0, zoneName.length())) {
201.1579 +            return true;
201.1580 +        }
201.1581 +        return false;
201.1582 +    }
201.1583 +
201.1584 +    /**
201.1585 +     * find time zone 'text' matched zoneStrings and set to internal
201.1586 +     * calendar.
201.1587 +     */
201.1588 +    private int subParseZoneString(String text, int start, CalendarBuilder calb) {
201.1589 +        boolean useSameName = false; // true if standard and daylight time use the same abbreviation.
201.1590 +        TimeZone currentTimeZone = getTimeZone();
201.1591 +
201.1592 +        // At this point, check for named time zones by looking through
201.1593 +        // the locale data from the TimeZoneNames strings.
201.1594 +        // Want to be able to parse both short and long forms.
201.1595 +        int zoneIndex = formatData.getZoneIndex(currentTimeZone.getID());
201.1596 +        TimeZone tz = null;
201.1597 +        String[][] zoneStrings = formatData.getZoneStringsWrapper();
201.1598 +        String[] zoneNames = null;
201.1599 +        int nameIndex = 0;
201.1600 +        if (zoneIndex != -1) {
201.1601 +            zoneNames = zoneStrings[zoneIndex];
201.1602 +            if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
201.1603 +                if (nameIndex <= 2) {
201.1604 +                    // Check if the standard name (abbr) and the daylight name are the same.
201.1605 +                    useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
201.1606 +                }
201.1607 +                tz = TimeZone.getTimeZone(zoneNames[0]);
201.1608 +            }
201.1609 +        }
201.1610 +        if (tz == null) {
201.1611 +            zoneIndex = formatData.getZoneIndex(TimeZone.getDefault().getID());
201.1612 +            if (zoneIndex != -1) {
201.1613 +                zoneNames = zoneStrings[zoneIndex];
201.1614 +                if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
201.1615 +                    if (nameIndex <= 2) {
201.1616 +                        useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
201.1617 +                    }
201.1618 +                    tz = TimeZone.getTimeZone(zoneNames[0]);
201.1619 +                }
201.1620 +            }
201.1621 +        }
201.1622 +
201.1623 +        if (tz == null) {
201.1624 +            int len = zoneStrings.length;
201.1625 +            for (int i = 0; i < len; i++) {
201.1626 +                zoneNames = zoneStrings[i];
201.1627 +                if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
201.1628 +                    if (nameIndex <= 2) {
201.1629 +                        useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
201.1630 +                    }
201.1631 +                    tz = TimeZone.getTimeZone(zoneNames[0]);
201.1632 +                    break;
201.1633 +                }
201.1634 +            }
201.1635 +        }
201.1636 +        if (tz != null) { // Matched any ?
201.1637 +            if (!tz.equals(currentTimeZone)) {
201.1638 +                setTimeZone(tz);
201.1639 +            }
201.1640 +            // If the time zone matched uses the same name
201.1641 +            // (abbreviation) for both standard and daylight time,
201.1642 +            // let the time zone in the Calendar decide which one.
201.1643 +            //
201.1644 +            // Also if tz.getDSTSaving() returns 0 for DST, use tz to
201.1645 +            // determine the local time. (6645292)
201.1646 +            int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0;
201.1647 +            if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) {
201.1648 +                calb.set(Calendar.ZONE_OFFSET, tz.getRawOffset())
201.1649 +                    .set(Calendar.DST_OFFSET, dstAmount);
201.1650 +            }
201.1651 +            return (start + zoneNames[nameIndex].length());
201.1652 +        }
201.1653 +        return 0;
201.1654 +    }
201.1655 +
201.1656 +    /**
201.1657 +     * Parses numeric forms of time zone offset, such as "hh:mm", and
201.1658 +     * sets calb to the parsed value.
201.1659 +     *
201.1660 +     * @param text  the text to be parsed
201.1661 +     * @param start the character position to start parsing
201.1662 +     * @param sign  1: positive; -1: negative
201.1663 +     * @param count 0: 'Z' or "GMT+hh:mm" parsing; 1 - 3: the number of 'X's
201.1664 +     * @param colon true - colon required between hh and mm; false - no colon required
201.1665 +     * @param calb  a CalendarBuilder in which the parsed value is stored
201.1666 +     * @return updated parsed position, or its negative value to indicate a parsing error
201.1667 +     */
201.1668 +    private int subParseNumericZone(String text, int start, int sign, int count,
201.1669 +                                    boolean colon, CalendarBuilder calb) {
201.1670 +        int index = start;
201.1671 +
201.1672 +      parse:
201.1673 +        try {
201.1674 +            char c = text.charAt(index++);
201.1675 +            // Parse hh
201.1676 +            int hours;
201.1677 +            if (!isDigit(c)) {
201.1678 +                break parse;
201.1679 +            }
201.1680 +            hours = c - '0';
201.1681 +            c = text.charAt(index++);
201.1682 +            if (isDigit(c)) {
201.1683 +                hours = hours * 10 + (c - '0');
201.1684 +            } else {
201.1685 +                // If no colon in RFC 822 or 'X' (ISO), two digits are
201.1686 +                // required.
201.1687 +                if (count > 0 || !colon) {
201.1688 +                    break parse;
201.1689 +                }
201.1690 +                --index;
201.1691 +            }
201.1692 +            if (hours > 23) {
201.1693 +                break parse;
201.1694 +            }
201.1695 +            int minutes = 0;
201.1696 +            if (count != 1) {
201.1697 +                // Proceed with parsing mm
201.1698 +                c = text.charAt(index++);
201.1699 +                if (colon) {
201.1700 +                    if (c != ':') {
201.1701 +                        break parse;
201.1702 +                    }
201.1703 +                    c = text.charAt(index++);
201.1704 +                }
201.1705 +                if (!isDigit(c)) {
201.1706 +                    break parse;
201.1707 +                }
201.1708 +                minutes = c - '0';
201.1709 +                c = text.charAt(index++);
201.1710 +                if (!isDigit(c)) {
201.1711 +                    break parse;
201.1712 +                }
201.1713 +                minutes = minutes * 10 + (c - '0');
201.1714 +                if (minutes > 59) {
201.1715 +                    break parse;
201.1716 +                }
201.1717 +            }
201.1718 +            minutes += hours * 60;
201.1719 +            calb.set(Calendar.ZONE_OFFSET, minutes * MILLIS_PER_MINUTE * sign)
201.1720 +                .set(Calendar.DST_OFFSET, 0);
201.1721 +            return index;
201.1722 +        } catch (IndexOutOfBoundsException e) {
201.1723 +        }
201.1724 +        return  1 - index; // -(index - 1)
201.1725 +    }
201.1726 +
201.1727 +    private boolean isDigit(char c) {
201.1728 +        return c >= '0' && c <= '9';
201.1729 +    }
201.1730 +
201.1731 +    /**
201.1732 +     * Private member function that converts the parsed date strings into
201.1733 +     * timeFields. Returns -start (for ParsePosition) if failed.
201.1734 +     * @param text the time text to be parsed.
201.1735 +     * @param start where to start parsing.
201.1736 +     * @param ch the pattern character for the date field text to be parsed.
201.1737 +     * @param count the count of a pattern character.
201.1738 +     * @param obeyCount if true, then the next field directly abuts this one,
201.1739 +     * and we should use the count to know when to stop parsing.
201.1740 +     * @param ambiguousYear return parameter; upon return, if ambiguousYear[0]
201.1741 +     * is true, then a two-digit year was parsed and may need to be readjusted.
201.1742 +     * @param origPos origPos.errorIndex is used to return an error index
201.1743 +     * at which a parse error occurred, if matching failure occurs.
201.1744 +     * @return the new start position if matching succeeded; -1 indicating
201.1745 +     * matching failure, otherwise. In case matching failure occurred,
201.1746 +     * an error index is set to origPos.errorIndex.
201.1747 +     */
201.1748 +    private int subParse(String text, int start, int patternCharIndex, int count,
201.1749 +                         boolean obeyCount, boolean[] ambiguousYear,
201.1750 +                         ParsePosition origPos,
201.1751 +                         boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) {
201.1752 +        Number number = null;
201.1753 +        int value = 0;
201.1754 +        ParsePosition pos = new ParsePosition(0);
201.1755 +        pos.index = start;
201.1756 +        if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) {
201.1757 +            // use calendar year 'y' instead
201.1758 +            patternCharIndex = PATTERN_YEAR;
201.1759 +        }
201.1760 +        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
201.1761 +
201.1762 +        // If there are any spaces here, skip over them.  If we hit the end
201.1763 +        // of the string, then fail.
201.1764 +        for (;;) {
201.1765 +            if (pos.index >= text.length()) {
201.1766 +                origPos.errorIndex = start;
201.1767 +                return -1;
201.1768 +            }
201.1769 +            char c = text.charAt(pos.index);
201.1770 +            if (c != ' ' && c != '\t') break;
201.1771 +            ++pos.index;
201.1772 +        }
201.1773 +
201.1774 +      parsing:
201.1775 +        {
201.1776 +            // We handle a few special cases here where we need to parse
201.1777 +            // a number value.  We handle further, more generic cases below.  We need
201.1778 +            // to handle some of them here because some fields require extra processing on
201.1779 +            // the parsed value.
201.1780 +            if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
201.1781 +                patternCharIndex == PATTERN_HOUR1 ||
201.1782 +                (patternCharIndex == PATTERN_MONTH && count <= 2) ||
201.1783 +                patternCharIndex == PATTERN_YEAR ||
201.1784 +                patternCharIndex == PATTERN_WEEK_YEAR) {
201.1785 +                // It would be good to unify this with the obeyCount logic below,
201.1786 +                // but that's going to be difficult.
201.1787 +                if (obeyCount) {
201.1788 +                    if ((start+count) > text.length()) {
201.1789 +                        break parsing;
201.1790 +                    }
201.1791 +                    number = numberFormat.parse(text.substring(0, start+count), pos);
201.1792 +                } else {
201.1793 +                    number = numberFormat.parse(text, pos);
201.1794 +                }
201.1795 +                if (number == null) {
201.1796 +                    if (patternCharIndex != PATTERN_YEAR || calendar instanceof GregorianCalendar) {
201.1797 +                        break parsing;
201.1798 +                    }
201.1799 +                } else {
201.1800 +                    value = number.intValue();
201.1801 +
201.1802 +                    if (useFollowingMinusSignAsDelimiter && (value < 0) &&
201.1803 +                        (((pos.index < text.length()) &&
201.1804 +                         (text.charAt(pos.index) != minusSign)) ||
201.1805 +                         ((pos.index == text.length()) &&
201.1806 +                          (text.charAt(pos.index-1) == minusSign)))) {
201.1807 +                        value = -value;
201.1808 +                        pos.index--;
201.1809 +                    }
201.1810 +                }
201.1811 +            }
201.1812 +
201.1813 +            boolean useDateFormatSymbols = useDateFormatSymbols();
201.1814 +
201.1815 +            int index;
201.1816 +            switch (patternCharIndex) {
201.1817 +            case PATTERN_ERA: // 'G'
201.1818 +                if (useDateFormatSymbols) {
201.1819 +                    if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) {
201.1820 +                        return index;
201.1821 +                    }
201.1822 +                } else {
201.1823 +                    Map<String, Integer> map = calendar.getDisplayNames(field,
201.1824 +                                                                        Calendar.ALL_STYLES,
201.1825 +                                                                        locale);
201.1826 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
201.1827 +                        return index;
201.1828 +                    }
201.1829 +                }
201.1830 +                break parsing;
201.1831 +
201.1832 +            case PATTERN_WEEK_YEAR: // 'Y'
201.1833 +            case PATTERN_YEAR:      // 'y'
201.1834 +                if (!(calendar instanceof GregorianCalendar)) {
201.1835 +                    // calendar might have text representations for year values,
201.1836 +                    // such as "\u5143" in JapaneseImperialCalendar.
201.1837 +                    int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
201.1838 +                    Map<String, Integer> map = calendar.getDisplayNames(field, style, locale);
201.1839 +                    if (map != null) {
201.1840 +                        if ((index = matchString(text, start, field, map, calb)) > 0) {
201.1841 +                            return index;
201.1842 +                        }
201.1843 +                    }
201.1844 +                    calb.set(field, value);
201.1845 +                    return pos.index;
201.1846 +                }
201.1847 +
201.1848 +                // If there are 3 or more YEAR pattern characters, this indicates
201.1849 +                // that the year value is to be treated literally, without any
201.1850 +                // two-digit year adjustments (e.g., from "01" to 2001).  Otherwise
201.1851 +                // we made adjustments to place the 2-digit year in the proper
201.1852 +                // century, for parsed strings from "00" to "99".  Any other string
201.1853 +                // is treated literally:  "2250", "-1", "1", "002".
201.1854 +                if (count <= 2 && (pos.index - start) == 2
201.1855 +                    && Character.isDigit(text.charAt(start))
201.1856 +                    && Character.isDigit(text.charAt(start+1))) {
201.1857 +                    // Assume for example that the defaultCenturyStart is 6/18/1903.
201.1858 +                    // This means that two-digit years will be forced into the range
201.1859 +                    // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
201.1860 +                    // correspond to 2000, 2001, and 2002.  Years 04, 05, etc. correspond
201.1861 +                    // to 1904, 1905, etc.  If the year is 03, then it is 2003 if the
201.1862 +                    // other fields specify a date before 6/18, or 1903 if they specify a
201.1863 +                    // date afterwards.  As a result, 03 is an ambiguous year.  All other
201.1864 +                    // two-digit years are unambiguous.
201.1865 +                    int ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
201.1866 +                    ambiguousYear[0] = value == ambiguousTwoDigitYear;
201.1867 +                    value += (defaultCenturyStartYear/100)*100 +
201.1868 +                        (value < ambiguousTwoDigitYear ? 100 : 0);
201.1869 +                }
201.1870 +                calb.set(field, value);
201.1871 +                return pos.index;
201.1872 +
201.1873 +            case PATTERN_MONTH: // 'M'
201.1874 +                if (count <= 2) // i.e., M or MM.
201.1875 +                {
201.1876 +                    // Don't want to parse the month if it is a string
201.1877 +                    // while pattern uses numeric style: M or MM.
201.1878 +                    // [We computed 'value' above.]
201.1879 +                    calb.set(Calendar.MONTH, value - 1);
201.1880 +                    return pos.index;
201.1881 +                }
201.1882 +
201.1883 +                if (useDateFormatSymbols) {
201.1884 +                    // count >= 3 // i.e., MMM or MMMM
201.1885 +                    // Want to be able to parse both short and long forms.
201.1886 +                    // Try count == 4 first:
201.1887 +                    int newStart = 0;
201.1888 +                    if ((newStart = matchString(text, start, Calendar.MONTH,
201.1889 +                                                formatData.getMonths(), calb)) > 0) {
201.1890 +                        return newStart;
201.1891 +                    }
201.1892 +                    // count == 4 failed, now try count == 3
201.1893 +                    if ((index = matchString(text, start, Calendar.MONTH,
201.1894 +                                             formatData.getShortMonths(), calb)) > 0) {
201.1895 +                        return index;
201.1896 +                    }
201.1897 +                } else {
201.1898 +                    Map<String, Integer> map = calendar.getDisplayNames(field,
201.1899 +                                                                        Calendar.ALL_STYLES,
201.1900 +                                                                        locale);
201.1901 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
201.1902 +                        return index;
201.1903 +                    }
201.1904 +                }
201.1905 +                break parsing;
201.1906 +
201.1907 +            case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
201.1908 +                if (!isLenient()) {
201.1909 +                    // Validate the hour value in non-lenient
201.1910 +                    if (value < 1 || value > 24) {
201.1911 +                        break parsing;
201.1912 +                    }
201.1913 +                }
201.1914 +                // [We computed 'value' above.]
201.1915 +                if (value == calendar.getMaximum(Calendar.HOUR_OF_DAY)+1)
201.1916 +                    value = 0;
201.1917 +                calb.set(Calendar.HOUR_OF_DAY, value);
201.1918 +                return pos.index;
201.1919 +
201.1920 +            case PATTERN_DAY_OF_WEEK:  // 'E'
201.1921 +                {
201.1922 +                    if (useDateFormatSymbols) {
201.1923 +                        // Want to be able to parse both short and long forms.
201.1924 +                        // Try count == 4 (DDDD) first:
201.1925 +                        int newStart = 0;
201.1926 +                        if ((newStart=matchString(text, start, Calendar.DAY_OF_WEEK,
201.1927 +                                                  formatData.getWeekdays(), calb)) > 0) {
201.1928 +                            return newStart;
201.1929 +                        }
201.1930 +                        // DDDD failed, now try DDD
201.1931 +                        if ((index = matchString(text, start, Calendar.DAY_OF_WEEK,
201.1932 +                                                 formatData.getShortWeekdays(), calb)) > 0) {
201.1933 +                            return index;
201.1934 +                        }
201.1935 +                    } else {
201.1936 +                        int[] styles = { Calendar.LONG, Calendar.SHORT };
201.1937 +                        for (int style : styles) {
201.1938 +                            Map<String,Integer> map = calendar.getDisplayNames(field, style, locale);
201.1939 +                            if ((index = matchString(text, start, field, map, calb)) > 0) {
201.1940 +                                return index;
201.1941 +                            }
201.1942 +                        }
201.1943 +                    }
201.1944 +                }
201.1945 +                break parsing;
201.1946 +
201.1947 +            case PATTERN_AM_PM:    // 'a'
201.1948 +                if (useDateFormatSymbols) {
201.1949 +                    if ((index = matchString(text, start, Calendar.AM_PM,
201.1950 +                                             formatData.getAmPmStrings(), calb)) > 0) {
201.1951 +                        return index;
201.1952 +                    }
201.1953 +                } else {
201.1954 +                    Map<String,Integer> map = calendar.getDisplayNames(field, Calendar.ALL_STYLES, locale);
201.1955 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
201.1956 +                        return index;
201.1957 +                    }
201.1958 +                }
201.1959 +                break parsing;
201.1960 +
201.1961 +            case PATTERN_HOUR1: // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
201.1962 +                if (!isLenient()) {
201.1963 +                    // Validate the hour value in non-lenient
201.1964 +                    if (value < 1 || value > 12) {
201.1965 +                        break parsing;
201.1966 +                    }
201.1967 +                }
201.1968 +                // [We computed 'value' above.]
201.1969 +                if (value == calendar.getLeastMaximum(Calendar.HOUR)+1)
201.1970 +                    value = 0;
201.1971 +                calb.set(Calendar.HOUR, value);
201.1972 +                return pos.index;
201.1973 +
201.1974 +            case PATTERN_ZONE_NAME:  // 'z'
201.1975 +            case PATTERN_ZONE_VALUE: // 'Z'
201.1976 +                {
201.1977 +                    int sign = 0;
201.1978 +                    try {
201.1979 +                        char c = text.charAt(pos.index);
201.1980 +                        if (c == '+') {
201.1981 +                            sign = 1;
201.1982 +                        } else if (c == '-') {
201.1983 +                            sign = -1;
201.1984 +                        }
201.1985 +                        if (sign == 0) {
201.1986 +                            // Try parsing a custom time zone "GMT+hh:mm" or "GMT".
201.1987 +                            if ((c == 'G' || c == 'g')
201.1988 +                                && (text.length() - start) >= GMT.length()
201.1989 +                                && text.regionMatches(true, start, GMT, 0, GMT.length())) {
201.1990 +                                pos.index = start + GMT.length();
201.1991 +
201.1992 +                                if ((text.length() - pos.index) > 0) {
201.1993 +                                    c = text.charAt(pos.index);
201.1994 +                                    if (c == '+') {
201.1995 +                                        sign = 1;
201.1996 +                                    } else if (c == '-') {
201.1997 +                                        sign = -1;
201.1998 +                                    }
201.1999 +                                }
201.2000 +
201.2001 +                                if (sign == 0) {    /* "GMT" without offset */
201.2002 +                                    calb.set(Calendar.ZONE_OFFSET, 0)
201.2003 +                                        .set(Calendar.DST_OFFSET, 0);
201.2004 +                                    return pos.index;
201.2005 +                                }
201.2006 +
201.2007 +                                // Parse the rest as "hh:mm"
201.2008 +                                int i = subParseNumericZone(text, ++pos.index,
201.2009 +                                                            sign, 0, true, calb);
201.2010 +                                if (i > 0) {
201.2011 +                                    return i;
201.2012 +                                }
201.2013 +                                pos.index = -i;
201.2014 +                            } else {
201.2015 +                                // Try parsing the text as a time zone
201.2016 +                                // name or abbreviation.
201.2017 +                                int i = subParseZoneString(text, pos.index, calb);
201.2018 +                                if (i > 0) {
201.2019 +                                    return i;
201.2020 +                                }
201.2021 +                                pos.index = -i;
201.2022 +                            }
201.2023 +                        } else {
201.2024 +                            // Parse the rest as "hhmm" (RFC 822)
201.2025 +                            int i = subParseNumericZone(text, ++pos.index,
201.2026 +                                                        sign, 0, false, calb);
201.2027 +                            if (i > 0) {
201.2028 +                                return i;
201.2029 +                            }
201.2030 +                            pos.index = -i;
201.2031 +                        }
201.2032 +                    } catch (IndexOutOfBoundsException e) {
201.2033 +                    }
201.2034 +                }
201.2035 +                break parsing;
201.2036 +
201.2037 +            case PATTERN_ISO_ZONE:   // 'X'
201.2038 +                {
201.2039 +                    if ((text.length() - pos.index) <= 0) {
201.2040 +                        break parsing;
201.2041 +                    }
201.2042 +
201.2043 +                    int sign = 0;
201.2044 +                    char c = text.charAt(pos.index);
201.2045 +                    if (c == 'Z') {
201.2046 +                        calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
201.2047 +                        return ++pos.index;
201.2048 +                    }
201.2049 +
201.2050 +                    // parse text as "+/-hh[[:]mm]" based on count
201.2051 +                    if (c == '+') {
201.2052 +                        sign = 1;
201.2053 +                    } else if (c == '-') {
201.2054 +                        sign = -1;
201.2055 +                    } else {
201.2056 +                        ++pos.index;
201.2057 +                        break parsing;
201.2058 +                    }
201.2059 +                    int i = subParseNumericZone(text, ++pos.index, sign, count,
201.2060 +                                                count == 3, calb);
201.2061 +                    if (i > 0) {
201.2062 +                        return i;
201.2063 +                    }
201.2064 +                    pos.index = -i;
201.2065 +                }
201.2066 +                break parsing;
201.2067 +
201.2068 +            default:
201.2069 +         // case PATTERN_DAY_OF_MONTH:         // 'd'
201.2070 +         // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
201.2071 +         // case PATTERN_MINUTE:               // 'm'
201.2072 +         // case PATTERN_SECOND:               // 's'
201.2073 +         // case PATTERN_MILLISECOND:          // 'S'
201.2074 +         // case PATTERN_DAY_OF_YEAR:          // 'D'
201.2075 +         // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
201.2076 +         // case PATTERN_WEEK_OF_YEAR:         // 'w'
201.2077 +         // case PATTERN_WEEK_OF_MONTH:        // 'W'
201.2078 +         // case PATTERN_HOUR0:                // 'K' 0-based.  eg, 11PM + 1 hour =>> 0 AM
201.2079 +         // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' (pseudo field);
201.2080 +
201.2081 +                // Handle "generic" fields
201.2082 +                if (obeyCount) {
201.2083 +                    if ((start+count) > text.length()) {
201.2084 +                        break parsing;
201.2085 +                    }
201.2086 +                    number = numberFormat.parse(text.substring(0, start+count), pos);
201.2087 +                } else {
201.2088 +                    number = numberFormat.parse(text, pos);
201.2089 +                }
201.2090 +                if (number != null) {
201.2091 +                    value = number.intValue();
201.2092 +
201.2093 +                    if (useFollowingMinusSignAsDelimiter && (value < 0) &&
201.2094 +                        (((pos.index < text.length()) &&
201.2095 +                         (text.charAt(pos.index) != minusSign)) ||
201.2096 +                         ((pos.index == text.length()) &&
201.2097 +                          (text.charAt(pos.index-1) == minusSign)))) {
201.2098 +                        value = -value;
201.2099 +                        pos.index--;
201.2100 +                    }
201.2101 +
201.2102 +                    calb.set(field, value);
201.2103 +                    return pos.index;
201.2104 +                }
201.2105 +                break parsing;
201.2106 +            }
201.2107 +        }
201.2108 +
201.2109 +        // Parsing failed.
201.2110 +        origPos.errorIndex = pos.index;
201.2111 +        return -1;
201.2112 +    }
201.2113 +
201.2114 +    private final String getCalendarName() {
201.2115 +        return calendar.getClass().getName();
201.2116 +    }
201.2117 +
201.2118 +    private boolean useDateFormatSymbols() {
201.2119 +        if (useDateFormatSymbols) {
201.2120 +            return true;
201.2121 +        }
201.2122 +        return isGregorianCalendar() || locale == null;
201.2123 +    }
201.2124 +
201.2125 +    private boolean isGregorianCalendar() {
201.2126 +        return "java.util.GregorianCalendar".equals(getCalendarName());
201.2127 +    }
201.2128 +
201.2129 +    /**
201.2130 +     * Translates a pattern, mapping each character in the from string to the
201.2131 +     * corresponding character in the to string.
201.2132 +     *
201.2133 +     * @exception IllegalArgumentException if the given pattern is invalid
201.2134 +     */
201.2135 +    private String translatePattern(String pattern, String from, String to) {
201.2136 +        StringBuilder result = new StringBuilder();
201.2137 +        boolean inQuote = false;
201.2138 +        for (int i = 0; i < pattern.length(); ++i) {
201.2139 +            char c = pattern.charAt(i);
201.2140 +            if (inQuote) {
201.2141 +                if (c == '\'')
201.2142 +                    inQuote = false;
201.2143 +            }
201.2144 +            else {
201.2145 +                if (c == '\'')
201.2146 +                    inQuote = true;
201.2147 +                else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
201.2148 +                    int ci = from.indexOf(c);
201.2149 +                    if (ci >= 0) {
201.2150 +                        // patternChars is longer than localPatternChars due
201.2151 +                        // to serialization compatibility. The pattern letters
201.2152 +                        // unsupported by localPatternChars pass through.
201.2153 +                        if (ci < to.length()) {
201.2154 +                            c = to.charAt(ci);
201.2155 +                        }
201.2156 +                    } else {
201.2157 +                        throw new IllegalArgumentException("Illegal pattern " +
201.2158 +                                                           " character '" +
201.2159 +                                                           c + "'");
201.2160 +                    }
201.2161 +                }
201.2162 +            }
201.2163 +            result.append(c);
201.2164 +        }
201.2165 +        if (inQuote)
201.2166 +            throw new IllegalArgumentException("Unfinished quote in pattern");
201.2167 +        return result.toString();
201.2168 +    }
201.2169 +
201.2170 +    /**
201.2171 +     * Returns a pattern string describing this date format.
201.2172 +     *
201.2173 +     * @return a pattern string describing this date format.
201.2174 +     */
201.2175 +    public String toPattern() {
201.2176 +        return pattern;
201.2177 +    }
201.2178 +
201.2179 +    /**
201.2180 +     * Returns a localized pattern string describing this date format.
201.2181 +     *
201.2182 +     * @return a localized pattern string describing this date format.
201.2183 +     */
201.2184 +    public String toLocalizedPattern() {
201.2185 +        return translatePattern(pattern,
201.2186 +                                DateFormatSymbols.patternChars,
201.2187 +                                formatData.getLocalPatternChars());
201.2188 +    }
201.2189 +
201.2190 +    /**
201.2191 +     * Applies the given pattern string to this date format.
201.2192 +     *
201.2193 +     * @param pattern the new date and time pattern for this date format
201.2194 +     * @exception NullPointerException if the given pattern is null
201.2195 +     * @exception IllegalArgumentException if the given pattern is invalid
201.2196 +     */
201.2197 +    public void applyPattern(String pattern)
201.2198 +    {
201.2199 +        compiledPattern = compile(pattern);
201.2200 +        this.pattern = pattern;
201.2201 +    }
201.2202 +
201.2203 +    /**
201.2204 +     * Applies the given localized pattern string to this date format.
201.2205 +     *
201.2206 +     * @param pattern a String to be mapped to the new date and time format
201.2207 +     *        pattern for this format
201.2208 +     * @exception NullPointerException if the given pattern is null
201.2209 +     * @exception IllegalArgumentException if the given pattern is invalid
201.2210 +     */
201.2211 +    public void applyLocalizedPattern(String pattern) {
201.2212 +         String p = translatePattern(pattern,
201.2213 +                                     formatData.getLocalPatternChars(),
201.2214 +                                     DateFormatSymbols.patternChars);
201.2215 +         compiledPattern = compile(p);
201.2216 +         this.pattern = p;
201.2217 +    }
201.2218 +
201.2219 +    /**
201.2220 +     * Gets a copy of the date and time format symbols of this date format.
201.2221 +     *
201.2222 +     * @return the date and time format symbols of this date format
201.2223 +     * @see #setDateFormatSymbols
201.2224 +     */
201.2225 +    public DateFormatSymbols getDateFormatSymbols()
201.2226 +    {
201.2227 +        return (DateFormatSymbols)formatData.clone();
201.2228 +    }
201.2229 +
201.2230 +    /**
201.2231 +     * Sets the date and time format symbols of this date format.
201.2232 +     *
201.2233 +     * @param newFormatSymbols the new date and time format symbols
201.2234 +     * @exception NullPointerException if the given newFormatSymbols is null
201.2235 +     * @see #getDateFormatSymbols
201.2236 +     */
201.2237 +    public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols)
201.2238 +    {
201.2239 +        this.formatData = (DateFormatSymbols)newFormatSymbols.clone();
201.2240 +        useDateFormatSymbols = true;
201.2241 +    }
201.2242 +
201.2243 +    /**
201.2244 +     * Creates a copy of this <code>SimpleDateFormat</code>. This also
201.2245 +     * clones the format's date format symbols.
201.2246 +     *
201.2247 +     * @return a clone of this <code>SimpleDateFormat</code>
201.2248 +     */
201.2249 +    public Object clone() {
201.2250 +        SimpleDateFormat other = (SimpleDateFormat) super.clone();
201.2251 +        other.formatData = (DateFormatSymbols) formatData.clone();
201.2252 +        return other;
201.2253 +    }
201.2254 +
201.2255 +    /**
201.2256 +     * Returns the hash code value for this <code>SimpleDateFormat</code> object.
201.2257 +     *
201.2258 +     * @return the hash code value for this <code>SimpleDateFormat</code> object.
201.2259 +     */
201.2260 +    public int hashCode()
201.2261 +    {
201.2262 +        return pattern.hashCode();
201.2263 +        // just enough fields for a reasonable distribution
201.2264 +    }
201.2265 +
201.2266 +    /**
201.2267 +     * Compares the given object with this <code>SimpleDateFormat</code> for
201.2268 +     * equality.
201.2269 +     *
201.2270 +     * @return true if the given object is equal to this
201.2271 +     * <code>SimpleDateFormat</code>
201.2272 +     */
201.2273 +    public boolean equals(Object obj)
201.2274 +    {
201.2275 +        if (!super.equals(obj)) return false; // super does class check
201.2276 +        SimpleDateFormat that = (SimpleDateFormat) obj;
201.2277 +        return (pattern.equals(that.pattern)
201.2278 +                && formatData.equals(that.formatData));
201.2279 +    }
201.2280 +
201.2281 +    /**
201.2282 +     * After reading an object from the input stream, the format
201.2283 +     * pattern in the object is verified.
201.2284 +     * <p>
201.2285 +     * @exception InvalidObjectException if the pattern is invalid
201.2286 +     */
201.2287 +    private void readObject(ObjectInputStream stream)
201.2288 +                         throws IOException, ClassNotFoundException {
201.2289 +        stream.defaultReadObject();
201.2290 +
201.2291 +        try {
201.2292 +            compiledPattern = compile(pattern);
201.2293 +        } catch (Exception e) {
201.2294 +            throw new InvalidObjectException("invalid pattern");
201.2295 +        }
201.2296 +
201.2297 +        if (serialVersionOnStream < 1) {
201.2298 +            // didn't have defaultCenturyStart field
201.2299 +            initializeDefaultCentury();
201.2300 +        }
201.2301 +        else {
201.2302 +            // fill in dependent transient field
201.2303 +            parseAmbiguousDatesAsAfter(defaultCenturyStart);
201.2304 +        }
201.2305 +        serialVersionOnStream = currentSerialVersion;
201.2306 +
201.2307 +        // If the deserialized object has a SimpleTimeZone, try
201.2308 +        // to replace it with a ZoneInfo equivalent in order to
201.2309 +        // be compatible with the SimpleTimeZone-based
201.2310 +        // implementation as much as possible.
201.2311 +        TimeZone tz = getTimeZone();
201.2312 +        if (tz instanceof SimpleTimeZone) {
201.2313 +            String id = tz.getID();
201.2314 +            TimeZone zi = TimeZone.getTimeZone(id);
201.2315 +            if (zi != null && zi.hasSameRules(tz) && zi.getID().equals(id)) {
201.2316 +                setTimeZone(zi);
201.2317 +            }
201.2318 +        }
201.2319 +    }
201.2320 +
201.2321 +    /**
201.2322 +     * Analyze the negative subpattern of DecimalFormat and set/update values
201.2323 +     * as necessary.
201.2324 +     */
201.2325 +    private void checkNegativeNumberExpression() {
201.2326 +        if ((numberFormat instanceof DecimalFormat) &&
201.2327 +            !numberFormat.equals(originalNumberFormat)) {
201.2328 +            String numberPattern = ((DecimalFormat)numberFormat).toPattern();
201.2329 +            if (!numberPattern.equals(originalNumberPattern)) {
201.2330 +                hasFollowingMinusSign = false;
201.2331 +
201.2332 +                int separatorIndex = numberPattern.indexOf(';');
201.2333 +                // If the negative subpattern is not absent, we have to analayze
201.2334 +                // it in order to check if it has a following minus sign.
201.2335 +                if (separatorIndex > -1) {
201.2336 +                    int minusIndex = numberPattern.indexOf('-', separatorIndex);
201.2337 +                    if ((minusIndex > numberPattern.lastIndexOf('0')) &&
201.2338 +                        (minusIndex > numberPattern.lastIndexOf('#'))) {
201.2339 +                        hasFollowingMinusSign = true;
201.2340 +                        minusSign = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getMinusSign();
201.2341 +                    }
201.2342 +                }
201.2343 +                originalNumberPattern = numberPattern;
201.2344 +            }
201.2345 +            originalNumberFormat = numberFormat;
201.2346 +        }
201.2347 +    }
201.2348 +
201.2349 +    private static final class GregorianCalendar extends Calendar {
201.2350 +        @Override
201.2351 +        protected void computeTime() {
201.2352 +        }
201.2353 +
201.2354 +        @Override
201.2355 +        protected void computeFields() {
201.2356 +        }
201.2357 +
201.2358 +        @Override
201.2359 +        public void add(int field, int amount) {
201.2360 +        }
201.2361 +
201.2362 +        @Override
201.2363 +        public void roll(int field, boolean up) {
201.2364 +        }
201.2365 +
201.2366 +        @Override
201.2367 +        public int getMinimum(int field) {
201.2368 +            return 0;
201.2369 +        }
201.2370 +
201.2371 +        @Override
201.2372 +        public int getMaximum(int field) {
201.2373 +            return 0;
201.2374 +        }
201.2375 +
201.2376 +        @Override
201.2377 +        public int getGreatestMinimum(int field) {
201.2378 +            return 0;
201.2379 +        }
201.2380 +
201.2381 +        @Override
201.2382 +        public int getLeastMaximum(int field) {
201.2383 +            return 0;
201.2384 +        }
201.2385 +    }
201.2386 +}
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/rt/emul/compact/src/main/java/java/util/BitSet.java	Wed Apr 30 15:04:10 2014 +0200
   202.3 @@ -0,0 +1,1188 @@
   202.4 +/*
   202.5 + * Copyright (c) 1995, 2007, Oracle and/or its affiliates. All rights reserved.
   202.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   202.7 + *
   202.8 + * This code is free software; you can redistribute it and/or modify it
   202.9 + * under the terms of the GNU General Public License version 2 only, as
  202.10 + * published by the Free Software Foundation.  Oracle designates this
  202.11 + * particular file as subject to the "Classpath" exception as provided
  202.12 + * by Oracle in the LICENSE file that accompanied this code.
  202.13 + *
  202.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  202.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  202.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  202.17 + * version 2 for more details (a copy is included in the LICENSE file that
  202.18 + * accompanied this code).
  202.19 + *
  202.20 + * You should have received a copy of the GNU General Public License version
  202.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  202.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  202.23 + *
  202.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  202.25 + * or visit www.oracle.com if you need additional information or have any
  202.26 + * questions.
  202.27 + */
  202.28 +
  202.29 +package java.util;
  202.30 +
  202.31 +import java.io.*;
  202.32 +
  202.33 +/**
  202.34 + * This class implements a vector of bits that grows as needed. Each
  202.35 + * component of the bit set has a {@code boolean} value. The
  202.36 + * bits of a {@code BitSet} are indexed by nonnegative integers.
  202.37 + * Individual indexed bits can be examined, set, or cleared. One
  202.38 + * {@code BitSet} may be used to modify the contents of another
  202.39 + * {@code BitSet} through logical AND, logical inclusive OR, and
  202.40 + * logical exclusive OR operations.
  202.41 + *
  202.42 + * <p>By default, all bits in the set initially have the value
  202.43 + * {@code false}.
  202.44 + *
  202.45 + * <p>Every bit set has a current size, which is the number of bits
  202.46 + * of space currently in use by the bit set. Note that the size is
  202.47 + * related to the implementation of a bit set, so it may change with
  202.48 + * implementation. The length of a bit set relates to logical length
  202.49 + * of a bit set and is defined independently of implementation.
  202.50 + *
  202.51 + * <p>Unless otherwise noted, passing a null parameter to any of the
  202.52 + * methods in a {@code BitSet} will result in a
  202.53 + * {@code NullPointerException}.
  202.54 + *
  202.55 + * <p>A {@code BitSet} is not safe for multithreaded use without
  202.56 + * external synchronization.
  202.57 + *
  202.58 + * @author  Arthur van Hoff
  202.59 + * @author  Michael McCloskey
  202.60 + * @author  Martin Buchholz
  202.61 + * @since   JDK1.0
  202.62 + */
  202.63 +public class BitSet implements Cloneable, java.io.Serializable {
  202.64 +    /*
  202.65 +     * BitSets are packed into arrays of "words."  Currently a word is
  202.66 +     * a long, which consists of 64 bits, requiring 6 address bits.
  202.67 +     * The choice of word size is determined purely by performance concerns.
  202.68 +     */
  202.69 +    private final static int ADDRESS_BITS_PER_WORD = 6;
  202.70 +    private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
  202.71 +    private final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;
  202.72 +
  202.73 +    /* Used to shift left or right for a partial word mask */
  202.74 +    private static final long WORD_MASK = 0xffffffffffffffffL;
  202.75 +
  202.76 +    /**
  202.77 +     * @serialField bits long[]
  202.78 +     *
  202.79 +     * The bits in this BitSet.  The ith bit is stored in bits[i/64] at
  202.80 +     * bit position i % 64 (where bit position 0 refers to the least
  202.81 +     * significant bit and 63 refers to the most significant bit).
  202.82 +     */
  202.83 +    private static final ObjectStreamField[] serialPersistentFields = {
  202.84 +        new ObjectStreamField("bits", long[].class),
  202.85 +    };
  202.86 +
  202.87 +    /**
  202.88 +     * The internal field corresponding to the serialField "bits".
  202.89 +     */
  202.90 +    private long[] words;
  202.91 +
  202.92 +    /**
  202.93 +     * The number of words in the logical size of this BitSet.
  202.94 +     */
  202.95 +    private transient int wordsInUse = 0;
  202.96 +
  202.97 +    /**
  202.98 +     * Whether the size of "words" is user-specified.  If so, we assume
  202.99 +     * the user knows what he's doing and try harder to preserve it.
 202.100 +     */
 202.101 +    private transient boolean sizeIsSticky = false;
 202.102 +
 202.103 +    /* use serialVersionUID from JDK 1.0.2 for interoperability */
 202.104 +    private static final long serialVersionUID = 7997698588986878753L;
 202.105 +
 202.106 +    /**
 202.107 +     * Given a bit index, return word index containing it.
 202.108 +     */
 202.109 +    private static int wordIndex(int bitIndex) {
 202.110 +        return bitIndex >> ADDRESS_BITS_PER_WORD;
 202.111 +    }
 202.112 +
 202.113 +    /**
 202.114 +     * Every public method must preserve these invariants.
 202.115 +     */
 202.116 +    private void checkInvariants() {
 202.117 +        assert(wordsInUse == 0 || words[wordsInUse - 1] != 0);
 202.118 +        assert(wordsInUse >= 0 && wordsInUse <= words.length);
 202.119 +        assert(wordsInUse == words.length || words[wordsInUse] == 0);
 202.120 +    }
 202.121 +
 202.122 +    /**
 202.123 +     * Sets the field wordsInUse to the logical size in words of the bit set.
 202.124 +     * WARNING:This method assumes that the number of words actually in use is
 202.125 +     * less than or equal to the current value of wordsInUse!
 202.126 +     */
 202.127 +    private void recalculateWordsInUse() {
 202.128 +        // Traverse the bitset until a used word is found
 202.129 +        int i;
 202.130 +        for (i = wordsInUse-1; i >= 0; i--)
 202.131 +            if (words[i] != 0)
 202.132 +                break;
 202.133 +
 202.134 +        wordsInUse = i+1; // The new logical size
 202.135 +    }
 202.136 +
 202.137 +    /**
 202.138 +     * Creates a new bit set. All bits are initially {@code false}.
 202.139 +     */
 202.140 +    public BitSet() {
 202.141 +        initWords(BITS_PER_WORD);
 202.142 +        sizeIsSticky = false;
 202.143 +    }
 202.144 +
 202.145 +    /**
 202.146 +     * Creates a bit set whose initial size is large enough to explicitly
 202.147 +     * represent bits with indices in the range {@code 0} through
 202.148 +     * {@code nbits-1}. All bits are initially {@code false}.
 202.149 +     *
 202.150 +     * @param  nbits the initial size of the bit set
 202.151 +     * @throws NegativeArraySizeException if the specified initial size
 202.152 +     *         is negative
 202.153 +     */
 202.154 +    public BitSet(int nbits) {
 202.155 +        // nbits can't be negative; size 0 is OK
 202.156 +        if (nbits < 0)
 202.157 +            throw new NegativeArraySizeException("nbits < 0: " + nbits);
 202.158 +
 202.159 +        initWords(nbits);
 202.160 +        sizeIsSticky = true;
 202.161 +    }
 202.162 +
 202.163 +    private void initWords(int nbits) {
 202.164 +        words = new long[wordIndex(nbits-1) + 1];
 202.165 +    }
 202.166 +
 202.167 +    /**
 202.168 +     * Creates a bit set using words as the internal representation.
 202.169 +     * The last word (if there is one) must be non-zero.
 202.170 +     */
 202.171 +    private BitSet(long[] words) {
 202.172 +        this.words = words;
 202.173 +        this.wordsInUse = words.length;
 202.174 +        checkInvariants();
 202.175 +    }
 202.176 +
 202.177 +    /**
 202.178 +     * Returns a new bit set containing all the bits in the given long array.
 202.179 +     *
 202.180 +     * <p>More precisely,
 202.181 +     * <br>{@code BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}
 202.182 +     * <br>for all {@code n < 64 * longs.length}.
 202.183 +     *
 202.184 +     * <p>This method is equivalent to
 202.185 +     * {@code BitSet.valueOf(LongBuffer.wrap(longs))}.
 202.186 +     *
 202.187 +     * @param longs a long array containing a little-endian representation
 202.188 +     *        of a sequence of bits to be used as the initial bits of the
 202.189 +     *        new bit set
 202.190 +     * @since 1.7
 202.191 +     */
 202.192 +    public static BitSet valueOf(long[] longs) {
 202.193 +        int n;
 202.194 +        for (n = longs.length; n > 0 && longs[n - 1] == 0; n--)
 202.195 +            ;
 202.196 +        return new BitSet(Arrays.copyOf(longs, n));
 202.197 +    }
 202.198 +
 202.199 +    /**
 202.200 +     * Returns a new bit set containing all the bits in the given long
 202.201 +     * buffer between its position and limit.
 202.202 +     *
 202.203 +     * <p>More precisely,
 202.204 +     * <br>{@code BitSet.valueOf(lb).get(n) == ((lb.get(lb.position()+n/64) & (1L<<(n%64))) != 0)}
 202.205 +     * <br>for all {@code n < 64 * lb.remaining()}.
 202.206 +     *
 202.207 +     * <p>The long buffer is not modified by this method, and no
 202.208 +     * reference to the buffer is retained by the bit set.
 202.209 +     *
 202.210 +     * @param lb a long buffer containing a little-endian representation
 202.211 +     *        of a sequence of bits between its position and limit, to be
 202.212 +     *        used as the initial bits of the new bit set
 202.213 +     * @since 1.7
 202.214 +     */
 202.215 +//    public static BitSet valueOf(LongBuffer lb) {
 202.216 +//        lb = lb.slice();
 202.217 +//        int n;
 202.218 +//        for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--)
 202.219 +//            ;
 202.220 +//        long[] words = new long[n];
 202.221 +//        lb.get(words);
 202.222 +//        return new BitSet(words);
 202.223 +//    }
 202.224 +
 202.225 +    /**
 202.226 +     * Returns a new bit set containing all the bits in the given byte array.
 202.227 +     *
 202.228 +     * <p>More precisely,
 202.229 +     * <br>{@code BitSet.valueOf(bytes).get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}
 202.230 +     * <br>for all {@code n <  8 * bytes.length}.
 202.231 +     *
 202.232 +     * <p>This method is equivalent to
 202.233 +     * {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}.
 202.234 +     *
 202.235 +     * @param bytes a byte array containing a little-endian
 202.236 +     *        representation of a sequence of bits to be used as the
 202.237 +     *        initial bits of the new bit set
 202.238 +     * @since 1.7
 202.239 +     */
 202.240 +//    public static BitSet valueOf(byte[] bytes) {
 202.241 +//        return BitSet.valueOf(ByteBuffer.wrap(bytes));
 202.242 +//    }
 202.243 +
 202.244 +    /**
 202.245 +     * Returns a new bit set containing all the bits in the given byte
 202.246 +     * buffer between its position and limit.
 202.247 +     *
 202.248 +     * <p>More precisely,
 202.249 +     * <br>{@code BitSet.valueOf(bb).get(n) == ((bb.get(bb.position()+n/8) & (1<<(n%8))) != 0)}
 202.250 +     * <br>for all {@code n < 8 * bb.remaining()}.
 202.251 +     *
 202.252 +     * <p>The byte buffer is not modified by this method, and no
 202.253 +     * reference to the buffer is retained by the bit set.
 202.254 +     *
 202.255 +     * @param bb a byte buffer containing a little-endian representation
 202.256 +     *        of a sequence of bits between its position and limit, to be
 202.257 +     *        used as the initial bits of the new bit set
 202.258 +     * @since 1.7
 202.259 +     */
 202.260 +//    public static BitSet valueOf(ByteBuffer bb) {
 202.261 +//        bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
 202.262 +//        int n;
 202.263 +//        for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--)
 202.264 +//            ;
 202.265 +//        long[] words = new long[(n + 7) / 8];
 202.266 +//        bb.limit(n);
 202.267 +//        int i = 0;
 202.268 +//        while (bb.remaining() >= 8)
 202.269 +//            words[i++] = bb.getLong();
 202.270 +//        for (int remaining = bb.remaining(), j = 0; j < remaining; j++)
 202.271 +//            words[i] |= (bb.get() & 0xffL) << (8 * j);
 202.272 +//        return new BitSet(words);
 202.273 +//    }
 202.274 +
 202.275 +    /**
 202.276 +     * Returns a new byte array containing all the bits in this bit set.
 202.277 +     *
 202.278 +     * <p>More precisely, if
 202.279 +     * <br>{@code byte[] bytes = s.toByteArray();}
 202.280 +     * <br>then {@code bytes.length == (s.length()+7)/8} and
 202.281 +     * <br>{@code s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)}
 202.282 +     * <br>for all {@code n < 8 * bytes.length}.
 202.283 +     *
 202.284 +     * @return a byte array containing a little-endian representation
 202.285 +     *         of all the bits in this bit set
 202.286 +     * @since 1.7
 202.287 +    */
 202.288 +//    public byte[] toByteArray() {
 202.289 +//        int n = wordsInUse;
 202.290 +//        if (n == 0)
 202.291 +//            return new byte[0];
 202.292 +//        int len = 8 * (n-1);
 202.293 +//        for (long x = words[n - 1]; x != 0; x >>>= 8)
 202.294 +//            len++;
 202.295 +//        byte[] bytes = new byte[len];
 202.296 +//        ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
 202.297 +//        for (int i = 0; i < n - 1; i++)
 202.298 +//            bb.putLong(words[i]);
 202.299 +//        for (long x = words[n - 1]; x != 0; x >>>= 8)
 202.300 +//            bb.put((byte) (x & 0xff));
 202.301 +//        return bytes;
 202.302 +//    }
 202.303 +
 202.304 +    /**
 202.305 +     * Returns a new long array containing all the bits in this bit set.
 202.306 +     *
 202.307 +     * <p>More precisely, if
 202.308 +     * <br>{@code long[] longs = s.toLongArray();}
 202.309 +     * <br>then {@code longs.length == (s.length()+63)/64} and
 202.310 +     * <br>{@code s.get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)}
 202.311 +     * <br>for all {@code n < 64 * longs.length}.
 202.312 +     *
 202.313 +     * @return a long array containing a little-endian representation
 202.314 +     *         of all the bits in this bit set
 202.315 +     * @since 1.7
 202.316 +    */
 202.317 +    public long[] toLongArray() {
 202.318 +        return Arrays.copyOf(words, wordsInUse);
 202.319 +    }
 202.320 +
 202.321 +    /**
 202.322 +     * Ensures that the BitSet can hold enough words.
 202.323 +     * @param wordsRequired the minimum acceptable number of words.
 202.324 +     */
 202.325 +    private void ensureCapacity(int wordsRequired) {
 202.326 +        if (words.length < wordsRequired) {
 202.327 +            // Allocate larger of doubled size or required size
 202.328 +            int request = Math.max(2 * words.length, wordsRequired);
 202.329 +            words = Arrays.copyOf(words, request);
 202.330 +            sizeIsSticky = false;
 202.331 +        }
 202.332 +    }
 202.333 +
 202.334 +    /**
 202.335 +     * Ensures that the BitSet can accommodate a given wordIndex,
 202.336 +     * temporarily violating the invariants.  The caller must
 202.337 +     * restore the invariants before returning to the user,
 202.338 +     * possibly using recalculateWordsInUse().
 202.339 +     * @param wordIndex the index to be accommodated.
 202.340 +     */
 202.341 +    private void expandTo(int wordIndex) {
 202.342 +        int wordsRequired = wordIndex+1;
 202.343 +        if (wordsInUse < wordsRequired) {
 202.344 +            ensureCapacity(wordsRequired);
 202.345 +            wordsInUse = wordsRequired;
 202.346 +        }
 202.347 +    }
 202.348 +
 202.349 +    /**
 202.350 +     * Checks that fromIndex ... toIndex is a valid range of bit indices.
 202.351 +     */
 202.352 +    private static void checkRange(int fromIndex, int toIndex) {
 202.353 +        if (fromIndex < 0)
 202.354 +            throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
 202.355 +        if (toIndex < 0)
 202.356 +            throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
 202.357 +        if (fromIndex > toIndex)
 202.358 +            throw new IndexOutOfBoundsException("fromIndex: " + fromIndex +
 202.359 +                                                " > toIndex: " + toIndex);
 202.360 +    }
 202.361 +
 202.362 +    /**
 202.363 +     * Sets the bit at the specified index to the complement of its
 202.364 +     * current value.
 202.365 +     *
 202.366 +     * @param  bitIndex the index of the bit to flip
 202.367 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.368 +     * @since  1.4
 202.369 +     */
 202.370 +    public void flip(int bitIndex) {
 202.371 +        if (bitIndex < 0)
 202.372 +            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
 202.373 +
 202.374 +        int wordIndex = wordIndex(bitIndex);
 202.375 +        expandTo(wordIndex);
 202.376 +
 202.377 +        words[wordIndex] ^= (1L << bitIndex);
 202.378 +
 202.379 +        recalculateWordsInUse();
 202.380 +        checkInvariants();
 202.381 +    }
 202.382 +
 202.383 +    /**
 202.384 +     * Sets each bit from the specified {@code fromIndex} (inclusive) to the
 202.385 +     * specified {@code toIndex} (exclusive) to the complement of its current
 202.386 +     * value.
 202.387 +     *
 202.388 +     * @param  fromIndex index of the first bit to flip
 202.389 +     * @param  toIndex index after the last bit to flip
 202.390 +     * @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
 202.391 +     *         or {@code toIndex} is negative, or {@code fromIndex} is
 202.392 +     *         larger than {@code toIndex}
 202.393 +     * @since  1.4
 202.394 +     */
 202.395 +    public void flip(int fromIndex, int toIndex) {
 202.396 +        checkRange(fromIndex, toIndex);
 202.397 +
 202.398 +        if (fromIndex == toIndex)
 202.399 +            return;
 202.400 +
 202.401 +        int startWordIndex = wordIndex(fromIndex);
 202.402 +        int endWordIndex   = wordIndex(toIndex - 1);
 202.403 +        expandTo(endWordIndex);
 202.404 +
 202.405 +        long firstWordMask = WORD_MASK << fromIndex;
 202.406 +        long lastWordMask  = WORD_MASK >>> -toIndex;
 202.407 +        if (startWordIndex == endWordIndex) {
 202.408 +            // Case 1: One word
 202.409 +            words[startWordIndex] ^= (firstWordMask & lastWordMask);
 202.410 +        } else {
 202.411 +            // Case 2: Multiple words
 202.412 +            // Handle first word
 202.413 +            words[startWordIndex] ^= firstWordMask;
 202.414 +
 202.415 +            // Handle intermediate words, if any
 202.416 +            for (int i = startWordIndex+1; i < endWordIndex; i++)
 202.417 +                words[i] ^= WORD_MASK;
 202.418 +
 202.419 +            // Handle last word
 202.420 +            words[endWordIndex] ^= lastWordMask;
 202.421 +        }
 202.422 +
 202.423 +        recalculateWordsInUse();
 202.424 +        checkInvariants();
 202.425 +    }
 202.426 +
 202.427 +    /**
 202.428 +     * Sets the bit at the specified index to {@code true}.
 202.429 +     *
 202.430 +     * @param  bitIndex a bit index
 202.431 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.432 +     * @since  JDK1.0
 202.433 +     */
 202.434 +    public void set(int bitIndex) {
 202.435 +        if (bitIndex < 0)
 202.436 +            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
 202.437 +
 202.438 +        int wordIndex = wordIndex(bitIndex);
 202.439 +        expandTo(wordIndex);
 202.440 +
 202.441 +        words[wordIndex] |= (1L << bitIndex); // Restores invariants
 202.442 +
 202.443 +        checkInvariants();
 202.444 +    }
 202.445 +
 202.446 +    /**
 202.447 +     * Sets the bit at the specified index to the specified value.
 202.448 +     *
 202.449 +     * @param  bitIndex a bit index
 202.450 +     * @param  value a boolean value to set
 202.451 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.452 +     * @since  1.4
 202.453 +     */
 202.454 +    public void set(int bitIndex, boolean value) {
 202.455 +        if (value)
 202.456 +            set(bitIndex);
 202.457 +        else
 202.458 +            clear(bitIndex);
 202.459 +    }
 202.460 +
 202.461 +    /**
 202.462 +     * Sets the bits from the specified {@code fromIndex} (inclusive) to the
 202.463 +     * specified {@code toIndex} (exclusive) to {@code true}.
 202.464 +     *
 202.465 +     * @param  fromIndex index of the first bit to be set
 202.466 +     * @param  toIndex index after the last bit to be set
 202.467 +     * @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
 202.468 +     *         or {@code toIndex} is negative, or {@code fromIndex} is
 202.469 +     *         larger than {@code toIndex}
 202.470 +     * @since  1.4
 202.471 +     */
 202.472 +    public void set(int fromIndex, int toIndex) {
 202.473 +        checkRange(fromIndex, toIndex);
 202.474 +
 202.475 +        if (fromIndex == toIndex)
 202.476 +            return;
 202.477 +
 202.478 +        // Increase capacity if necessary
 202.479 +        int startWordIndex = wordIndex(fromIndex);
 202.480 +        int endWordIndex   = wordIndex(toIndex - 1);
 202.481 +        expandTo(endWordIndex);
 202.482 +
 202.483 +        long firstWordMask = WORD_MASK << fromIndex;
 202.484 +        long lastWordMask  = WORD_MASK >>> -toIndex;
 202.485 +        if (startWordIndex == endWordIndex) {
 202.486 +            // Case 1: One word
 202.487 +            words[startWordIndex] |= (firstWordMask & lastWordMask);
 202.488 +        } else {
 202.489 +            // Case 2: Multiple words
 202.490 +            // Handle first word
 202.491 +            words[startWordIndex] |= firstWordMask;
 202.492 +
 202.493 +            // Handle intermediate words, if any
 202.494 +            for (int i = startWordIndex+1; i < endWordIndex; i++)
 202.495 +                words[i] = WORD_MASK;
 202.496 +
 202.497 +            // Handle last word (restores invariants)
 202.498 +            words[endWordIndex] |= lastWordMask;
 202.499 +        }
 202.500 +
 202.501 +        checkInvariants();
 202.502 +    }
 202.503 +
 202.504 +    /**
 202.505 +     * Sets the bits from the specified {@code fromIndex} (inclusive) to the
 202.506 +     * specified {@code toIndex} (exclusive) to the specified value.
 202.507 +     *
 202.508 +     * @param  fromIndex index of the first bit to be set
 202.509 +     * @param  toIndex index after the last bit to be set
 202.510 +     * @param  value value to set the selected bits to
 202.511 +     * @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
 202.512 +     *         or {@code toIndex} is negative, or {@code fromIndex} is
 202.513 +     *         larger than {@code toIndex}
 202.514 +     * @since  1.4
 202.515 +     */
 202.516 +    public void set(int fromIndex, int toIndex, boolean value) {
 202.517 +        if (value)
 202.518 +            set(fromIndex, toIndex);
 202.519 +        else
 202.520 +            clear(fromIndex, toIndex);
 202.521 +    }
 202.522 +
 202.523 +    /**
 202.524 +     * Sets the bit specified by the index to {@code false}.
 202.525 +     *
 202.526 +     * @param  bitIndex the index of the bit to be cleared
 202.527 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.528 +     * @since  JDK1.0
 202.529 +     */
 202.530 +    public void clear(int bitIndex) {
 202.531 +        if (bitIndex < 0)
 202.532 +            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
 202.533 +
 202.534 +        int wordIndex = wordIndex(bitIndex);
 202.535 +        if (wordIndex >= wordsInUse)
 202.536 +            return;
 202.537 +
 202.538 +        words[wordIndex] &= ~(1L << bitIndex);
 202.539 +
 202.540 +        recalculateWordsInUse();
 202.541 +        checkInvariants();
 202.542 +    }
 202.543 +
 202.544 +    /**
 202.545 +     * Sets the bits from the specified {@code fromIndex} (inclusive) to the
 202.546 +     * specified {@code toIndex} (exclusive) to {@code false}.
 202.547 +     *
 202.548 +     * @param  fromIndex index of the first bit to be cleared
 202.549 +     * @param  toIndex index after the last bit to be cleared
 202.550 +     * @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
 202.551 +     *         or {@code toIndex} is negative, or {@code fromIndex} is
 202.552 +     *         larger than {@code toIndex}
 202.553 +     * @since  1.4
 202.554 +     */
 202.555 +    public void clear(int fromIndex, int toIndex) {
 202.556 +        checkRange(fromIndex, toIndex);
 202.557 +
 202.558 +        if (fromIndex == toIndex)
 202.559 +            return;
 202.560 +
 202.561 +        int startWordIndex = wordIndex(fromIndex);
 202.562 +        if (startWordIndex >= wordsInUse)
 202.563 +            return;
 202.564 +
 202.565 +        int endWordIndex = wordIndex(toIndex - 1);
 202.566 +        if (endWordIndex >= wordsInUse) {
 202.567 +            toIndex = length();
 202.568 +            endWordIndex = wordsInUse - 1;
 202.569 +        }
 202.570 +
 202.571 +        long firstWordMask = WORD_MASK << fromIndex;
 202.572 +        long lastWordMask  = WORD_MASK >>> -toIndex;
 202.573 +        if (startWordIndex == endWordIndex) {
 202.574 +            // Case 1: One word
 202.575 +            words[startWordIndex] &= ~(firstWordMask & lastWordMask);
 202.576 +        } else {
 202.577 +            // Case 2: Multiple words
 202.578 +            // Handle first word
 202.579 +            words[startWordIndex] &= ~firstWordMask;
 202.580 +
 202.581 +            // Handle intermediate words, if any
 202.582 +            for (int i = startWordIndex+1; i < endWordIndex; i++)
 202.583 +                words[i] = 0;
 202.584 +
 202.585 +            // Handle last word
 202.586 +            words[endWordIndex] &= ~lastWordMask;
 202.587 +        }
 202.588 +
 202.589 +        recalculateWordsInUse();
 202.590 +        checkInvariants();
 202.591 +    }
 202.592 +
 202.593 +    /**
 202.594 +     * Sets all of the bits in this BitSet to {@code false}.
 202.595 +     *
 202.596 +     * @since 1.4
 202.597 +     */
 202.598 +    public void clear() {
 202.599 +        while (wordsInUse > 0)
 202.600 +            words[--wordsInUse] = 0;
 202.601 +    }
 202.602 +
 202.603 +    /**
 202.604 +     * Returns the value of the bit with the specified index. The value
 202.605 +     * is {@code true} if the bit with the index {@code bitIndex}
 202.606 +     * is currently set in this {@code BitSet}; otherwise, the result
 202.607 +     * is {@code false}.
 202.608 +     *
 202.609 +     * @param  bitIndex   the bit index
 202.610 +     * @return the value of the bit with the specified index
 202.611 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.612 +     */
 202.613 +    public boolean get(int bitIndex) {
 202.614 +        if (bitIndex < 0)
 202.615 +            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);
 202.616 +
 202.617 +        checkInvariants();
 202.618 +
 202.619 +        int wordIndex = wordIndex(bitIndex);
 202.620 +        return (wordIndex < wordsInUse)
 202.621 +            && ((words[wordIndex] & (1L << bitIndex)) != 0);
 202.622 +    }
 202.623 +
 202.624 +    /**
 202.625 +     * Returns a new {@code BitSet} composed of bits from this {@code BitSet}
 202.626 +     * from {@code fromIndex} (inclusive) to {@code toIndex} (exclusive).
 202.627 +     *
 202.628 +     * @param  fromIndex index of the first bit to include
 202.629 +     * @param  toIndex index after the last bit to include
 202.630 +     * @return a new {@code BitSet} from a range of this {@code BitSet}
 202.631 +     * @throws IndexOutOfBoundsException if {@code fromIndex} is negative,
 202.632 +     *         or {@code toIndex} is negative, or {@code fromIndex} is
 202.633 +     *         larger than {@code toIndex}
 202.634 +     * @since  1.4
 202.635 +     */
 202.636 +    public BitSet get(int fromIndex, int toIndex) {
 202.637 +        checkRange(fromIndex, toIndex);
 202.638 +
 202.639 +        checkInvariants();
 202.640 +
 202.641 +        int len = length();
 202.642 +
 202.643 +        // If no set bits in range return empty bitset
 202.644 +        if (len <= fromIndex || fromIndex == toIndex)
 202.645 +            return new BitSet(0);
 202.646 +
 202.647 +        // An optimization
 202.648 +        if (toIndex > len)
 202.649 +            toIndex = len;
 202.650 +
 202.651 +        BitSet result = new BitSet(toIndex - fromIndex);
 202.652 +        int targetWords = wordIndex(toIndex - fromIndex - 1) + 1;
 202.653 +        int sourceIndex = wordIndex(fromIndex);
 202.654 +        boolean wordAligned = ((fromIndex & BIT_INDEX_MASK) == 0);
 202.655 +
 202.656 +        // Process all words but the last word
 202.657 +        for (int i = 0; i < targetWords - 1; i++, sourceIndex++)
 202.658 +            result.words[i] = wordAligned ? words[sourceIndex] :
 202.659 +                (words[sourceIndex] >>> fromIndex) |
 202.660 +                (words[sourceIndex+1] << -fromIndex);
 202.661 +
 202.662 +        // Process the last word
 202.663 +        long lastWordMask = WORD_MASK >>> -toIndex;
 202.664 +        result.words[targetWords - 1] =
 202.665 +            ((toIndex-1) & BIT_INDEX_MASK) < (fromIndex & BIT_INDEX_MASK)
 202.666 +            ? /* straddles source words */
 202.667 +            ((words[sourceIndex] >>> fromIndex) |
 202.668 +             (words[sourceIndex+1] & lastWordMask) << -fromIndex)
 202.669 +            :
 202.670 +            ((words[sourceIndex] & lastWordMask) >>> fromIndex);
 202.671 +
 202.672 +        // Set wordsInUse correctly
 202.673 +        result.wordsInUse = targetWords;
 202.674 +        result.recalculateWordsInUse();
 202.675 +        result.checkInvariants();
 202.676 +
 202.677 +        return result;
 202.678 +    }
 202.679 +
 202.680 +    /**
 202.681 +     * Returns the index of the first bit that is set to {@code true}
 202.682 +     * that occurs on or after the specified starting index. If no such
 202.683 +     * bit exists then {@code -1} is returned.
 202.684 +     *
 202.685 +     * <p>To iterate over the {@code true} bits in a {@code BitSet},
 202.686 +     * use the following loop:
 202.687 +     *
 202.688 +     *  <pre> {@code
 202.689 +     * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
 202.690 +     *     // operate on index i here
 202.691 +     * }}</pre>
 202.692 +     *
 202.693 +     * @param  fromIndex the index to start checking from (inclusive)
 202.694 +     * @return the index of the next set bit, or {@code -1} if there
 202.695 +     *         is no such bit
 202.696 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.697 +     * @since  1.4
 202.698 +     */
 202.699 +    public int nextSetBit(int fromIndex) {
 202.700 +        if (fromIndex < 0)
 202.701 +            throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
 202.702 +
 202.703 +        checkInvariants();
 202.704 +
 202.705 +        int u = wordIndex(fromIndex);
 202.706 +        if (u >= wordsInUse)
 202.707 +            return -1;
 202.708 +
 202.709 +        long word = words[u] & (WORD_MASK << fromIndex);
 202.710 +
 202.711 +        while (true) {
 202.712 +            if (word != 0)
 202.713 +                return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
 202.714 +            if (++u == wordsInUse)
 202.715 +                return -1;
 202.716 +            word = words[u];
 202.717 +        }
 202.718 +    }
 202.719 +
 202.720 +    /**
 202.721 +     * Returns the index of the first bit that is set to {@code false}
 202.722 +     * that occurs on or after the specified starting index.
 202.723 +     *
 202.724 +     * @param  fromIndex the index to start checking from (inclusive)
 202.725 +     * @return the index of the next clear bit
 202.726 +     * @throws IndexOutOfBoundsException if the specified index is negative
 202.727 +     * @since  1.4
 202.728 +     */
 202.729 +    public int nextClearBit(int fromIndex) {
 202.730 +        // Neither spec nor implementation handle bitsets of maximal length.
 202.731 +        // See 4816253.
 202.732 +        if (fromIndex < 0)
 202.733 +            throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
 202.734 +
 202.735 +        checkInvariants();
 202.736 +
 202.737 +        int u = wordIndex(fromIndex);
 202.738 +        if (u >= wordsInUse)
 202.739 +            return fromIndex;
 202.740 +
 202.741 +        long word = ~words[u] & (WORD_MASK << fromIndex);
 202.742 +
 202.743 +        while (true) {
 202.744 +            if (word != 0)
 202.745 +                return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
 202.746 +            if (++u == wordsInUse)
 202.747 +                return wordsInUse * BITS_PER_WORD;
 202.748 +            word = ~words[u];
 202.749 +        }
 202.750 +    }
 202.751 +
 202.752 +    /**
 202.753 +     * Returns the index of the nearest bit that is set to {@code true}
 202.754 +     * that occurs on or before the specified starting index.
 202.755 +     * If no such bit exists, or if {@code -1} is given as the
 202.756 +     * starting index, then {@code -1} is returned.
 202.757 +     *
 202.758 +     * <p>To iterate over the {@code true} bits in a {@code BitSet},
 202.759 +     * use the following loop:
 202.760 +     *
 202.761 +     *  <pre> {@code
 202.762 +     * for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) {
 202.763 +     *     // operate on index i here
 202.764 +     * }}</pre>
 202.765 +     *
 202.766 +     * @param  fromIndex the index to start checking from (inclusive)
 202.767 +     * @return the index of the previous set bit, or {@code -1} if there
 202.768 +     *         is no such bit
 202.769 +     * @throws IndexOutOfBoundsException if the specified index is less
 202.770 +     *         than {@code -1}
 202.771 +     * @since  1.7
 202.772 +     */
 202.773 +    public int previousSetBit(int fromIndex) {
 202.774 +        if (fromIndex < 0) {
 202.775 +            if (fromIndex == -1)
 202.776 +                return -1;
 202.777 +            throw new IndexOutOfBoundsException(
 202.778 +                "fromIndex < -1: " + fromIndex);
 202.779 +        }
 202.780 +
 202.781 +        checkInvariants();
 202.782 +
 202.783 +        int u = wordIndex(fromIndex);
 202.784 +        if (u >= wordsInUse)
 202.785 +            return length() - 1;
 202.786 +
 202.787 +        long word = words[u] & (WORD_MASK >>> -(fromIndex+1));
 202.788 +
 202.789 +        while (true) {
 202.790 +            if (word != 0)
 202.791 +                return (u+1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word);
 202.792 +            if (u-- == 0)
 202.793 +                return -1;
 202.794 +            word = words[u];
 202.795 +        }
 202.796 +    }
 202.797 +
 202.798 +    /**
 202.799 +     * Returns the index of the nearest bit that is set to {@code false}
 202.800 +     * that occurs on or before the specified starting index.
 202.801 +     * If no such bit exists, or if {@code -1} is given as the
 202.802 +     * starting index, then {@code -1} is returned.
 202.803 +     *
 202.804 +     * @param  fromIndex the index to start checking from (inclusive)
 202.805 +     * @return the index of the previous clear bit, or {@code -1} if there
 202.806 +     *         is no such bit
 202.807 +     * @throws IndexOutOfBoundsException if the specified index is less
 202.808 +     *         than {@code -1}
 202.809 +     * @since  1.7
 202.810 +     */
 202.811 +    public int previousClearBit(int fromIndex) {
 202.812 +        if (fromIndex < 0) {
 202.813 +            if (fromIndex == -1)
 202.814 +                return -1;
 202.815 +            throw new IndexOutOfBoundsException(
 202.816 +                "fromIndex < -1: " + fromIndex);
 202.817 +        }
 202.818 +
 202.819 +        checkInvariants();
 202.820 +
 202.821 +        int u = wordIndex(fromIndex);
 202.822 +        if (u >= wordsInUse)
 202.823 +            return fromIndex;
 202.824 +
 202.825 +        long word = ~words[u] & (WORD_MASK >>> -(fromIndex+1));
 202.826 +
 202.827 +        while (true) {
 202.828 +            if (word != 0)
 202.829 +                return (u+1) * BITS_PER_WORD -1 - Long.numberOfLeadingZeros(word);
 202.830 +            if (u-- == 0)
 202.831 +                return -1;
 202.832 +            word = ~words[u];
 202.833 +        }
 202.834 +    }
 202.835 +
 202.836 +    /**
 202.837 +     * Returns the "logical size" of this {@code BitSet}: the index of
 202.838 +     * the highest set bit in the {@code BitSet} plus one. Returns zero
 202.839 +     * if the {@code BitSet} contains no set bits.
 202.840 +     *
 202.841 +     * @return the logical size of this {@code BitSet}
 202.842 +     * @since  1.2
 202.843 +     */
 202.844 +    public int length() {
 202.845 +        if (wordsInUse == 0)
 202.846 +            return 0;
 202.847 +
 202.848 +        return BITS_PER_WORD * (wordsInUse - 1) +
 202.849 +            (BITS_PER_WORD - Long.numberOfLeadingZeros(words[wordsInUse - 1]));
 202.850 +    }
 202.851 +
 202.852 +    /**
 202.853 +     * Returns true if this {@code BitSet} contains no bits that are set
 202.854 +     * to {@code true}.
 202.855 +     *
 202.856 +     * @return boolean indicating whether this {@code BitSet} is empty
 202.857 +     * @since  1.4
 202.858 +     */
 202.859 +    public boolean isEmpty() {
 202.860 +        return wordsInUse == 0;
 202.861 +    }
 202.862 +
 202.863 +    /**
 202.864 +     * Returns true if the specified {@code BitSet} has any bits set to
 202.865 +     * {@code true} that are also set to {@code true} in this {@code BitSet}.
 202.866 +     *
 202.867 +     * @param  set {@code BitSet} to intersect with
 202.868 +     * @return boolean indicating whether this {@code BitSet} intersects
 202.869 +     *         the specified {@code BitSet}
 202.870 +     * @since  1.4
 202.871 +     */
 202.872 +    public boolean intersects(BitSet set) {
 202.873 +        for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)
 202.874 +            if ((words[i] & set.words[i]) != 0)
 202.875 +                return true;
 202.876 +        return false;
 202.877 +    }
 202.878 +
 202.879 +    /**
 202.880 +     * Returns the number of bits set to {@code true} in this {@code BitSet}.
 202.881 +     *
 202.882 +     * @return the number of bits set to {@code true} in this {@code BitSet}
 202.883 +     * @since  1.4
 202.884 +     */
 202.885 +    public int cardinality() {
 202.886 +        int sum = 0;
 202.887 +        for (int i = 0; i < wordsInUse; i++)
 202.888 +            sum += Long.bitCount(words[i]);
 202.889 +        return sum;
 202.890 +    }
 202.891 +
 202.892 +    /**
 202.893 +     * Performs a logical <b>AND</b> of this target bit set with the
 202.894 +     * argument bit set. This bit set is modified so that each bit in it
 202.895 +     * has the value {@code true} if and only if it both initially
 202.896 +     * had the value {@code true} and the corresponding bit in the
 202.897 +     * bit set argument also had the value {@code true}.
 202.898 +     *
 202.899 +     * @param set a bit set
 202.900 +     */
 202.901 +    public void and(BitSet set) {
 202.902 +        if (this == set)
 202.903 +            return;
 202.904 +
 202.905 +        while (wordsInUse > set.wordsInUse)
 202.906 +            words[--wordsInUse] = 0;
 202.907 +
 202.908 +        // Perform logical AND on words in common
 202.909 +        for (int i = 0; i < wordsInUse; i++)
 202.910 +            words[i] &= set.words[i];
 202.911 +
 202.912 +        recalculateWordsInUse();
 202.913 +        checkInvariants();
 202.914 +    }
 202.915 +
 202.916 +    /**
 202.917 +     * Performs a logical <b>OR</b> of this bit set with the bit set
 202.918 +     * argument. This bit set is modified so that a bit in it has the
 202.919 +     * value {@code true} if and only if it either already had the
 202.920 +     * value {@code true} or the corresponding bit in the bit set
 202.921 +     * argument has the value {@code true}.
 202.922 +     *
 202.923 +     * @param set a bit set
 202.924 +     */
 202.925 +    public void or(BitSet set) {
 202.926 +        if (this == set)
 202.927 +            return;
 202.928 +
 202.929 +        int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);
 202.930 +
 202.931 +        if (wordsInUse < set.wordsInUse) {
 202.932 +            ensureCapacity(set.wordsInUse);
 202.933 +            wordsInUse = set.wordsInUse;
 202.934 +        }
 202.935 +
 202.936 +        // Perform logical OR on words in common
 202.937 +        for (int i = 0; i < wordsInCommon; i++)
 202.938 +            words[i] |= set.words[i];
 202.939 +
 202.940 +        // Copy any remaining words
 202.941 +        if (wordsInCommon < set.wordsInUse)
 202.942 +            System.arraycopy(set.words, wordsInCommon,
 202.943 +                             words, wordsInCommon,
 202.944 +                             wordsInUse - wordsInCommon);
 202.945 +
 202.946 +        // recalculateWordsInUse() is unnecessary
 202.947 +        checkInvariants();
 202.948 +    }
 202.949 +
 202.950 +    /**
 202.951 +     * Performs a logical <b>XOR</b> of this bit set with the bit set
 202.952 +     * argument. This bit set is modified so that a bit in it has the
 202.953 +     * value {@code true} if and only if one of the following
 202.954 +     * statements holds:
 202.955 +     * <ul>
 202.956 +     * <li>The bit initially has the value {@code true}, and the
 202.957 +     *     corresponding bit in the argument has the value {@code false}.
 202.958 +     * <li>The bit initially has the value {@code false}, and the
 202.959 +     *     corresponding bit in the argument has the value {@code true}.
 202.960 +     * </ul>
 202.961 +     *
 202.962 +     * @param  set a bit set
 202.963 +     */
 202.964 +    public void xor(BitSet set) {
 202.965 +        int wordsInCommon = Math.min(wordsInUse, set.wordsInUse);
 202.966 +
 202.967 +        if (wordsInUse < set.wordsInUse) {
 202.968 +            ensureCapacity(set.wordsInUse);
 202.969 +            wordsInUse = set.wordsInUse;
 202.970 +        }
 202.971 +
 202.972 +        // Perform logical XOR on words in common
 202.973 +        for (int i = 0; i < wordsInCommon; i++)
 202.974 +            words[i] ^= set.words[i];
 202.975 +
 202.976 +        // Copy any remaining words
 202.977 +        if (wordsInCommon < set.wordsInUse)
 202.978 +            System.arraycopy(set.words, wordsInCommon,
 202.979 +                             words, wordsInCommon,
 202.980 +                             set.wordsInUse - wordsInCommon);
 202.981 +
 202.982 +        recalculateWordsInUse();
 202.983 +        checkInvariants();
 202.984 +    }
 202.985 +
 202.986 +    /**
 202.987 +     * Clears all of the bits in this {@code BitSet} whose corresponding
 202.988 +     * bit is set in the specified {@code BitSet}.
 202.989 +     *
 202.990 +     * @param  set the {@code BitSet} with which to mask this
 202.991 +     *         {@code BitSet}
 202.992 +     * @since  1.2
 202.993 +     */
 202.994 +    public void andNot(BitSet set) {
 202.995 +        // Perform logical (a & !b) on words in common
 202.996 +        for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--)
 202.997 +            words[i] &= ~set.words[i];
 202.998 +
 202.999 +        recalculateWordsInUse();
202.1000 +        checkInvariants();
202.1001 +    }
202.1002 +
202.1003 +    /**
202.1004 +     * Returns the hash code value for this bit set. The hash code depends
202.1005 +     * only on which bits are set within this {@code BitSet}.
202.1006 +     *
202.1007 +     * <p>The hash code is defined to be the result of the following
202.1008 +     * calculation:
202.1009 +     *  <pre> {@code
202.1010 +     * public int hashCode() {
202.1011 +     *     long h = 1234;
202.1012 +     *     long[] words = toLongArray();
202.1013 +     *     for (int i = words.length; --i >= 0; )
202.1014 +     *         h ^= words[i] * (i + 1);
202.1015 +     *     return (int)((h >> 32) ^ h);
202.1016 +     * }}</pre>
202.1017 +     * Note that the hash code changes if the set of bits is altered.
202.1018 +     *
202.1019 +     * @return the hash code value for this bit set
202.1020 +     */
202.1021 +    public int hashCode() {
202.1022 +        long h = 1234;
202.1023 +        for (int i = wordsInUse; --i >= 0; )
202.1024 +            h ^= words[i] * (i + 1);
202.1025 +
202.1026 +        return (int)((h >> 32) ^ h);
202.1027 +    }
202.1028 +
202.1029 +    /**
202.1030 +     * Returns the number of bits of space actually in use by this
202.1031 +     * {@code BitSet} to represent bit values.
202.1032 +     * The maximum element in the set is the size - 1st element.
202.1033 +     *
202.1034 +     * @return the number of bits currently in this bit set
202.1035 +     */
202.1036 +    public int size() {
202.1037 +        return words.length * BITS_PER_WORD;
202.1038 +    }
202.1039 +
202.1040 +    /**
202.1041 +     * Compares this object against the specified object.
202.1042 +     * The result is {@code true} if and only if the argument is
202.1043 +     * not {@code null} and is a {@code Bitset} object that has
202.1044 +     * exactly the same set of bits set to {@code true} as this bit
202.1045 +     * set. That is, for every nonnegative {@code int} index {@code k},
202.1046 +     * <pre>((BitSet)obj).get(k) == this.get(k)</pre>
202.1047 +     * must be true. The current sizes of the two bit sets are not compared.
202.1048 +     *
202.1049 +     * @param  obj the object to compare with
202.1050 +     * @return {@code true} if the objects are the same;
202.1051 +     *         {@code false} otherwise
202.1052 +     * @see    #size()
202.1053 +     */
202.1054 +    public boolean equals(Object obj) {
202.1055 +        if (!(obj instanceof BitSet))
202.1056 +            return false;
202.1057 +        if (this == obj)
202.1058 +            return true;
202.1059 +
202.1060 +        BitSet set = (BitSet) obj;
202.1061 +
202.1062 +        checkInvariants();
202.1063 +        set.checkInvariants();
202.1064 +
202.1065 +        if (wordsInUse != set.wordsInUse)
202.1066 +            return false;
202.1067 +
202.1068 +        // Check words in use by both BitSets
202.1069 +        for (int i = 0; i < wordsInUse; i++)
202.1070 +            if (words[i] != set.words[i])
202.1071 +                return false;
202.1072 +
202.1073 +        return true;
202.1074 +    }
202.1075 +
202.1076 +    /**
202.1077 +     * Cloning this {@code BitSet} produces a new {@code BitSet}
202.1078 +     * that is equal to it.
202.1079 +     * The clone of the bit set is another bit set that has exactly the
202.1080 +     * same bits set to {@code true} as this bit set.
202.1081 +     *
202.1082 +     * @return a clone of this bit set
202.1083 +     * @see    #size()
202.1084 +     */
202.1085 +    public Object clone() {
202.1086 +        if (! sizeIsSticky)
202.1087 +            trimToSize();
202.1088 +
202.1089 +        try {
202.1090 +            BitSet result = (BitSet) super.clone();
202.1091 +            result.words = words.clone();
202.1092 +            result.checkInvariants();
202.1093 +            return result;
202.1094 +        } catch (CloneNotSupportedException e) {
202.1095 +            throw new InternalError();
202.1096 +        }
202.1097 +    }
202.1098 +
202.1099 +    /**
202.1100 +     * Attempts to reduce internal storage used for the bits in this bit set.
202.1101 +     * Calling this method may, but is not required to, affect the value
202.1102 +     * returned by a subsequent call to the {@link #size()} method.
202.1103 +     */
202.1104 +    private void trimToSize() {
202.1105 +        if (wordsInUse != words.length) {
202.1106 +            words = Arrays.copyOf(words, wordsInUse);
202.1107 +            checkInvariants();
202.1108 +        }
202.1109 +    }
202.1110 +
202.1111 +    /**
202.1112 +     * Save the state of the {@code BitSet} instance to a stream (i.e.,
202.1113 +     * serialize it).
202.1114 +     */
202.1115 +    private void writeObject(ObjectOutputStream s)
202.1116 +        throws IOException {
202.1117 +
202.1118 +        checkInvariants();
202.1119 +
202.1120 +        if (! sizeIsSticky)
202.1121 +            trimToSize();
202.1122 +
202.1123 +        ObjectOutputStream.PutField fields = s.putFields();
202.1124 +        fields.put("bits", words);
202.1125 +        s.writeFields();
202.1126 +    }
202.1127 +
202.1128 +    /**
202.1129 +     * Reconstitute the {@code BitSet} instance from a stream (i.e.,
202.1130 +     * deserialize it).
202.1131 +     */
202.1132 +    private void readObject(ObjectInputStream s)
202.1133 +        throws IOException, ClassNotFoundException {
202.1134 +
202.1135 +        ObjectInputStream.GetField fields = s.readFields();
202.1136 +        words = (long[]) fields.get("bits", null);
202.1137 +
202.1138 +        // Assume maximum length then find real length
202.1139 +        // because recalculateWordsInUse assumes maintenance
202.1140 +        // or reduction in logical size
202.1141 +        wordsInUse = words.length;
202.1142 +        recalculateWordsInUse();
202.1143 +        sizeIsSticky = (words.length > 0 && words[words.length-1] == 0L); // heuristic
202.1144 +        checkInvariants();
202.1145 +    }
202.1146 +
202.1147 +    /**
202.1148 +     * Returns a string representation of this bit set. For every index
202.1149 +     * for which this {@code BitSet} contains a bit in the set
202.1150 +     * state, the decimal representation of that index is included in
202.1151 +     * the result. Such indices are listed in order from lowest to
202.1152 +     * highest, separated by ",&nbsp;" (a comma and a space) and
202.1153 +     * surrounded by braces, resulting in the usual mathematical
202.1154 +     * notation for a set of integers.
202.1155 +     *
202.1156 +     * <p>Example:
202.1157 +     * <pre>
202.1158 +     * BitSet drPepper = new BitSet();</pre>
202.1159 +     * Now {@code drPepper.toString()} returns "{@code {}}".<p>
202.1160 +     * <pre>
202.1161 +     * drPepper.set(2);</pre>
202.1162 +     * Now {@code drPepper.toString()} returns "{@code {2}}".<p>
202.1163 +     * <pre>
202.1164 +     * drPepper.set(4);
202.1165 +     * drPepper.set(10);</pre>
202.1166 +     * Now {@code drPepper.toString()} returns "{@code {2, 4, 10}}".
202.1167 +     *
202.1168 +     * @return a string representation of this bit set
202.1169 +     */
202.1170 +    public String toString() {
202.1171 +        checkInvariants();
202.1172 +
202.1173 +        int numBits = (wordsInUse > 128) ?
202.1174 +            cardinality() : wordsInUse * BITS_PER_WORD;
202.1175 +        StringBuilder b = new StringBuilder(6*numBits + 2);
202.1176 +        b.append('{');
202.1177 +
202.1178 +        int i = nextSetBit(0);
202.1179 +        if (i != -1) {
202.1180 +            b.append(i);
202.1181 +            for (i = nextSetBit(i+1); i >= 0; i = nextSetBit(i+1)) {
202.1182 +                int endOfRun = nextClearBit(i);
202.1183 +                do { b.append(", ").append(i); }
202.1184 +                while (++i < endOfRun);
202.1185 +            }
202.1186 +        }
202.1187 +
202.1188 +        b.append('}');
202.1189 +        return b.toString();
202.1190 +    }
202.1191 +}
   203.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   203.2 +++ b/rt/emul/compact/src/main/java/java/util/Calendar.java	Wed Apr 30 15:04:10 2014 +0200
   203.3 @@ -0,0 +1,2806 @@
   203.4 +/*
   203.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   203.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   203.7 + *
   203.8 + * This code is free software; you can redistribute it and/or modify it
   203.9 + * under the terms of the GNU General Public License version 2 only, as
  203.10 + * published by the Free Software Foundation.  Oracle designates this
  203.11 + * particular file as subject to the "Classpath" exception as provided
  203.12 + * by Oracle in the LICENSE file that accompanied this code.
  203.13 + *
  203.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  203.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  203.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  203.17 + * version 2 for more details (a copy is included in the LICENSE file that
  203.18 + * accompanied this code).
  203.19 + *
  203.20 + * You should have received a copy of the GNU General Public License version
  203.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  203.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  203.23 + *
  203.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  203.25 + * or visit www.oracle.com if you need additional information or have any
  203.26 + * questions.
  203.27 + */
  203.28 +
  203.29 +/*
  203.30 + * (C) Copyright Taligent, Inc. 1996-1998 - All Rights Reserved
  203.31 + * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
  203.32 + *
  203.33 + *   The original version of this source code and documentation is copyrighted
  203.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  203.35 + * materials are provided under terms of a License Agreement between Taligent
  203.36 + * and Sun. This technology is protected by multiple US and International
  203.37 + * patents. This notice and attribution to Taligent may not be removed.
  203.38 + *   Taligent is a registered trademark of Taligent, Inc.
  203.39 + *
  203.40 + */
  203.41 +
  203.42 +package java.util;
  203.43 +
  203.44 +import java.io.IOException;
  203.45 +import java.io.ObjectInputStream;
  203.46 +import java.io.ObjectOutputStream;
  203.47 +import java.io.OptionalDataException;
  203.48 +import java.io.Serializable;
  203.49 +import java.security.AccessController;
  203.50 +import java.security.PrivilegedActionException;
  203.51 +import java.security.PrivilegedExceptionAction;
  203.52 +import java.text.DateFormat;
  203.53 +import java.text.DateFormatSymbols;
  203.54 +import java.util.concurrent.ConcurrentHashMap;
  203.55 +import java.util.concurrent.ConcurrentMap;
  203.56 +
  203.57 +/**
  203.58 + * The <code>Calendar</code> class is an abstract class that provides methods
  203.59 + * for converting between a specific instant in time and a set of {@link
  203.60 + * #fields calendar fields} such as <code>YEAR</code>, <code>MONTH</code>,
  203.61 + * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, and so on, and for
  203.62 + * manipulating the calendar fields, such as getting the date of the next
  203.63 + * week. An instant in time can be represented by a millisecond value that is
  203.64 + * an offset from the <a name="Epoch"><em>Epoch</em></a>, January 1, 1970
  203.65 + * 00:00:00.000 GMT (Gregorian).
  203.66 + *
  203.67 + * <p>The class also provides additional fields and methods for
  203.68 + * implementing a concrete calendar system outside the package. Those
  203.69 + * fields and methods are defined as <code>protected</code>.
  203.70 + *
  203.71 + * <p>
  203.72 + * Like other locale-sensitive classes, <code>Calendar</code> provides a
  203.73 + * class method, <code>getInstance</code>, for getting a generally useful
  203.74 + * object of this type. <code>Calendar</code>'s <code>getInstance</code> method
  203.75 + * returns a <code>Calendar</code> object whose
  203.76 + * calendar fields have been initialized with the current date and time:
  203.77 + * <blockquote>
  203.78 + * <pre>
  203.79 + *     Calendar rightNow = Calendar.getInstance();
  203.80 + * </pre>
  203.81 + * </blockquote>
  203.82 + *
  203.83 + * <p>A <code>Calendar</code> object can produce all the calendar field values
  203.84 + * needed to implement the date-time formatting for a particular language and
  203.85 + * calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
  203.86 + * <code>Calendar</code> defines the range of values returned by
  203.87 + * certain calendar fields, as well as their meaning.  For example,
  203.88 + * the first month of the calendar system has value <code>MONTH ==
  203.89 + * JANUARY</code> for all calendars.  Other values are defined by the
  203.90 + * concrete subclass, such as <code>ERA</code>.  See individual field
  203.91 + * documentation and subclass documentation for details.
  203.92 + *
  203.93 + * <h4>Getting and Setting Calendar Field Values</h4>
  203.94 + *
  203.95 + * <p>The calendar field values can be set by calling the <code>set</code>
  203.96 + * methods. Any field values set in a <code>Calendar</code> will not be
  203.97 + * interpreted until it needs to calculate its time value (milliseconds from
  203.98 + * the Epoch) or values of the calendar fields. Calling the
  203.99 + * <code>get</code>, <code>getTimeInMillis</code>, <code>getTime</code>,
 203.100 + * <code>add</code> and <code>roll</code> involves such calculation.
 203.101 + *
 203.102 + * <h4>Leniency</h4>
 203.103 + *
 203.104 + * <p><code>Calendar</code> has two modes for interpreting the calendar
 203.105 + * fields, <em>lenient</em> and <em>non-lenient</em>.  When a
 203.106 + * <code>Calendar</code> is in lenient mode, it accepts a wider range of
 203.107 + * calendar field values than it produces.  When a <code>Calendar</code>
 203.108 + * recomputes calendar field values for return by <code>get()</code>, all of
 203.109 + * the calendar fields are normalized. For example, a lenient
 203.110 + * <code>GregorianCalendar</code> interprets <code>MONTH == JANUARY</code>,
 203.111 + * <code>DAY_OF_MONTH == 32</code> as February 1.
 203.112 +
 203.113 + * <p>When a <code>Calendar</code> is in non-lenient mode, it throws an
 203.114 + * exception if there is any inconsistency in its calendar fields. For
 203.115 + * example, a <code>GregorianCalendar</code> always produces
 203.116 + * <code>DAY_OF_MONTH</code> values between 1 and the length of the month. A
 203.117 + * non-lenient <code>GregorianCalendar</code> throws an exception upon
 203.118 + * calculating its time or calendar field values if any out-of-range field
 203.119 + * value has been set.
 203.120 + *
 203.121 + * <h4><a name="first_week">First Week</a></h4>
 203.122 + *
 203.123 + * <code>Calendar</code> defines a locale-specific seven day week using two
 203.124 + * parameters: the first day of the week and the minimal days in first week
 203.125 + * (from 1 to 7).  These numbers are taken from the locale resource data when a
 203.126 + * <code>Calendar</code> is constructed.  They may also be specified explicitly
 203.127 + * through the methods for setting their values.
 203.128 + *
 203.129 + * <p>When setting or getting the <code>WEEK_OF_MONTH</code> or
 203.130 + * <code>WEEK_OF_YEAR</code> fields, <code>Calendar</code> must determine the
 203.131 + * first week of the month or year as a reference point.  The first week of a
 203.132 + * month or year is defined as the earliest seven day period beginning on
 203.133 + * <code>getFirstDayOfWeek()</code> and containing at least
 203.134 + * <code>getMinimalDaysInFirstWeek()</code> days of that month or year.  Weeks
 203.135 + * numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow
 203.136 + * it.  Note that the normalized numbering returned by <code>get()</code> may be
 203.137 + * different.  For example, a specific <code>Calendar</code> subclass may
 203.138 + * designate the week before week 1 of a year as week <code><i>n</i></code> of
 203.139 + * the previous year.
 203.140 + *
 203.141 + * <h4>Calendar Fields Resolution</h4>
 203.142 + *
 203.143 + * When computing a date and time from the calendar fields, there
 203.144 + * may be insufficient information for the computation (such as only
 203.145 + * year and month with no day of month), or there may be inconsistent
 203.146 + * information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15,
 203.147 + * 1996 is actually a Monday). <code>Calendar</code> will resolve
 203.148 + * calendar field values to determine the date and time in the
 203.149 + * following way.
 203.150 + *
 203.151 + * <p>If there is any conflict in calendar field values,
 203.152 + * <code>Calendar</code> gives priorities to calendar fields that have been set
 203.153 + * more recently. The following are the default combinations of the
 203.154 + * calendar fields. The most recent combination, as determined by the
 203.155 + * most recently set single field, will be used.
 203.156 + *
 203.157 + * <p><a name="date_resolution">For the date fields</a>:
 203.158 + * <blockquote>
 203.159 + * <pre>
 203.160 + * YEAR + MONTH + DAY_OF_MONTH
 203.161 + * YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 203.162 + * YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 203.163 + * YEAR + DAY_OF_YEAR
 203.164 + * YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
 203.165 + * </pre></blockquote>
 203.166 + *
 203.167 + * <a name="time_resolution">For the time of day fields</a>:
 203.168 + * <blockquote>
 203.169 + * <pre>
 203.170 + * HOUR_OF_DAY
 203.171 + * AM_PM + HOUR
 203.172 + * </pre></blockquote>
 203.173 + *
 203.174 + * <p>If there are any calendar fields whose values haven't been set in the selected
 203.175 + * field combination, <code>Calendar</code> uses their default values. The default
 203.176 + * value of each field may vary by concrete calendar systems. For example, in
 203.177 + * <code>GregorianCalendar</code>, the default of a field is the same as that
 203.178 + * of the start of the Epoch: i.e., <code>YEAR = 1970</code>, <code>MONTH =
 203.179 + * JANUARY</code>, <code>DAY_OF_MONTH = 1</code>, etc.
 203.180 + *
 203.181 + * <p>
 203.182 + * <strong>Note:</strong> There are certain possible ambiguities in
 203.183 + * interpretation of certain singular times, which are resolved in the
 203.184 + * following ways:
 203.185 + * <ol>
 203.186 + *     <li> 23:59 is the last minute of the day and 00:00 is the first
 203.187 + *          minute of the next day. Thus, 23:59 on Dec 31, 1999 &lt; 00:00 on
 203.188 + *          Jan 1, 2000 &lt; 00:01 on Jan 1, 2000.
 203.189 + *
 203.190 + *     <li> Although historically not precise, midnight also belongs to "am",
 203.191 + *          and noon belongs to "pm", so on the same day,
 203.192 + *          12:00 am (midnight) &lt; 12:01 am, and 12:00 pm (noon) &lt; 12:01 pm
 203.193 + * </ol>
 203.194 + *
 203.195 + * <p>
 203.196 + * The date or time format strings are not part of the definition of a
 203.197 + * calendar, as those must be modifiable or overridable by the user at
 203.198 + * runtime. Use {@link DateFormat}
 203.199 + * to format dates.
 203.200 + *
 203.201 + * <h4>Field Manipulation</h4>
 203.202 + *
 203.203 + * The calendar fields can be changed using three methods:
 203.204 + * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.</p>
 203.205 + *
 203.206 + * <p><strong><code>set(f, value)</code></strong> changes calendar field
 203.207 + * <code>f</code> to <code>value</code>.  In addition, it sets an
 203.208 + * internal member variable to indicate that calendar field <code>f</code> has
 203.209 + * been changed. Although calendar field <code>f</code> is changed immediately,
 203.210 + * the calendar's time value in milliseconds is not recomputed until the next call to
 203.211 + * <code>get()</code>, <code>getTime()</code>, <code>getTimeInMillis()</code>,
 203.212 + * <code>add()</code>, or <code>roll()</code> is made. Thus, multiple calls to
 203.213 + * <code>set()</code> do not trigger multiple, unnecessary
 203.214 + * computations. As a result of changing a calendar field using
 203.215 + * <code>set()</code>, other calendar fields may also change, depending on the
 203.216 + * calendar field, the calendar field value, and the calendar system. In addition,
 203.217 + * <code>get(f)</code> will not necessarily return <code>value</code> set by
 203.218 + * the call to the <code>set</code> method
 203.219 + * after the calendar fields have been recomputed. The specifics are determined by
 203.220 + * the concrete calendar class.</p>
 203.221 + *
 203.222 + * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
 203.223 + * originally set to August 31, 1999. Calling <code>set(Calendar.MONTH,
 203.224 + * Calendar.SEPTEMBER)</code> sets the date to September 31,
 203.225 + * 1999. This is a temporary internal representation that resolves to
 203.226 + * October 1, 1999 if <code>getTime()</code>is then called. However, a
 203.227 + * call to <code>set(Calendar.DAY_OF_MONTH, 30)</code> before the call to
 203.228 + * <code>getTime()</code> sets the date to September 30, 1999, since
 203.229 + * no recomputation occurs after <code>set()</code> itself.</p>
 203.230 + *
 203.231 + * <p><strong><code>add(f, delta)</code></strong> adds <code>delta</code>
 203.232 + * to field <code>f</code>.  This is equivalent to calling <code>set(f,
 203.233 + * get(f) + delta)</code> with two adjustments:</p>
 203.234 + *
 203.235 + * <blockquote>
 203.236 + *   <p><strong>Add rule 1</strong>. The value of field <code>f</code>
 203.237 + *   after the call minus the value of field <code>f</code> before the
 203.238 + *   call is <code>delta</code>, modulo any overflow that has occurred in
 203.239 + *   field <code>f</code>. Overflow occurs when a field value exceeds its
 203.240 + *   range and, as a result, the next larger field is incremented or
 203.241 + *   decremented and the field value is adjusted back into its range.</p>
 203.242 + *
 203.243 + *   <p><strong>Add rule 2</strong>. If a smaller field is expected to be
 203.244 + *   invariant, but it is impossible for it to be equal to its
 203.245 + *   prior value because of changes in its minimum or maximum after field
 203.246 + *   <code>f</code> is changed or other constraints, such as time zone
 203.247 + *   offset changes, then its value is adjusted to be as close
 203.248 + *   as possible to its expected value. A smaller field represents a
 203.249 + *   smaller unit of time. <code>HOUR</code> is a smaller field than
 203.250 + *   <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
 203.251 + *   that are not expected to be invariant. The calendar system
 203.252 + *   determines what fields are expected to be invariant.</p>
 203.253 + * </blockquote>
 203.254 + *
 203.255 + * <p>In addition, unlike <code>set()</code>, <code>add()</code> forces
 203.256 + * an immediate recomputation of the calendar's milliseconds and all
 203.257 + * fields.</p>
 203.258 + *
 203.259 + * <p><em>Example</em>: Consider a <code>GregorianCalendar</code>
 203.260 + * originally set to August 31, 1999. Calling <code>add(Calendar.MONTH,
 203.261 + * 13)</code> sets the calendar to September 30, 2000. <strong>Add rule
 203.262 + * 1</strong> sets the <code>MONTH</code> field to September, since
 203.263 + * adding 13 months to August gives September of the next year. Since
 203.264 + * <code>DAY_OF_MONTH</code> cannot be 31 in September in a
 203.265 + * <code>GregorianCalendar</code>, <strong>add rule 2</strong> sets the
 203.266 + * <code>DAY_OF_MONTH</code> to 30, the closest possible value. Although
 203.267 + * it is a smaller field, <code>DAY_OF_WEEK</code> is not adjusted by
 203.268 + * rule 2, since it is expected to change when the month changes in a
 203.269 + * <code>GregorianCalendar</code>.</p>
 203.270 + *
 203.271 + * <p><strong><code>roll(f, delta)</code></strong> adds
 203.272 + * <code>delta</code> to field <code>f</code> without changing larger
 203.273 + * fields. This is equivalent to calling <code>add(f, delta)</code> with
 203.274 + * the following adjustment:</p>
 203.275 + *
 203.276 + * <blockquote>
 203.277 + *   <p><strong>Roll rule</strong>. Larger fields are unchanged after the
 203.278 + *   call. A larger field represents a larger unit of
 203.279 + *   time. <code>DAY_OF_MONTH</code> is a larger field than
 203.280 + *   <code>HOUR</code>.</p>
 203.281 + * </blockquote>
 203.282 + *
 203.283 + * <p><em>Example</em>: See {@link java.util.GregorianCalendar#roll(int, int)}.
 203.284 + *
 203.285 + * <p><strong>Usage model</strong>. To motivate the behavior of
 203.286 + * <code>add()</code> and <code>roll()</code>, consider a user interface
 203.287 + * component with increment and decrement buttons for the month, day, and
 203.288 + * year, and an underlying <code>GregorianCalendar</code>. If the
 203.289 + * interface reads January 31, 1999 and the user presses the month
 203.290 + * increment button, what should it read? If the underlying
 203.291 + * implementation uses <code>set()</code>, it might read March 3, 1999. A
 203.292 + * better result would be February 28, 1999. Furthermore, if the user
 203.293 + * presses the month increment button again, it should read March 31,
 203.294 + * 1999, not March 28, 1999. By saving the original date and using either
 203.295 + * <code>add()</code> or <code>roll()</code>, depending on whether larger
 203.296 + * fields should be affected, the user interface can behave as most users
 203.297 + * will intuitively expect.</p>
 203.298 + *
 203.299 + * @see          java.lang.System#currentTimeMillis()
 203.300 + * @see          Date
 203.301 + * @see          GregorianCalendar
 203.302 + * @see          TimeZone
 203.303 + * @see          java.text.DateFormat
 203.304 + * @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
 203.305 + * @since JDK1.1
 203.306 + */
 203.307 +public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
 203.308 +
 203.309 +    // Data flow in Calendar
 203.310 +    // ---------------------
 203.311 +
 203.312 +    // The current time is represented in two ways by Calendar: as UTC
 203.313 +    // milliseconds from the epoch (1 January 1970 0:00 UTC), and as local
 203.314 +    // fields such as MONTH, HOUR, AM_PM, etc.  It is possible to compute the
 203.315 +    // millis from the fields, and vice versa.  The data needed to do this
 203.316 +    // conversion is encapsulated by a TimeZone object owned by the Calendar.
 203.317 +    // The data provided by the TimeZone object may also be overridden if the
 203.318 +    // user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class
 203.319 +    // keeps track of what information was most recently set by the caller, and
 203.320 +    // uses that to compute any other information as needed.
 203.321 +
 203.322 +    // If the user sets the fields using set(), the data flow is as follows.
 203.323 +    // This is implemented by the Calendar subclass's computeTime() method.
 203.324 +    // During this process, certain fields may be ignored.  The disambiguation
 203.325 +    // algorithm for resolving which fields to pay attention to is described
 203.326 +    // in the class documentation.
 203.327 +
 203.328 +    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
 203.329 +    //           |
 203.330 +    //           | Using Calendar-specific algorithm
 203.331 +    //           V
 203.332 +    //   local standard millis
 203.333 +    //           |
 203.334 +    //           | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET
 203.335 +    //           V
 203.336 +    //   UTC millis (in time data member)
 203.337 +
 203.338 +    // If the user sets the UTC millis using setTime() or setTimeInMillis(),
 203.339 +    // the data flow is as follows.  This is implemented by the Calendar
 203.340 +    // subclass's computeFields() method.
 203.341 +
 203.342 +    //   UTC millis (in time data member)
 203.343 +    //           |
 203.344 +    //           | Using TimeZone getOffset()
 203.345 +    //           V
 203.346 +    //   local standard millis
 203.347 +    //           |
 203.348 +    //           | Using Calendar-specific algorithm
 203.349 +    //           V
 203.350 +    //   local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.)
 203.351 +
 203.352 +    // In general, a round trip from fields, through local and UTC millis, and
 203.353 +    // back out to fields is made when necessary.  This is implemented by the
 203.354 +    // complete() method.  Resolving a partial set of fields into a UTC millis
 203.355 +    // value allows all remaining fields to be generated from that value.  If
 203.356 +    // the Calendar is lenient, the fields are also renormalized to standard
 203.357 +    // ranges when they are regenerated.
 203.358 +
 203.359 +    /**
 203.360 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.361 +     * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
 203.362 +     * value; see subclass documentation.
 203.363 +     *
 203.364 +     * @see GregorianCalendar#AD
 203.365 +     * @see GregorianCalendar#BC
 203.366 +     */
 203.367 +    public final static int ERA = 0;
 203.368 +
 203.369 +    /**
 203.370 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.371 +     * year. This is a calendar-specific value; see subclass documentation.
 203.372 +     */
 203.373 +    public final static int YEAR = 1;
 203.374 +
 203.375 +    /**
 203.376 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.377 +     * month. This is a calendar-specific value. The first month of
 203.378 +     * the year in the Gregorian and Julian calendars is
 203.379 +     * <code>JANUARY</code> which is 0; the last depends on the number
 203.380 +     * of months in a year.
 203.381 +     *
 203.382 +     * @see #JANUARY
 203.383 +     * @see #FEBRUARY
 203.384 +     * @see #MARCH
 203.385 +     * @see #APRIL
 203.386 +     * @see #MAY
 203.387 +     * @see #JUNE
 203.388 +     * @see #JULY
 203.389 +     * @see #AUGUST
 203.390 +     * @see #SEPTEMBER
 203.391 +     * @see #OCTOBER
 203.392 +     * @see #NOVEMBER
 203.393 +     * @see #DECEMBER
 203.394 +     * @see #UNDECIMBER
 203.395 +     */
 203.396 +    public final static int MONTH = 2;
 203.397 +
 203.398 +    /**
 203.399 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.400 +     * week number within the current year.  The first week of the year, as
 203.401 +     * defined by <code>getFirstDayOfWeek()</code> and
 203.402 +     * <code>getMinimalDaysInFirstWeek()</code>, has value 1.  Subclasses define
 203.403 +     * the value of <code>WEEK_OF_YEAR</code> for days before the first week of
 203.404 +     * the year.
 203.405 +     *
 203.406 +     * @see #getFirstDayOfWeek
 203.407 +     * @see #getMinimalDaysInFirstWeek
 203.408 +     */
 203.409 +    public final static int WEEK_OF_YEAR = 3;
 203.410 +
 203.411 +    /**
 203.412 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.413 +     * week number within the current month.  The first week of the month, as
 203.414 +     * defined by <code>getFirstDayOfWeek()</code> and
 203.415 +     * <code>getMinimalDaysInFirstWeek()</code>, has value 1.  Subclasses define
 203.416 +     * the value of <code>WEEK_OF_MONTH</code> for days before the first week of
 203.417 +     * the month.
 203.418 +     *
 203.419 +     * @see #getFirstDayOfWeek
 203.420 +     * @see #getMinimalDaysInFirstWeek
 203.421 +     */
 203.422 +    public final static int WEEK_OF_MONTH = 4;
 203.423 +
 203.424 +    /**
 203.425 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.426 +     * day of the month. This is a synonym for <code>DAY_OF_MONTH</code>.
 203.427 +     * The first day of the month has value 1.
 203.428 +     *
 203.429 +     * @see #DAY_OF_MONTH
 203.430 +     */
 203.431 +    public final static int DATE = 5;
 203.432 +
 203.433 +    /**
 203.434 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.435 +     * day of the month. This is a synonym for <code>DATE</code>.
 203.436 +     * The first day of the month has value 1.
 203.437 +     *
 203.438 +     * @see #DATE
 203.439 +     */
 203.440 +    public final static int DAY_OF_MONTH = 5;
 203.441 +
 203.442 +    /**
 203.443 +     * Field number for <code>get</code> and <code>set</code> indicating the day
 203.444 +     * number within the current year.  The first day of the year has value 1.
 203.445 +     */
 203.446 +    public final static int DAY_OF_YEAR = 6;
 203.447 +
 203.448 +    /**
 203.449 +     * Field number for <code>get</code> and <code>set</code> indicating the day
 203.450 +     * of the week.  This field takes values <code>SUNDAY</code>,
 203.451 +     * <code>MONDAY</code>, <code>TUESDAY</code>, <code>WEDNESDAY</code>,
 203.452 +     * <code>THURSDAY</code>, <code>FRIDAY</code>, and <code>SATURDAY</code>.
 203.453 +     *
 203.454 +     * @see #SUNDAY
 203.455 +     * @see #MONDAY
 203.456 +     * @see #TUESDAY
 203.457 +     * @see #WEDNESDAY
 203.458 +     * @see #THURSDAY
 203.459 +     * @see #FRIDAY
 203.460 +     * @see #SATURDAY
 203.461 +     */
 203.462 +    public final static int DAY_OF_WEEK = 7;
 203.463 +
 203.464 +    /**
 203.465 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.466 +     * ordinal number of the day of the week within the current month. Together
 203.467 +     * with the <code>DAY_OF_WEEK</code> field, this uniquely specifies a day
 203.468 +     * within a month.  Unlike <code>WEEK_OF_MONTH</code> and
 203.469 +     * <code>WEEK_OF_YEAR</code>, this field's value does <em>not</em> depend on
 203.470 +     * <code>getFirstDayOfWeek()</code> or
 203.471 +     * <code>getMinimalDaysInFirstWeek()</code>.  <code>DAY_OF_MONTH 1</code>
 203.472 +     * through <code>7</code> always correspond to <code>DAY_OF_WEEK_IN_MONTH
 203.473 +     * 1</code>; <code>8</code> through <code>14</code> correspond to
 203.474 +     * <code>DAY_OF_WEEK_IN_MONTH 2</code>, and so on.
 203.475 +     * <code>DAY_OF_WEEK_IN_MONTH 0</code> indicates the week before
 203.476 +     * <code>DAY_OF_WEEK_IN_MONTH 1</code>.  Negative values count back from the
 203.477 +     * end of the month, so the last Sunday of a month is specified as
 203.478 +     * <code>DAY_OF_WEEK = SUNDAY, DAY_OF_WEEK_IN_MONTH = -1</code>.  Because
 203.479 +     * negative values count backward they will usually be aligned differently
 203.480 +     * within the month than positive values.  For example, if a month has 31
 203.481 +     * days, <code>DAY_OF_WEEK_IN_MONTH -1</code> will overlap
 203.482 +     * <code>DAY_OF_WEEK_IN_MONTH 5</code> and the end of <code>4</code>.
 203.483 +     *
 203.484 +     * @see #DAY_OF_WEEK
 203.485 +     * @see #WEEK_OF_MONTH
 203.486 +     */
 203.487 +    public final static int DAY_OF_WEEK_IN_MONTH = 8;
 203.488 +
 203.489 +    /**
 203.490 +     * Field number for <code>get</code> and <code>set</code> indicating
 203.491 +     * whether the <code>HOUR</code> is before or after noon.
 203.492 +     * E.g., at 10:04:15.250 PM the <code>AM_PM</code> is <code>PM</code>.
 203.493 +     *
 203.494 +     * @see #AM
 203.495 +     * @see #PM
 203.496 +     * @see #HOUR
 203.497 +     */
 203.498 +    public final static int AM_PM = 9;
 203.499 +
 203.500 +    /**
 203.501 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.502 +     * hour of the morning or afternoon. <code>HOUR</code> is used for the
 203.503 +     * 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12.
 203.504 +     * E.g., at 10:04:15.250 PM the <code>HOUR</code> is 10.
 203.505 +     *
 203.506 +     * @see #AM_PM
 203.507 +     * @see #HOUR_OF_DAY
 203.508 +     */
 203.509 +    public final static int HOUR = 10;
 203.510 +
 203.511 +    /**
 203.512 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.513 +     * hour of the day. <code>HOUR_OF_DAY</code> is used for the 24-hour clock.
 203.514 +     * E.g., at 10:04:15.250 PM the <code>HOUR_OF_DAY</code> is 22.
 203.515 +     *
 203.516 +     * @see #HOUR
 203.517 +     */
 203.518 +    public final static int HOUR_OF_DAY = 11;
 203.519 +
 203.520 +    /**
 203.521 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.522 +     * minute within the hour.
 203.523 +     * E.g., at 10:04:15.250 PM the <code>MINUTE</code> is 4.
 203.524 +     */
 203.525 +    public final static int MINUTE = 12;
 203.526 +
 203.527 +    /**
 203.528 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.529 +     * second within the minute.
 203.530 +     * E.g., at 10:04:15.250 PM the <code>SECOND</code> is 15.
 203.531 +     */
 203.532 +    public final static int SECOND = 13;
 203.533 +
 203.534 +    /**
 203.535 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.536 +     * millisecond within the second.
 203.537 +     * E.g., at 10:04:15.250 PM the <code>MILLISECOND</code> is 250.
 203.538 +     */
 203.539 +    public final static int MILLISECOND = 14;
 203.540 +
 203.541 +    /**
 203.542 +     * Field number for <code>get</code> and <code>set</code>
 203.543 +     * indicating the raw offset from GMT in milliseconds.
 203.544 +     * <p>
 203.545 +     * This field reflects the correct GMT offset value of the time
 203.546 +     * zone of this <code>Calendar</code> if the
 203.547 +     * <code>TimeZone</code> implementation subclass supports
 203.548 +     * historical GMT offset changes.
 203.549 +     */
 203.550 +    public final static int ZONE_OFFSET = 15;
 203.551 +
 203.552 +    /**
 203.553 +     * Field number for <code>get</code> and <code>set</code> indicating the
 203.554 +     * daylight saving offset in milliseconds.
 203.555 +     * <p>
 203.556 +     * This field reflects the correct daylight saving offset value of
 203.557 +     * the time zone of this <code>Calendar</code> if the
 203.558 +     * <code>TimeZone</code> implementation subclass supports
 203.559 +     * historical Daylight Saving Time schedule changes.
 203.560 +     */
 203.561 +    public final static int DST_OFFSET = 16;
 203.562 +
 203.563 +    /**
 203.564 +     * The number of distinct fields recognized by <code>get</code> and <code>set</code>.
 203.565 +     * Field numbers range from <code>0..FIELD_COUNT-1</code>.
 203.566 +     */
 203.567 +    public final static int FIELD_COUNT = 17;
 203.568 +
 203.569 +    /**
 203.570 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.571 +     * Sunday.
 203.572 +     */
 203.573 +    public final static int SUNDAY = 1;
 203.574 +
 203.575 +    /**
 203.576 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.577 +     * Monday.
 203.578 +     */
 203.579 +    public final static int MONDAY = 2;
 203.580 +
 203.581 +    /**
 203.582 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.583 +     * Tuesday.
 203.584 +     */
 203.585 +    public final static int TUESDAY = 3;
 203.586 +
 203.587 +    /**
 203.588 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.589 +     * Wednesday.
 203.590 +     */
 203.591 +    public final static int WEDNESDAY = 4;
 203.592 +
 203.593 +    /**
 203.594 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.595 +     * Thursday.
 203.596 +     */
 203.597 +    public final static int THURSDAY = 5;
 203.598 +
 203.599 +    /**
 203.600 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.601 +     * Friday.
 203.602 +     */
 203.603 +    public final static int FRIDAY = 6;
 203.604 +
 203.605 +    /**
 203.606 +     * Value of the {@link #DAY_OF_WEEK} field indicating
 203.607 +     * Saturday.
 203.608 +     */
 203.609 +    public final static int SATURDAY = 7;
 203.610 +
 203.611 +    /**
 203.612 +     * Value of the {@link #MONTH} field indicating the
 203.613 +     * first month of the year in the Gregorian and Julian calendars.
 203.614 +     */
 203.615 +    public final static int JANUARY = 0;
 203.616 +
 203.617 +    /**
 203.618 +     * Value of the {@link #MONTH} field indicating the
 203.619 +     * second month of the year in the Gregorian and Julian calendars.
 203.620 +     */
 203.621 +    public final static int FEBRUARY = 1;
 203.622 +
 203.623 +    /**
 203.624 +     * Value of the {@link #MONTH} field indicating the
 203.625 +     * third month of the year in the Gregorian and Julian calendars.
 203.626 +     */
 203.627 +    public final static int MARCH = 2;
 203.628 +
 203.629 +    /**
 203.630 +     * Value of the {@link #MONTH} field indicating the
 203.631 +     * fourth month of the year in the Gregorian and Julian calendars.
 203.632 +     */
 203.633 +    public final static int APRIL = 3;
 203.634 +
 203.635 +    /**
 203.636 +     * Value of the {@link #MONTH} field indicating the
 203.637 +     * fifth month of the year in the Gregorian and Julian calendars.
 203.638 +     */
 203.639 +    public final static int MAY = 4;
 203.640 +
 203.641 +    /**
 203.642 +     * Value of the {@link #MONTH} field indicating the
 203.643 +     * sixth month of the year in the Gregorian and Julian calendars.
 203.644 +     */
 203.645 +    public final static int JUNE = 5;
 203.646 +
 203.647 +    /**
 203.648 +     * Value of the {@link #MONTH} field indicating the
 203.649 +     * seventh month of the year in the Gregorian and Julian calendars.
 203.650 +     */
 203.651 +    public final static int JULY = 6;
 203.652 +
 203.653 +    /**
 203.654 +     * Value of the {@link #MONTH} field indicating the
 203.655 +     * eighth month of the year in the Gregorian and Julian calendars.
 203.656 +     */
 203.657 +    public final static int AUGUST = 7;
 203.658 +
 203.659 +    /**
 203.660 +     * Value of the {@link #MONTH} field indicating the
 203.661 +     * ninth month of the year in the Gregorian and Julian calendars.
 203.662 +     */
 203.663 +    public final static int SEPTEMBER = 8;
 203.664 +
 203.665 +    /**
 203.666 +     * Value of the {@link #MONTH} field indicating the
 203.667 +     * tenth month of the year in the Gregorian and Julian calendars.
 203.668 +     */
 203.669 +    public final static int OCTOBER = 9;
 203.670 +
 203.671 +    /**
 203.672 +     * Value of the {@link #MONTH} field indicating the
 203.673 +     * eleventh month of the year in the Gregorian and Julian calendars.
 203.674 +     */
 203.675 +    public final static int NOVEMBER = 10;
 203.676 +
 203.677 +    /**
 203.678 +     * Value of the {@link #MONTH} field indicating the
 203.679 +     * twelfth month of the year in the Gregorian and Julian calendars.
 203.680 +     */
 203.681 +    public final static int DECEMBER = 11;
 203.682 +
 203.683 +    /**
 203.684 +     * Value of the {@link #MONTH} field indicating the
 203.685 +     * thirteenth month of the year. Although <code>GregorianCalendar</code>
 203.686 +     * does not use this value, lunar calendars do.
 203.687 +     */
 203.688 +    public final static int UNDECIMBER = 12;
 203.689 +
 203.690 +    /**
 203.691 +     * Value of the {@link #AM_PM} field indicating the
 203.692 +     * period of the day from midnight to just before noon.
 203.693 +     */
 203.694 +    public final static int AM = 0;
 203.695 +
 203.696 +    /**
 203.697 +     * Value of the {@link #AM_PM} field indicating the
 203.698 +     * period of the day from noon to just before midnight.
 203.699 +     */
 203.700 +    public final static int PM = 1;
 203.701 +
 203.702 +    /**
 203.703 +     * A style specifier for {@link #getDisplayNames(int, int, Locale)
 203.704 +     * getDisplayNames} indicating names in all styles, such as
 203.705 +     * "January" and "Jan".
 203.706 +     *
 203.707 +     * @see #SHORT
 203.708 +     * @see #LONG
 203.709 +     * @since 1.6
 203.710 +     */
 203.711 +    public static final int ALL_STYLES = 0;
 203.712 +
 203.713 +    /**
 203.714 +     * A style specifier for {@link #getDisplayName(int, int, Locale)
 203.715 +     * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 203.716 +     * getDisplayNames} indicating a short name, such as "Jan".
 203.717 +     *
 203.718 +     * @see #LONG
 203.719 +     * @since 1.6
 203.720 +     */
 203.721 +    public static final int SHORT = 1;
 203.722 +
 203.723 +    /**
 203.724 +     * A style specifier for {@link #getDisplayName(int, int, Locale)
 203.725 +     * getDisplayName} and {@link #getDisplayNames(int, int, Locale)
 203.726 +     * getDisplayNames} indicating a long name, such as "January".
 203.727 +     *
 203.728 +     * @see #SHORT
 203.729 +     * @since 1.6
 203.730 +     */
 203.731 +    public static final int LONG = 2;
 203.732 +
 203.733 +    // Internal notes:
 203.734 +    // Calendar contains two kinds of time representations: current "time" in
 203.735 +    // milliseconds, and a set of calendar "fields" representing the current time.
 203.736 +    // The two representations are usually in sync, but can get out of sync
 203.737 +    // as follows.
 203.738 +    // 1. Initially, no fields are set, and the time is invalid.
 203.739 +    // 2. If the time is set, all fields are computed and in sync.
 203.740 +    // 3. If a single field is set, the time is invalid.
 203.741 +    // Recomputation of the time and fields happens when the object needs
 203.742 +    // to return a result to the user, or use a result for a computation.
 203.743 +
 203.744 +    /**
 203.745 +     * The calendar field values for the currently set time for this calendar.
 203.746 +     * This is an array of <code>FIELD_COUNT</code> integers, with index values
 203.747 +     * <code>ERA</code> through <code>DST_OFFSET</code>.
 203.748 +     * @serial
 203.749 +     */
 203.750 +    protected int           fields[];
 203.751 +
 203.752 +    /**
 203.753 +     * The flags which tell if a specified calendar field for the calendar is set.
 203.754 +     * A new object has no fields set.  After the first call to a method
 203.755 +     * which generates the fields, they all remain set after that.
 203.756 +     * This is an array of <code>FIELD_COUNT</code> booleans, with index values
 203.757 +     * <code>ERA</code> through <code>DST_OFFSET</code>.
 203.758 +     * @serial
 203.759 +     */
 203.760 +    protected boolean       isSet[];
 203.761 +
 203.762 +    /**
 203.763 +     * Pseudo-time-stamps which specify when each field was set. There
 203.764 +     * are two special values, UNSET and COMPUTED. Values from
 203.765 +     * MINIMUM_USER_SET to Integer.MAX_VALUE are legal user set values.
 203.766 +     */
 203.767 +    transient private int   stamp[];
 203.768 +
 203.769 +    /**
 203.770 +     * The currently set time for this calendar, expressed in milliseconds after
 203.771 +     * January 1, 1970, 0:00:00 GMT.
 203.772 +     * @see #isTimeSet
 203.773 +     * @serial
 203.774 +     */
 203.775 +    protected long          time;
 203.776 +
 203.777 +    /**
 203.778 +     * True if then the value of <code>time</code> is valid.
 203.779 +     * The time is made invalid by a change to an item of <code>field[]</code>.
 203.780 +     * @see #time
 203.781 +     * @serial
 203.782 +     */
 203.783 +    protected boolean       isTimeSet;
 203.784 +
 203.785 +    /**
 203.786 +     * True if <code>fields[]</code> are in sync with the currently set time.
 203.787 +     * If false, then the next attempt to get the value of a field will
 203.788 +     * force a recomputation of all fields from the current value of
 203.789 +     * <code>time</code>.
 203.790 +     * @serial
 203.791 +     */
 203.792 +    protected boolean       areFieldsSet;
 203.793 +
 203.794 +    /**
 203.795 +     * True if all fields have been set.
 203.796 +     * @serial
 203.797 +     */
 203.798 +    transient boolean       areAllFieldsSet;
 203.799 +
 203.800 +    /**
 203.801 +     * <code>True</code> if this calendar allows out-of-range field values during computation
 203.802 +     * of <code>time</code> from <code>fields[]</code>.
 203.803 +     * @see #setLenient
 203.804 +     * @see #isLenient
 203.805 +     * @serial
 203.806 +     */
 203.807 +    private boolean         lenient = true;
 203.808 +
 203.809 +    /**
 203.810 +     * The <code>TimeZone</code> used by this calendar. <code>Calendar</code>
 203.811 +     * uses the time zone data to translate between locale and GMT time.
 203.812 +     * @serial
 203.813 +     */
 203.814 +    private TimeZone        zone;
 203.815 +
 203.816 +    /**
 203.817 +     * <code>True</code> if zone references to a shared TimeZone object.
 203.818 +     */
 203.819 +    transient private boolean sharedZone = false;
 203.820 +
 203.821 +    /**
 203.822 +     * The first day of the week, with possible values <code>SUNDAY</code>,
 203.823 +     * <code>MONDAY</code>, etc.  This is a locale-dependent value.
 203.824 +     * @serial
 203.825 +     */
 203.826 +    private int             firstDayOfWeek;
 203.827 +
 203.828 +    /**
 203.829 +     * The number of days required for the first week in a month or year,
 203.830 +     * with possible values from 1 to 7.  This is a locale-dependent value.
 203.831 +     * @serial
 203.832 +     */
 203.833 +    private int             minimalDaysInFirstWeek;
 203.834 +
 203.835 +    /**
 203.836 +     * Cache to hold the firstDayOfWeek and minimalDaysInFirstWeek
 203.837 +     * of a Locale.
 203.838 +     */
 203.839 +    private static final ConcurrentMap<Locale, int[]> cachedLocaleData
 203.840 +        = new ConcurrentHashMap<Locale, int[]>(3);
 203.841 +
 203.842 +    // Special values of stamp[]
 203.843 +    /**
 203.844 +     * The corresponding fields[] has no value.
 203.845 +     */
 203.846 +    private static final int        UNSET = 0;
 203.847 +
 203.848 +    /**
 203.849 +     * The value of the corresponding fields[] has been calculated internally.
 203.850 +     */
 203.851 +    private static final int        COMPUTED = 1;
 203.852 +
 203.853 +    /**
 203.854 +     * The value of the corresponding fields[] has been set externally. Stamp
 203.855 +     * values which are greater than 1 represents the (pseudo) time when the
 203.856 +     * corresponding fields[] value was set.
 203.857 +     */
 203.858 +    private static final int        MINIMUM_USER_STAMP = 2;
 203.859 +
 203.860 +    /**
 203.861 +     * The mask value that represents all of the fields.
 203.862 +     */
 203.863 +    static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;
 203.864 +
 203.865 +    /**
 203.866 +     * The next available value for <code>stamp[]</code>, an internal array.
 203.867 +     * This actually should not be written out to the stream, and will probably
 203.868 +     * be removed from the stream in the near future.  In the meantime,
 203.869 +     * a value of <code>MINIMUM_USER_STAMP</code> should be used.
 203.870 +     * @serial
 203.871 +     */
 203.872 +    private int             nextStamp = MINIMUM_USER_STAMP;
 203.873 +
 203.874 +    // the internal serial version which says which version was written
 203.875 +    // - 0 (default) for version up to JDK 1.1.5
 203.876 +    // - 1 for version from JDK 1.1.6, which writes a correct 'time' value
 203.877 +    //     as well as compatible values for other fields.  This is a
 203.878 +    //     transitional format.
 203.879 +    // - 2 (not implemented yet) a future version, in which fields[],
 203.880 +    //     areFieldsSet, and isTimeSet become transient, and isSet[] is
 203.881 +    //     removed. In JDK 1.1.6 we write a format compatible with version 2.
 203.882 +    static final int        currentSerialVersion = 1;
 203.883 +
 203.884 +    /**
 203.885 +     * The version of the serialized data on the stream.  Possible values:
 203.886 +     * <dl>
 203.887 +     * <dt><b>0</b> or not present on stream</dt>
 203.888 +     * <dd>
 203.889 +     * JDK 1.1.5 or earlier.
 203.890 +     * </dd>
 203.891 +     * <dt><b>1</b></dt>
 203.892 +     * <dd>
 203.893 +     * JDK 1.1.6 or later.  Writes a correct 'time' value
 203.894 +     * as well as compatible values for other fields.  This is a
 203.895 +     * transitional format.
 203.896 +     * </dd>
 203.897 +     * </dl>
 203.898 +     * When streaming out this class, the most recent format
 203.899 +     * and the highest allowable <code>serialVersionOnStream</code>
 203.900 +     * is written.
 203.901 +     * @serial
 203.902 +     * @since JDK1.1.6
 203.903 +     */
 203.904 +    private int             serialVersionOnStream = currentSerialVersion;
 203.905 +
 203.906 +    // Proclaim serialization compatibility with JDK 1.1
 203.907 +    static final long       serialVersionUID = -1807547505821590642L;
 203.908 +
 203.909 +    // Mask values for calendar fields
 203.910 +    final static int ERA_MASK           = (1 << ERA);
 203.911 +    final static int YEAR_MASK          = (1 << YEAR);
 203.912 +    final static int MONTH_MASK         = (1 << MONTH);
 203.913 +    final static int WEEK_OF_YEAR_MASK  = (1 << WEEK_OF_YEAR);
 203.914 +    final static int WEEK_OF_MONTH_MASK = (1 << WEEK_OF_MONTH);
 203.915 +    final static int DAY_OF_MONTH_MASK  = (1 << DAY_OF_MONTH);
 203.916 +    final static int DATE_MASK          = DAY_OF_MONTH_MASK;
 203.917 +    final static int DAY_OF_YEAR_MASK   = (1 << DAY_OF_YEAR);
 203.918 +    final static int DAY_OF_WEEK_MASK   = (1 << DAY_OF_WEEK);
 203.919 +    final static int DAY_OF_WEEK_IN_MONTH_MASK  = (1 << DAY_OF_WEEK_IN_MONTH);
 203.920 +    final static int AM_PM_MASK         = (1 << AM_PM);
 203.921 +    final static int HOUR_MASK          = (1 << HOUR);
 203.922 +    final static int HOUR_OF_DAY_MASK   = (1 << HOUR_OF_DAY);
 203.923 +    final static int MINUTE_MASK        = (1 << MINUTE);
 203.924 +    final static int SECOND_MASK        = (1 << SECOND);
 203.925 +    final static int MILLISECOND_MASK   = (1 << MILLISECOND);
 203.926 +    final static int ZONE_OFFSET_MASK   = (1 << ZONE_OFFSET);
 203.927 +    final static int DST_OFFSET_MASK    = (1 << DST_OFFSET);
 203.928 +
 203.929 +    /**
 203.930 +     * Constructs a Calendar with the default time zone
 203.931 +     * and locale.
 203.932 +     * @see     TimeZone#getDefault
 203.933 +     */
 203.934 +    protected Calendar()
 203.935 +    {
 203.936 +        this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
 203.937 +        sharedZone = true;
 203.938 +    }
 203.939 +
 203.940 +    /**
 203.941 +     * Constructs a calendar with the specified time zone and locale.
 203.942 +     *
 203.943 +     * @param zone the time zone to use
 203.944 +     * @param aLocale the locale for the week data
 203.945 +     */
 203.946 +    protected Calendar(TimeZone zone, Locale aLocale)
 203.947 +    {
 203.948 +        fields = new int[FIELD_COUNT];
 203.949 +        isSet = new boolean[FIELD_COUNT];
 203.950 +        stamp = new int[FIELD_COUNT];
 203.951 +
 203.952 +        this.zone = zone;
 203.953 +        setWeekCountData(aLocale);
 203.954 +    }
 203.955 +
 203.956 +    /**
 203.957 +     * Gets a calendar using the default time zone and locale. The
 203.958 +     * <code>Calendar</code> returned is based on the current time
 203.959 +     * in the default time zone with the default locale.
 203.960 +     *
 203.961 +     * @return a Calendar.
 203.962 +     */
 203.963 +    public static Calendar getInstance()
 203.964 +    {
 203.965 +        Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
 203.966 +        cal.sharedZone = true;
 203.967 +        return cal;
 203.968 +    }
 203.969 +
 203.970 +    /**
 203.971 +     * Gets a calendar using the specified time zone and default locale.
 203.972 +     * The <code>Calendar</code> returned is based on the current time
 203.973 +     * in the given time zone with the default locale.
 203.974 +     *
 203.975 +     * @param zone the time zone to use
 203.976 +     * @return a Calendar.
 203.977 +     */
 203.978 +    public static Calendar getInstance(TimeZone zone)
 203.979 +    {
 203.980 +        return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
 203.981 +    }
 203.982 +
 203.983 +    /**
 203.984 +     * Gets a calendar using the default time zone and specified locale.
 203.985 +     * The <code>Calendar</code> returned is based on the current time
 203.986 +     * in the default time zone with the given locale.
 203.987 +     *
 203.988 +     * @param aLocale the locale for the week data
 203.989 +     * @return a Calendar.
 203.990 +     */
 203.991 +    public static Calendar getInstance(Locale aLocale)
 203.992 +    {
 203.993 +        Calendar cal = createCalendar(TimeZone.getDefaultRef(), aLocale);
 203.994 +        cal.sharedZone = true;
 203.995 +        return cal;
 203.996 +    }
 203.997 +
 203.998 +    /**
 203.999 +     * Gets a calendar with the specified time zone and locale.
203.1000 +     * The <code>Calendar</code> returned is based on the current time
203.1001 +     * in the given time zone with the given locale.
203.1002 +     *
203.1003 +     * @param zone the time zone to use
203.1004 +     * @param aLocale the locale for the week data
203.1005 +     * @return a Calendar.
203.1006 +     */
203.1007 +    public static Calendar getInstance(TimeZone zone,
203.1008 +                                       Locale aLocale)
203.1009 +    {
203.1010 +        return createCalendar(zone, aLocale);
203.1011 +    }
203.1012 +
203.1013 +    private static Calendar createCalendar(TimeZone zone,
203.1014 +                                           Locale aLocale)
203.1015 +    {
203.1016 +        Calendar cal = null;
203.1017 +
203.1018 +        String caltype = aLocale.getUnicodeLocaleType("ca");
203.1019 +        if (caltype == null) {
203.1020 +            // Calendar type is not specified.
203.1021 +            // If the specified locale is a Thai locale,
203.1022 +            // returns a BuddhistCalendar instance.
203.1023 +            if ("th".equals(aLocale.getLanguage())
203.1024 +                    && ("TH".equals(aLocale.getCountry()))) {
203.1025 +//                cal = new BuddhistCalendar(zone, aLocale);
203.1026 +            } else {
203.1027 +//                cal = new GregorianCalendar(zone, aLocale);
203.1028 +            }
203.1029 +        } else if (caltype.equals("japanese")) {
203.1030 +//            cal = new JapaneseImperialCalendar(zone, aLocale);
203.1031 +        } else if (caltype.equals("buddhist")) {
203.1032 +//            cal = new BuddhistCalendar(zone, aLocale);
203.1033 +        } else {
203.1034 +            // Unsupported calendar type.
203.1035 +            // Use Gregorian calendar as a fallback.
203.1036 +//            cal = new GregorianCalendar(zone, aLocale);
203.1037 +        }
203.1038 +
203.1039 +        return cal;
203.1040 +    }
203.1041 +
203.1042 +    /**
203.1043 +     * Returns an array of all locales for which the <code>getInstance</code>
203.1044 +     * methods of this class can return localized instances.
203.1045 +     * The array returned must contain at least a <code>Locale</code>
203.1046 +     * instance equal to {@link java.util.Locale#US Locale.US}.
203.1047 +     *
203.1048 +     * @return An array of locales for which localized
203.1049 +     *         <code>Calendar</code> instances are available.
203.1050 +     */
203.1051 +    public static synchronized Locale[] getAvailableLocales()
203.1052 +    {
203.1053 +        return DateFormat.getAvailableLocales();
203.1054 +    }
203.1055 +
203.1056 +    /**
203.1057 +     * Converts the current calendar field values in {@link #fields fields[]}
203.1058 +     * to the millisecond time value
203.1059 +     * {@link #time}.
203.1060 +     *
203.1061 +     * @see #complete()
203.1062 +     * @see #computeFields()
203.1063 +     */
203.1064 +    protected abstract void computeTime();
203.1065 +
203.1066 +    /**
203.1067 +     * Converts the current millisecond time value {@link #time}
203.1068 +     * to calendar field values in {@link #fields fields[]}.
203.1069 +     * This allows you to sync up the calendar field values with
203.1070 +     * a new time that is set for the calendar.  The time is <em>not</em>
203.1071 +     * recomputed first; to recompute the time, then the fields, call the
203.1072 +     * {@link #complete()} method.
203.1073 +     *
203.1074 +     * @see #computeTime()
203.1075 +     */
203.1076 +    protected abstract void computeFields();
203.1077 +
203.1078 +    /**
203.1079 +     * Returns a <code>Date</code> object representing this
203.1080 +     * <code>Calendar</code>'s time value (millisecond offset from the <a
203.1081 +     * href="#Epoch">Epoch</a>").
203.1082 +     *
203.1083 +     * @return a <code>Date</code> representing the time value.
203.1084 +     * @see #setTime(Date)
203.1085 +     * @see #getTimeInMillis()
203.1086 +     */
203.1087 +    public final Date getTime() {
203.1088 +        return new Date(getTimeInMillis());
203.1089 +    }
203.1090 +
203.1091 +    /**
203.1092 +     * Sets this Calendar's time with the given <code>Date</code>.
203.1093 +     * <p>
203.1094 +     * Note: Calling <code>setTime()</code> with
203.1095 +     * <code>Date(Long.MAX_VALUE)</code> or <code>Date(Long.MIN_VALUE)</code>
203.1096 +     * may yield incorrect field values from <code>get()</code>.
203.1097 +     *
203.1098 +     * @param date the given Date.
203.1099 +     * @see #getTime()
203.1100 +     * @see #setTimeInMillis(long)
203.1101 +     */
203.1102 +    public final void setTime(Date date) {
203.1103 +        setTimeInMillis(date.getTime());
203.1104 +    }
203.1105 +
203.1106 +    /**
203.1107 +     * Returns this Calendar's time value in milliseconds.
203.1108 +     *
203.1109 +     * @return the current time as UTC milliseconds from the epoch.
203.1110 +     * @see #getTime()
203.1111 +     * @see #setTimeInMillis(long)
203.1112 +     */
203.1113 +    public long getTimeInMillis() {
203.1114 +        if (!isTimeSet) {
203.1115 +            updateTime();
203.1116 +        }
203.1117 +        return time;
203.1118 +    }
203.1119 +
203.1120 +    /**
203.1121 +     * Sets this Calendar's current time from the given long value.
203.1122 +     *
203.1123 +     * @param millis the new time in UTC milliseconds from the epoch.
203.1124 +     * @see #setTime(Date)
203.1125 +     * @see #getTimeInMillis()
203.1126 +     */
203.1127 +    public void setTimeInMillis(long millis) {
203.1128 +        // If we don't need to recalculate the calendar field values,
203.1129 +        // do nothing.
203.1130 +//        if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet
203.1131 +//            && (zone instanceof ZoneInfo) && !((ZoneInfo)zone).isDirty()) {
203.1132 +//            return;
203.1133 +//        }
203.1134 +        time = millis;
203.1135 +        isTimeSet = true;
203.1136 +        areFieldsSet = false;
203.1137 +        computeFields();
203.1138 +        areAllFieldsSet = areFieldsSet = true;
203.1139 +    }
203.1140 +
203.1141 +    /**
203.1142 +     * Returns the value of the given calendar field. In lenient mode,
203.1143 +     * all calendar fields are normalized. In non-lenient mode, all
203.1144 +     * calendar fields are validated and this method throws an
203.1145 +     * exception if any calendar fields have out-of-range values. The
203.1146 +     * normalization and validation are handled by the
203.1147 +     * {@link #complete()} method, which process is calendar
203.1148 +     * system dependent.
203.1149 +     *
203.1150 +     * @param field the given calendar field.
203.1151 +     * @return the value for the given calendar field.
203.1152 +     * @throws ArrayIndexOutOfBoundsException if the specified field is out of range
203.1153 +     *             (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1154 +     * @see #set(int,int)
203.1155 +     * @see #complete()
203.1156 +     */
203.1157 +    public int get(int field)
203.1158 +    {
203.1159 +        complete();
203.1160 +        return internalGet(field);
203.1161 +    }
203.1162 +
203.1163 +    /**
203.1164 +     * Returns the value of the given calendar field. This method does
203.1165 +     * not involve normalization or validation of the field value.
203.1166 +     *
203.1167 +     * @param field the given calendar field.
203.1168 +     * @return the value for the given calendar field.
203.1169 +     * @see #get(int)
203.1170 +     */
203.1171 +    protected final int internalGet(int field)
203.1172 +    {
203.1173 +        return fields[field];
203.1174 +    }
203.1175 +
203.1176 +    /**
203.1177 +     * Sets the value of the given calendar field. This method does
203.1178 +     * not affect any setting state of the field in this
203.1179 +     * <code>Calendar</code> instance.
203.1180 +     *
203.1181 +     * @throws IndexOutOfBoundsException if the specified field is out of range
203.1182 +     *             (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1183 +     * @see #areFieldsSet
203.1184 +     * @see #isTimeSet
203.1185 +     * @see #areAllFieldsSet
203.1186 +     * @see #set(int,int)
203.1187 +     */
203.1188 +    final void internalSet(int field, int value)
203.1189 +    {
203.1190 +        fields[field] = value;
203.1191 +    }
203.1192 +
203.1193 +    /**
203.1194 +     * Sets the given calendar field to the given value. The value is not
203.1195 +     * interpreted by this method regardless of the leniency mode.
203.1196 +     *
203.1197 +     * @param field the given calendar field.
203.1198 +     * @param value the value to be set for the given calendar field.
203.1199 +     * @throws ArrayIndexOutOfBoundsException if the specified field is out of range
203.1200 +     *             (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1201 +     * in non-lenient mode.
203.1202 +     * @see #set(int,int,int)
203.1203 +     * @see #set(int,int,int,int,int)
203.1204 +     * @see #set(int,int,int,int,int,int)
203.1205 +     * @see #get(int)
203.1206 +     */
203.1207 +    public void set(int field, int value)
203.1208 +    {
203.1209 +        // If the fields are partially normalized, calculate all the
203.1210 +        // fields before changing any fields.
203.1211 +        if (areFieldsSet && !areAllFieldsSet) {
203.1212 +            computeFields();
203.1213 +        }
203.1214 +        internalSet(field, value);
203.1215 +        isTimeSet = false;
203.1216 +        areFieldsSet = false;
203.1217 +        isSet[field] = true;
203.1218 +        stamp[field] = nextStamp++;
203.1219 +        if (nextStamp == Integer.MAX_VALUE) {
203.1220 +            adjustStamp();
203.1221 +        }
203.1222 +    }
203.1223 +
203.1224 +    /**
203.1225 +     * Sets the values for the calendar fields <code>YEAR</code>,
203.1226 +     * <code>MONTH</code>, and <code>DAY_OF_MONTH</code>.
203.1227 +     * Previous values of other calendar fields are retained.  If this is not desired,
203.1228 +     * call {@link #clear()} first.
203.1229 +     *
203.1230 +     * @param year the value used to set the <code>YEAR</code> calendar field.
203.1231 +     * @param month the value used to set the <code>MONTH</code> calendar field.
203.1232 +     * Month value is 0-based. e.g., 0 for January.
203.1233 +     * @param date the value used to set the <code>DAY_OF_MONTH</code> calendar field.
203.1234 +     * @see #set(int,int)
203.1235 +     * @see #set(int,int,int,int,int)
203.1236 +     * @see #set(int,int,int,int,int,int)
203.1237 +     */
203.1238 +    public final void set(int year, int month, int date)
203.1239 +    {
203.1240 +        set(YEAR, year);
203.1241 +        set(MONTH, month);
203.1242 +        set(DATE, date);
203.1243 +    }
203.1244 +
203.1245 +    /**
203.1246 +     * Sets the values for the calendar fields <code>YEAR</code>,
203.1247 +     * <code>MONTH</code>, <code>DAY_OF_MONTH</code>,
203.1248 +     * <code>HOUR_OF_DAY</code>, and <code>MINUTE</code>.
203.1249 +     * Previous values of other fields are retained.  If this is not desired,
203.1250 +     * call {@link #clear()} first.
203.1251 +     *
203.1252 +     * @param year the value used to set the <code>YEAR</code> calendar field.
203.1253 +     * @param month the value used to set the <code>MONTH</code> calendar field.
203.1254 +     * Month value is 0-based. e.g., 0 for January.
203.1255 +     * @param date the value used to set the <code>DAY_OF_MONTH</code> calendar field.
203.1256 +     * @param hourOfDay the value used to set the <code>HOUR_OF_DAY</code> calendar field.
203.1257 +     * @param minute the value used to set the <code>MINUTE</code> calendar field.
203.1258 +     * @see #set(int,int)
203.1259 +     * @see #set(int,int,int)
203.1260 +     * @see #set(int,int,int,int,int,int)
203.1261 +     */
203.1262 +    public final void set(int year, int month, int date, int hourOfDay, int minute)
203.1263 +    {
203.1264 +        set(YEAR, year);
203.1265 +        set(MONTH, month);
203.1266 +        set(DATE, date);
203.1267 +        set(HOUR_OF_DAY, hourOfDay);
203.1268 +        set(MINUTE, minute);
203.1269 +    }
203.1270 +
203.1271 +    /**
203.1272 +     * Sets the values for the fields <code>YEAR</code>, <code>MONTH</code>,
203.1273 +     * <code>DAY_OF_MONTH</code>, <code>HOUR</code>, <code>MINUTE</code>, and
203.1274 +     * <code>SECOND</code>.
203.1275 +     * Previous values of other fields are retained.  If this is not desired,
203.1276 +     * call {@link #clear()} first.
203.1277 +     *
203.1278 +     * @param year the value used to set the <code>YEAR</code> calendar field.
203.1279 +     * @param month the value used to set the <code>MONTH</code> calendar field.
203.1280 +     * Month value is 0-based. e.g., 0 for January.
203.1281 +     * @param date the value used to set the <code>DAY_OF_MONTH</code> calendar field.
203.1282 +     * @param hourOfDay the value used to set the <code>HOUR_OF_DAY</code> calendar field.
203.1283 +     * @param minute the value used to set the <code>MINUTE</code> calendar field.
203.1284 +     * @param second the value used to set the <code>SECOND</code> calendar field.
203.1285 +     * @see #set(int,int)
203.1286 +     * @see #set(int,int,int)
203.1287 +     * @see #set(int,int,int,int,int)
203.1288 +     */
203.1289 +    public final void set(int year, int month, int date, int hourOfDay, int minute,
203.1290 +                          int second)
203.1291 +    {
203.1292 +        set(YEAR, year);
203.1293 +        set(MONTH, month);
203.1294 +        set(DATE, date);
203.1295 +        set(HOUR_OF_DAY, hourOfDay);
203.1296 +        set(MINUTE, minute);
203.1297 +        set(SECOND, second);
203.1298 +    }
203.1299 +
203.1300 +    /**
203.1301 +     * Sets all the calendar field values and the time value
203.1302 +     * (millisecond offset from the <a href="#Epoch">Epoch</a>) of
203.1303 +     * this <code>Calendar</code> undefined. This means that {@link
203.1304 +     * #isSet(int) isSet()} will return <code>false</code> for all the
203.1305 +     * calendar fields, and the date and time calculations will treat
203.1306 +     * the fields as if they had never been set. A
203.1307 +     * <code>Calendar</code> implementation class may use its specific
203.1308 +     * default field values for date/time calculations. For example,
203.1309 +     * <code>GregorianCalendar</code> uses 1970 if the
203.1310 +     * <code>YEAR</code> field value is undefined.
203.1311 +     *
203.1312 +     * @see #clear(int)
203.1313 +     */
203.1314 +    public final void clear()
203.1315 +    {
203.1316 +        for (int i = 0; i < fields.length; ) {
203.1317 +            stamp[i] = fields[i] = 0; // UNSET == 0
203.1318 +            isSet[i++] = false;
203.1319 +        }
203.1320 +        areAllFieldsSet = areFieldsSet = false;
203.1321 +        isTimeSet = false;
203.1322 +    }
203.1323 +
203.1324 +    /**
203.1325 +     * Sets the given calendar field value and the time value
203.1326 +     * (millisecond offset from the <a href="#Epoch">Epoch</a>) of
203.1327 +     * this <code>Calendar</code> undefined. This means that {@link
203.1328 +     * #isSet(int) isSet(field)} will return <code>false</code>, and
203.1329 +     * the date and time calculations will treat the field as if it
203.1330 +     * had never been set. A <code>Calendar</code> implementation
203.1331 +     * class may use the field's specific default value for date and
203.1332 +     * time calculations.
203.1333 +     *
203.1334 +     * <p>The {@link #HOUR_OF_DAY}, {@link #HOUR} and {@link #AM_PM}
203.1335 +     * fields are handled independently and the <a
203.1336 +     * href="#time_resolution">the resolution rule for the time of
203.1337 +     * day</a> is applied. Clearing one of the fields doesn't reset
203.1338 +     * the hour of day value of this <code>Calendar</code>. Use {@link
203.1339 +     * #set(int,int) set(Calendar.HOUR_OF_DAY, 0)} to reset the hour
203.1340 +     * value.
203.1341 +     *
203.1342 +     * @param field the calendar field to be cleared.
203.1343 +     * @see #clear()
203.1344 +     */
203.1345 +    public final void clear(int field)
203.1346 +    {
203.1347 +        fields[field] = 0;
203.1348 +        stamp[field] = UNSET;
203.1349 +        isSet[field] = false;
203.1350 +
203.1351 +        areAllFieldsSet = areFieldsSet = false;
203.1352 +        isTimeSet = false;
203.1353 +    }
203.1354 +
203.1355 +    /**
203.1356 +     * Determines if the given calendar field has a value set,
203.1357 +     * including cases that the value has been set by internal fields
203.1358 +     * calculations triggered by a <code>get</code> method call.
203.1359 +     *
203.1360 +     * @return <code>true</code> if the given calendar field has a value set;
203.1361 +     * <code>false</code> otherwise.
203.1362 +     */
203.1363 +    public final boolean isSet(int field)
203.1364 +    {
203.1365 +        return stamp[field] != UNSET;
203.1366 +    }
203.1367 +
203.1368 +    /**
203.1369 +     * Returns the string representation of the calendar
203.1370 +     * <code>field</code> value in the given <code>style</code> and
203.1371 +     * <code>locale</code>.  If no string representation is
203.1372 +     * applicable, <code>null</code> is returned. This method calls
203.1373 +     * {@link Calendar#get(int) get(field)} to get the calendar
203.1374 +     * <code>field</code> value if the string representation is
203.1375 +     * applicable to the given calendar <code>field</code>.
203.1376 +     *
203.1377 +     * <p>For example, if this <code>Calendar</code> is a
203.1378 +     * <code>GregorianCalendar</code> and its date is 2005-01-01, then
203.1379 +     * the string representation of the {@link #MONTH} field would be
203.1380 +     * "January" in the long style in an English locale or "Jan" in
203.1381 +     * the short style. However, no string representation would be
203.1382 +     * available for the {@link #DAY_OF_MONTH} field, and this method
203.1383 +     * would return <code>null</code>.
203.1384 +     *
203.1385 +     * <p>The default implementation supports the calendar fields for
203.1386 +     * which a {@link DateFormatSymbols} has names in the given
203.1387 +     * <code>locale</code>.
203.1388 +     *
203.1389 +     * @param field
203.1390 +     *        the calendar field for which the string representation
203.1391 +     *        is returned
203.1392 +     * @param style
203.1393 +     *        the style applied to the string representation; one of
203.1394 +     *        {@link #SHORT} or {@link #LONG}.
203.1395 +     * @param locale
203.1396 +     *        the locale for the string representation
203.1397 +     * @return the string representation of the given
203.1398 +     *        <code>field</code> in the given <code>style</code>, or
203.1399 +     *        <code>null</code> if no string representation is
203.1400 +     *        applicable.
203.1401 +     * @exception IllegalArgumentException
203.1402 +     *        if <code>field</code> or <code>style</code> is invalid,
203.1403 +     *        or if this <code>Calendar</code> is non-lenient and any
203.1404 +     *        of the calendar fields have invalid values
203.1405 +     * @exception NullPointerException
203.1406 +     *        if <code>locale</code> is null
203.1407 +     * @since 1.6
203.1408 +     */
203.1409 +    public String getDisplayName(int field, int style, Locale locale) {
203.1410 +        if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
203.1411 +                                    ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
203.1412 +            return null;
203.1413 +        }
203.1414 +
203.1415 +        DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
203.1416 +        String[] strings = getFieldStrings(field, style, symbols);
203.1417 +        if (strings != null) {
203.1418 +            int fieldValue = get(field);
203.1419 +            if (fieldValue < strings.length) {
203.1420 +                return strings[fieldValue];
203.1421 +            }
203.1422 +        }
203.1423 +        return null;
203.1424 +    }
203.1425 +
203.1426 +    /**
203.1427 +     * Returns a <code>Map</code> containing all names of the calendar
203.1428 +     * <code>field</code> in the given <code>style</code> and
203.1429 +     * <code>locale</code> and their corresponding field values. For
203.1430 +     * example, if this <code>Calendar</code> is a {@link
203.1431 +     * GregorianCalendar}, the returned map would contain "Jan" to
203.1432 +     * {@link #JANUARY}, "Feb" to {@link #FEBRUARY}, and so on, in the
203.1433 +     * {@linkplain #SHORT short} style in an English locale.
203.1434 +     *
203.1435 +     * <p>The values of other calendar fields may be taken into
203.1436 +     * account to determine a set of display names. For example, if
203.1437 +     * this <code>Calendar</code> is a lunisolar calendar system and
203.1438 +     * the year value given by the {@link #YEAR} field has a leap
203.1439 +     * month, this method would return month names containing the leap
203.1440 +     * month name, and month names are mapped to their values specific
203.1441 +     * for the year.
203.1442 +     *
203.1443 +     * <p>The default implementation supports display names contained in
203.1444 +     * a {@link DateFormatSymbols}. For example, if <code>field</code>
203.1445 +     * is {@link #MONTH} and <code>style</code> is {@link
203.1446 +     * #ALL_STYLES}, this method returns a <code>Map</code> containing
203.1447 +     * all strings returned by {@link DateFormatSymbols#getShortMonths()}
203.1448 +     * and {@link DateFormatSymbols#getMonths()}.
203.1449 +     *
203.1450 +     * @param field
203.1451 +     *        the calendar field for which the display names are returned
203.1452 +     * @param style
203.1453 +     *        the style applied to the display names; one of {@link
203.1454 +     *        #SHORT}, {@link #LONG}, or {@link #ALL_STYLES}.
203.1455 +     * @param locale
203.1456 +     *        the locale for the display names
203.1457 +     * @return a <code>Map</code> containing all display names in
203.1458 +     *        <code>style</code> and <code>locale</code> and their
203.1459 +     *        field values, or <code>null</code> if no display names
203.1460 +     *        are defined for <code>field</code>
203.1461 +     * @exception IllegalArgumentException
203.1462 +     *        if <code>field</code> or <code>style</code> is invalid,
203.1463 +     *        or if this <code>Calendar</code> is non-lenient and any
203.1464 +     *        of the calendar fields have invalid values
203.1465 +     * @exception NullPointerException
203.1466 +     *        if <code>locale</code> is null
203.1467 +     * @since 1.6
203.1468 +     */
203.1469 +    public Map<String, Integer> getDisplayNames(int field, int style, Locale locale) {
203.1470 +        if (!checkDisplayNameParams(field, style, ALL_STYLES, LONG, locale,
203.1471 +                                    ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
203.1472 +            return null;
203.1473 +        }
203.1474 +
203.1475 +        // ALL_STYLES
203.1476 +        if (style == ALL_STYLES) {
203.1477 +            Map<String,Integer> shortNames = getDisplayNamesImpl(field, SHORT, locale);
203.1478 +            if (field == ERA || field == AM_PM) {
203.1479 +                return shortNames;
203.1480 +            }
203.1481 +            Map<String,Integer> longNames = getDisplayNamesImpl(field, LONG, locale);
203.1482 +            if (shortNames == null) {
203.1483 +                return longNames;
203.1484 +            }
203.1485 +            if (longNames != null) {
203.1486 +                shortNames.putAll(longNames);
203.1487 +            }
203.1488 +            return shortNames;
203.1489 +        }
203.1490 +
203.1491 +        // SHORT or LONG
203.1492 +        return getDisplayNamesImpl(field, style, locale);
203.1493 +    }
203.1494 +
203.1495 +    private Map<String,Integer> getDisplayNamesImpl(int field, int style, Locale locale) {
203.1496 +        DateFormatSymbols symbols = DateFormatSymbols.getInstance(locale);
203.1497 +        String[] strings = getFieldStrings(field, style, symbols);
203.1498 +        if (strings != null) {
203.1499 +            Map<String,Integer> names = new HashMap<String,Integer>();
203.1500 +            for (int i = 0; i < strings.length; i++) {
203.1501 +                if (strings[i].length() == 0) {
203.1502 +                    continue;
203.1503 +                }
203.1504 +                names.put(strings[i], i);
203.1505 +            }
203.1506 +            return names;
203.1507 +        }
203.1508 +        return null;
203.1509 +    }
203.1510 +
203.1511 +    boolean checkDisplayNameParams(int field, int style, int minStyle, int maxStyle,
203.1512 +                                   Locale locale, int fieldMask) {
203.1513 +        if (field < 0 || field >= fields.length ||
203.1514 +            style < minStyle || style > maxStyle) {
203.1515 +            throw new IllegalArgumentException();
203.1516 +        }
203.1517 +        if (locale == null) {
203.1518 +            throw new NullPointerException();
203.1519 +        }
203.1520 +        return isFieldSet(fieldMask, field);
203.1521 +    }
203.1522 +
203.1523 +    private String[] getFieldStrings(int field, int style, DateFormatSymbols symbols) {
203.1524 +        String[] strings = null;
203.1525 +        switch (field) {
203.1526 +        case ERA:
203.1527 +            strings = symbols.getEras();
203.1528 +            break;
203.1529 +
203.1530 +        case MONTH:
203.1531 +            strings = (style == LONG) ? symbols.getMonths() : symbols.getShortMonths();
203.1532 +            break;
203.1533 +
203.1534 +        case DAY_OF_WEEK:
203.1535 +            strings = (style == LONG) ? symbols.getWeekdays() : symbols.getShortWeekdays();
203.1536 +            break;
203.1537 +
203.1538 +        case AM_PM:
203.1539 +            strings = symbols.getAmPmStrings();
203.1540 +            break;
203.1541 +        }
203.1542 +        return strings;
203.1543 +    }
203.1544 +
203.1545 +    /**
203.1546 +     * Fills in any unset fields in the calendar fields. First, the {@link
203.1547 +     * #computeTime()} method is called if the time value (millisecond offset
203.1548 +     * from the <a href="#Epoch">Epoch</a>) has not been calculated from
203.1549 +     * calendar field values. Then, the {@link #computeFields()} method is
203.1550 +     * called to calculate all calendar field values.
203.1551 +     */
203.1552 +    protected void complete()
203.1553 +    {
203.1554 +        if (!isTimeSet)
203.1555 +            updateTime();
203.1556 +        if (!areFieldsSet || !areAllFieldsSet) {
203.1557 +            computeFields(); // fills in unset fields
203.1558 +            areAllFieldsSet = areFieldsSet = true;
203.1559 +        }
203.1560 +    }
203.1561 +
203.1562 +    /**
203.1563 +     * Returns whether the value of the specified calendar field has been set
203.1564 +     * externally by calling one of the setter methods rather than by the
203.1565 +     * internal time calculation.
203.1566 +     *
203.1567 +     * @return <code>true</code> if the field has been set externally,
203.1568 +     * <code>false</code> otherwise.
203.1569 +     * @exception IndexOutOfBoundsException if the specified
203.1570 +     *                <code>field</code> is out of range
203.1571 +     *               (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1572 +     * @see #selectFields()
203.1573 +     * @see #setFieldsComputed(int)
203.1574 +     */
203.1575 +    final boolean isExternallySet(int field) {
203.1576 +        return stamp[field] >= MINIMUM_USER_STAMP;
203.1577 +    }
203.1578 +
203.1579 +    /**
203.1580 +     * Returns a field mask (bit mask) indicating all calendar fields that
203.1581 +     * have the state of externally or internally set.
203.1582 +     *
203.1583 +     * @return a bit mask indicating set state fields
203.1584 +     */
203.1585 +    final int getSetStateFields() {
203.1586 +        int mask = 0;
203.1587 +        for (int i = 0; i < fields.length; i++) {
203.1588 +            if (stamp[i] != UNSET) {
203.1589 +                mask |= 1 << i;
203.1590 +            }
203.1591 +        }
203.1592 +        return mask;
203.1593 +    }
203.1594 +
203.1595 +    /**
203.1596 +     * Sets the state of the specified calendar fields to
203.1597 +     * <em>computed</em>. This state means that the specified calendar fields
203.1598 +     * have valid values that have been set by internal time calculation
203.1599 +     * rather than by calling one of the setter methods.
203.1600 +     *
203.1601 +     * @param fieldMask the field to be marked as computed.
203.1602 +     * @exception IndexOutOfBoundsException if the specified
203.1603 +     *                <code>field</code> is out of range
203.1604 +     *               (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1605 +     * @see #isExternallySet(int)
203.1606 +     * @see #selectFields()
203.1607 +     */
203.1608 +    final void setFieldsComputed(int fieldMask) {
203.1609 +        if (fieldMask == ALL_FIELDS) {
203.1610 +            for (int i = 0; i < fields.length; i++) {
203.1611 +                stamp[i] = COMPUTED;
203.1612 +                isSet[i] = true;
203.1613 +            }
203.1614 +            areFieldsSet = areAllFieldsSet = true;
203.1615 +        } else {
203.1616 +            for (int i = 0; i < fields.length; i++) {
203.1617 +                if ((fieldMask & 1) == 1) {
203.1618 +                    stamp[i] = COMPUTED;
203.1619 +                    isSet[i] = true;
203.1620 +                } else {
203.1621 +                    if (areAllFieldsSet && !isSet[i]) {
203.1622 +                        areAllFieldsSet = false;
203.1623 +                    }
203.1624 +                }
203.1625 +                fieldMask >>>= 1;
203.1626 +            }
203.1627 +        }
203.1628 +    }
203.1629 +
203.1630 +    /**
203.1631 +     * Sets the state of the calendar fields that are <em>not</em> specified
203.1632 +     * by <code>fieldMask</code> to <em>unset</em>. If <code>fieldMask</code>
203.1633 +     * specifies all the calendar fields, then the state of this
203.1634 +     * <code>Calendar</code> becomes that all the calendar fields are in sync
203.1635 +     * with the time value (millisecond offset from the Epoch).
203.1636 +     *
203.1637 +     * @param fieldMask the field mask indicating which calendar fields are in
203.1638 +     * sync with the time value.
203.1639 +     * @exception IndexOutOfBoundsException if the specified
203.1640 +     *                <code>field</code> is out of range
203.1641 +     *               (<code>field &lt; 0 || field &gt;= FIELD_COUNT</code>).
203.1642 +     * @see #isExternallySet(int)
203.1643 +     * @see #selectFields()
203.1644 +     */
203.1645 +    final void setFieldsNormalized(int fieldMask) {
203.1646 +        if (fieldMask != ALL_FIELDS) {
203.1647 +            for (int i = 0; i < fields.length; i++) {
203.1648 +                if ((fieldMask & 1) == 0) {
203.1649 +                    stamp[i] = fields[i] = 0; // UNSET == 0
203.1650 +                    isSet[i] = false;
203.1651 +                }
203.1652 +                fieldMask >>= 1;
203.1653 +            }
203.1654 +        }
203.1655 +
203.1656 +        // Some or all of the fields are in sync with the
203.1657 +        // milliseconds, but the stamp values are not normalized yet.
203.1658 +        areFieldsSet = true;
203.1659 +        areAllFieldsSet = false;
203.1660 +    }
203.1661 +
203.1662 +    /**
203.1663 +     * Returns whether the calendar fields are partially in sync with the time
203.1664 +     * value or fully in sync but not stamp values are not normalized yet.
203.1665 +     */
203.1666 +    final boolean isPartiallyNormalized() {
203.1667 +        return areFieldsSet && !areAllFieldsSet;
203.1668 +    }
203.1669 +
203.1670 +    /**
203.1671 +     * Returns whether the calendar fields are fully in sync with the time
203.1672 +     * value.
203.1673 +     */
203.1674 +    final boolean isFullyNormalized() {
203.1675 +        return areFieldsSet && areAllFieldsSet;
203.1676 +    }
203.1677 +
203.1678 +    /**
203.1679 +     * Marks this Calendar as not sync'd.
203.1680 +     */
203.1681 +    final void setUnnormalized() {
203.1682 +        areFieldsSet = areAllFieldsSet = false;
203.1683 +    }
203.1684 +
203.1685 +    /**
203.1686 +     * Returns whether the specified <code>field</code> is on in the
203.1687 +     * <code>fieldMask</code>.
203.1688 +     */
203.1689 +    static final boolean isFieldSet(int fieldMask, int field) {
203.1690 +        return (fieldMask & (1 << field)) != 0;
203.1691 +    }
203.1692 +
203.1693 +    /**
203.1694 +     * Returns a field mask indicating which calendar field values
203.1695 +     * to be used to calculate the time value. The calendar fields are
203.1696 +     * returned as a bit mask, each bit of which corresponds to a field, i.e.,
203.1697 +     * the mask value of <code>field</code> is <code>(1 &lt;&lt;
203.1698 +     * field)</code>. For example, 0x26 represents the <code>YEAR</code>,
203.1699 +     * <code>MONTH</code>, and <code>DAY_OF_MONTH</code> fields (i.e., 0x26 is
203.1700 +     * equal to
203.1701 +     * <code>(1&lt;&lt;YEAR)|(1&lt;&lt;MONTH)|(1&lt;&lt;DAY_OF_MONTH))</code>.
203.1702 +     *
203.1703 +     * <p>This method supports the calendar fields resolution as described in
203.1704 +     * the class description. If the bit mask for a given field is on and its
203.1705 +     * field has not been set (i.e., <code>isSet(field)</code> is
203.1706 +     * <code>false</code>), then the default value of the field has to be
203.1707 +     * used, which case means that the field has been selected because the
203.1708 +     * selected combination involves the field.
203.1709 +     *
203.1710 +     * @return a bit mask of selected fields
203.1711 +     * @see #isExternallySet(int)
203.1712 +     * @see #setInternallySetState(int)
203.1713 +     */
203.1714 +    final int selectFields() {
203.1715 +        // This implementation has been taken from the GregorianCalendar class.
203.1716 +
203.1717 +        // The YEAR field must always be used regardless of its SET
203.1718 +        // state because YEAR is a mandatory field to determine the date
203.1719 +        // and the default value (EPOCH_YEAR) may change through the
203.1720 +        // normalization process.
203.1721 +        int fieldMask = YEAR_MASK;
203.1722 +
203.1723 +        if (stamp[ERA] != UNSET) {
203.1724 +            fieldMask |= ERA_MASK;
203.1725 +        }
203.1726 +        // Find the most recent group of fields specifying the day within
203.1727 +        // the year.  These may be any of the following combinations:
203.1728 +        //   MONTH + DAY_OF_MONTH
203.1729 +        //   MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
203.1730 +        //   MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
203.1731 +        //   DAY_OF_YEAR
203.1732 +        //   WEEK_OF_YEAR + DAY_OF_WEEK
203.1733 +        // We look for the most recent of the fields in each group to determine
203.1734 +        // the age of the group.  For groups involving a week-related field such
203.1735 +        // as WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR, both the
203.1736 +        // week-related field and the DAY_OF_WEEK must be set for the group as a
203.1737 +        // whole to be considered.  (See bug 4153860 - liu 7/24/98.)
203.1738 +        int dowStamp = stamp[DAY_OF_WEEK];
203.1739 +        int monthStamp = stamp[MONTH];
203.1740 +        int domStamp = stamp[DAY_OF_MONTH];
203.1741 +        int womStamp = aggregateStamp(stamp[WEEK_OF_MONTH], dowStamp);
203.1742 +        int dowimStamp = aggregateStamp(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp);
203.1743 +        int doyStamp = stamp[DAY_OF_YEAR];
203.1744 +        int woyStamp = aggregateStamp(stamp[WEEK_OF_YEAR], dowStamp);
203.1745 +
203.1746 +        int bestStamp = domStamp;
203.1747 +        if (womStamp > bestStamp) {
203.1748 +            bestStamp = womStamp;
203.1749 +        }
203.1750 +        if (dowimStamp > bestStamp) {
203.1751 +            bestStamp = dowimStamp;
203.1752 +        }
203.1753 +        if (doyStamp > bestStamp) {
203.1754 +            bestStamp = doyStamp;
203.1755 +        }
203.1756 +        if (woyStamp > bestStamp) {
203.1757 +            bestStamp = woyStamp;
203.1758 +        }
203.1759 +
203.1760 +        /* No complete combination exists.  Look for WEEK_OF_MONTH,
203.1761 +         * DAY_OF_WEEK_IN_MONTH, or WEEK_OF_YEAR alone.  Treat DAY_OF_WEEK alone
203.1762 +         * as DAY_OF_WEEK_IN_MONTH.
203.1763 +         */
203.1764 +        if (bestStamp == UNSET) {
203.1765 +            womStamp = stamp[WEEK_OF_MONTH];
203.1766 +            dowimStamp = Math.max(stamp[DAY_OF_WEEK_IN_MONTH], dowStamp);
203.1767 +            woyStamp = stamp[WEEK_OF_YEAR];
203.1768 +            bestStamp = Math.max(Math.max(womStamp, dowimStamp), woyStamp);
203.1769 +
203.1770 +            /* Treat MONTH alone or no fields at all as DAY_OF_MONTH.  This may
203.1771 +             * result in bestStamp = domStamp = UNSET if no fields are set,
203.1772 +             * which indicates DAY_OF_MONTH.
203.1773 +             */
203.1774 +            if (bestStamp == UNSET) {
203.1775 +                bestStamp = domStamp = monthStamp;
203.1776 +            }
203.1777 +        }
203.1778 +
203.1779 +        if (bestStamp == domStamp ||
203.1780 +           (bestStamp == womStamp && stamp[WEEK_OF_MONTH] >= stamp[WEEK_OF_YEAR]) ||
203.1781 +           (bestStamp == dowimStamp && stamp[DAY_OF_WEEK_IN_MONTH] >= stamp[WEEK_OF_YEAR])) {
203.1782 +            fieldMask |= MONTH_MASK;
203.1783 +            if (bestStamp == domStamp) {
203.1784 +                fieldMask |= DAY_OF_MONTH_MASK;
203.1785 +            } else {
203.1786 +                assert (bestStamp == womStamp || bestStamp == dowimStamp);
203.1787 +                if (dowStamp != UNSET) {
203.1788 +                    fieldMask |= DAY_OF_WEEK_MASK;
203.1789 +                }
203.1790 +                if (womStamp == dowimStamp) {
203.1791 +                    // When they are equal, give the priority to
203.1792 +                    // WEEK_OF_MONTH for compatibility.
203.1793 +                    if (stamp[WEEK_OF_MONTH] >= stamp[DAY_OF_WEEK_IN_MONTH]) {
203.1794 +                        fieldMask |= WEEK_OF_MONTH_MASK;
203.1795 +                    } else {
203.1796 +                        fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK;
203.1797 +                    }
203.1798 +                } else {
203.1799 +                    if (bestStamp == womStamp) {
203.1800 +                        fieldMask |= WEEK_OF_MONTH_MASK;
203.1801 +                    } else {
203.1802 +                        assert (bestStamp == dowimStamp);
203.1803 +                        if (stamp[DAY_OF_WEEK_IN_MONTH] != UNSET) {
203.1804 +                            fieldMask |= DAY_OF_WEEK_IN_MONTH_MASK;
203.1805 +                        }
203.1806 +                    }
203.1807 +                }
203.1808 +            }
203.1809 +        } else {
203.1810 +            assert (bestStamp == doyStamp || bestStamp == woyStamp ||
203.1811 +                    bestStamp == UNSET);
203.1812 +            if (bestStamp == doyStamp) {
203.1813 +                fieldMask |= DAY_OF_YEAR_MASK;
203.1814 +            } else {
203.1815 +                assert (bestStamp == woyStamp);
203.1816 +                if (dowStamp != UNSET) {
203.1817 +                    fieldMask |= DAY_OF_WEEK_MASK;
203.1818 +                }
203.1819 +                fieldMask |= WEEK_OF_YEAR_MASK;
203.1820 +            }
203.1821 +        }
203.1822 +
203.1823 +        // Find the best set of fields specifying the time of day.  There
203.1824 +        // are only two possibilities here; the HOUR_OF_DAY or the
203.1825 +        // AM_PM and the HOUR.
203.1826 +        int hourOfDayStamp = stamp[HOUR_OF_DAY];
203.1827 +        int hourStamp = aggregateStamp(stamp[HOUR], stamp[AM_PM]);
203.1828 +        bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp;
203.1829 +
203.1830 +        // if bestStamp is still UNSET, then take HOUR or AM_PM. (See 4846659)
203.1831 +        if (bestStamp == UNSET) {
203.1832 +            bestStamp = Math.max(stamp[HOUR], stamp[AM_PM]);
203.1833 +        }
203.1834 +
203.1835 +        // Hours
203.1836 +        if (bestStamp != UNSET) {
203.1837 +            if (bestStamp == hourOfDayStamp) {
203.1838 +                fieldMask |= HOUR_OF_DAY_MASK;
203.1839 +            } else {
203.1840 +                fieldMask |= HOUR_MASK;
203.1841 +                if (stamp[AM_PM] != UNSET) {
203.1842 +                    fieldMask |= AM_PM_MASK;
203.1843 +                }
203.1844 +            }
203.1845 +        }
203.1846 +        if (stamp[MINUTE] != UNSET) {
203.1847 +            fieldMask |= MINUTE_MASK;
203.1848 +        }
203.1849 +        if (stamp[SECOND] != UNSET) {
203.1850 +            fieldMask |= SECOND_MASK;
203.1851 +        }
203.1852 +        if (stamp[MILLISECOND] != UNSET) {
203.1853 +            fieldMask |= MILLISECOND_MASK;
203.1854 +        }
203.1855 +        if (stamp[ZONE_OFFSET] >= MINIMUM_USER_STAMP) {
203.1856 +                fieldMask |= ZONE_OFFSET_MASK;
203.1857 +        }
203.1858 +        if (stamp[DST_OFFSET] >= MINIMUM_USER_STAMP) {
203.1859 +            fieldMask |= DST_OFFSET_MASK;
203.1860 +        }
203.1861 +
203.1862 +        return fieldMask;
203.1863 +    }
203.1864 +
203.1865 +    /**
203.1866 +     * Returns the pseudo-time-stamp for two fields, given their
203.1867 +     * individual pseudo-time-stamps.  If either of the fields
203.1868 +     * is unset, then the aggregate is unset.  Otherwise, the
203.1869 +     * aggregate is the later of the two stamps.
203.1870 +     */
203.1871 +    private static final int aggregateStamp(int stamp_a, int stamp_b) {
203.1872 +        if (stamp_a == UNSET || stamp_b == UNSET) {
203.1873 +            return UNSET;
203.1874 +        }
203.1875 +        return (stamp_a > stamp_b) ? stamp_a : stamp_b;
203.1876 +    }
203.1877 +
203.1878 +    /**
203.1879 +     * Compares this <code>Calendar</code> to the specified
203.1880 +     * <code>Object</code>.  The result is <code>true</code> if and only if
203.1881 +     * the argument is a <code>Calendar</code> object of the same calendar
203.1882 +     * system that represents the same time value (millisecond offset from the
203.1883 +     * <a href="#Epoch">Epoch</a>) under the same
203.1884 +     * <code>Calendar</code> parameters as this object.
203.1885 +     *
203.1886 +     * <p>The <code>Calendar</code> parameters are the values represented
203.1887 +     * by the <code>isLenient</code>, <code>getFirstDayOfWeek</code>,
203.1888 +     * <code>getMinimalDaysInFirstWeek</code> and <code>getTimeZone</code>
203.1889 +     * methods. If there is any difference in those parameters
203.1890 +     * between the two <code>Calendar</code>s, this method returns
203.1891 +     * <code>false</code>.
203.1892 +     *
203.1893 +     * <p>Use the {@link #compareTo(Calendar) compareTo} method to
203.1894 +     * compare only the time values.
203.1895 +     *
203.1896 +     * @param obj the object to compare with.
203.1897 +     * @return <code>true</code> if this object is equal to <code>obj</code>;
203.1898 +     * <code>false</code> otherwise.
203.1899 +     */
203.1900 +    public boolean equals(Object obj) {
203.1901 +        if (this == obj)
203.1902 +            return true;
203.1903 +        try {
203.1904 +            Calendar that = (Calendar)obj;
203.1905 +            return compareTo(getMillisOf(that)) == 0 &&
203.1906 +                lenient == that.lenient &&
203.1907 +                firstDayOfWeek == that.firstDayOfWeek &&
203.1908 +                minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&
203.1909 +                zone.equals(that.zone);
203.1910 +        } catch (Exception e) {
203.1911 +            // Note: GregorianCalendar.computeTime throws
203.1912 +            // IllegalArgumentException if the ERA value is invalid
203.1913 +            // even it's in lenient mode.
203.1914 +        }
203.1915 +        return false;
203.1916 +    }
203.1917 +
203.1918 +    /**
203.1919 +     * Returns a hash code for this calendar.
203.1920 +     *
203.1921 +     * @return a hash code value for this object.
203.1922 +     * @since 1.2
203.1923 +     */
203.1924 +    public int hashCode() {
203.1925 +        // 'otheritems' represents the hash code for the previous versions.
203.1926 +        int otheritems = (lenient ? 1 : 0)
203.1927 +            | (firstDayOfWeek << 1)
203.1928 +            | (minimalDaysInFirstWeek << 4)
203.1929 +            | (zone.hashCode() << 7);
203.1930 +        long t = getMillisOf(this);
203.1931 +        return (int) t ^ (int)(t >> 32) ^ otheritems;
203.1932 +    }
203.1933 +
203.1934 +    /**
203.1935 +     * Returns whether this <code>Calendar</code> represents a time
203.1936 +     * before the time represented by the specified
203.1937 +     * <code>Object</code>. This method is equivalent to:
203.1938 +     * <pre><blockquote>
203.1939 +     *         compareTo(when) < 0
203.1940 +     * </blockquote></pre>
203.1941 +     * if and only if <code>when</code> is a <code>Calendar</code>
203.1942 +     * instance. Otherwise, the method returns <code>false</code>.
203.1943 +     *
203.1944 +     * @param when the <code>Object</code> to be compared
203.1945 +     * @return <code>true</code> if the time of this
203.1946 +     * <code>Calendar</code> is before the time represented by
203.1947 +     * <code>when</code>; <code>false</code> otherwise.
203.1948 +     * @see     #compareTo(Calendar)
203.1949 +     */
203.1950 +    public boolean before(Object when) {
203.1951 +        return when instanceof Calendar
203.1952 +            && compareTo((Calendar)when) < 0;
203.1953 +    }
203.1954 +
203.1955 +    /**
203.1956 +     * Returns whether this <code>Calendar</code> represents a time
203.1957 +     * after the time represented by the specified
203.1958 +     * <code>Object</code>. This method is equivalent to:
203.1959 +     * <pre><blockquote>
203.1960 +     *         compareTo(when) > 0
203.1961 +     * </blockquote></pre>
203.1962 +     * if and only if <code>when</code> is a <code>Calendar</code>
203.1963 +     * instance. Otherwise, the method returns <code>false</code>.
203.1964 +     *
203.1965 +     * @param when the <code>Object</code> to be compared
203.1966 +     * @return <code>true</code> if the time of this <code>Calendar</code> is
203.1967 +     * after the time represented by <code>when</code>; <code>false</code>
203.1968 +     * otherwise.
203.1969 +     * @see     #compareTo(Calendar)
203.1970 +     */
203.1971 +    public boolean after(Object when) {
203.1972 +        return when instanceof Calendar
203.1973 +            && compareTo((Calendar)when) > 0;
203.1974 +    }
203.1975 +
203.1976 +    /**
203.1977 +     * Compares the time values (millisecond offsets from the <a
203.1978 +     * href="#Epoch">Epoch</a>) represented by two
203.1979 +     * <code>Calendar</code> objects.
203.1980 +     *
203.1981 +     * @param anotherCalendar the <code>Calendar</code> to be compared.
203.1982 +     * @return the value <code>0</code> if the time represented by the argument
203.1983 +     * is equal to the time represented by this <code>Calendar</code>; a value
203.1984 +     * less than <code>0</code> if the time of this <code>Calendar</code> is
203.1985 +     * before the time represented by the argument; and a value greater than
203.1986 +     * <code>0</code> if the time of this <code>Calendar</code> is after the
203.1987 +     * time represented by the argument.
203.1988 +     * @exception NullPointerException if the specified <code>Calendar</code> is
203.1989 +     *            <code>null</code>.
203.1990 +     * @exception IllegalArgumentException if the time value of the
203.1991 +     * specified <code>Calendar</code> object can't be obtained due to
203.1992 +     * any invalid calendar values.
203.1993 +     * @since   1.5
203.1994 +     */
203.1995 +    public int compareTo(Calendar anotherCalendar) {
203.1996 +        return compareTo(getMillisOf(anotherCalendar));
203.1997 +    }
203.1998 +
203.1999 +    /**
203.2000 +     * Adds or subtracts the specified amount of time to the given calendar field,
203.2001 +     * based on the calendar's rules. For example, to subtract 5 days from
203.2002 +     * the current time of the calendar, you can achieve it by calling:
203.2003 +     * <p><code>add(Calendar.DAY_OF_MONTH, -5)</code>.
203.2004 +     *
203.2005 +     * @param field the calendar field.
203.2006 +     * @param amount the amount of date or time to be added to the field.
203.2007 +     * @see #roll(int,int)
203.2008 +     * @see #set(int,int)
203.2009 +     */
203.2010 +    abstract public void add(int field, int amount);
203.2011 +
203.2012 +    /**
203.2013 +     * Adds or subtracts (up/down) a single unit of time on the given time
203.2014 +     * field without changing larger fields. For example, to roll the current
203.2015 +     * date up by one day, you can achieve it by calling:
203.2016 +     * <p>roll(Calendar.DATE, true).
203.2017 +     * When rolling on the year or Calendar.YEAR field, it will roll the year
203.2018 +     * value in the range between 1 and the value returned by calling
203.2019 +     * <code>getMaximum(Calendar.YEAR)</code>.
203.2020 +     * When rolling on the month or Calendar.MONTH field, other fields like
203.2021 +     * date might conflict and, need to be changed. For instance,
203.2022 +     * rolling the month on the date 01/31/96 will result in 02/29/96.
203.2023 +     * When rolling on the hour-in-day or Calendar.HOUR_OF_DAY field, it will
203.2024 +     * roll the hour value in the range between 0 and 23, which is zero-based.
203.2025 +     *
203.2026 +     * @param field the time field.
203.2027 +     * @param up indicates if the value of the specified time field is to be
203.2028 +     * rolled up or rolled down. Use true if rolling up, false otherwise.
203.2029 +     * @see Calendar#add(int,int)
203.2030 +     * @see Calendar#set(int,int)
203.2031 +     */
203.2032 +    abstract public void roll(int field, boolean up);
203.2033 +
203.2034 +    /**
203.2035 +     * Adds the specified (signed) amount to the specified calendar field
203.2036 +     * without changing larger fields.  A negative amount means to roll
203.2037 +     * down.
203.2038 +     *
203.2039 +     * <p>NOTE:  This default implementation on <code>Calendar</code> just repeatedly calls the
203.2040 +     * version of {@link #roll(int,boolean) roll()} that rolls by one unit.  This may not
203.2041 +     * always do the right thing.  For example, if the <code>DAY_OF_MONTH</code> field is 31,
203.2042 +     * rolling through February will leave it set to 28.  The <code>GregorianCalendar</code>
203.2043 +     * version of this function takes care of this problem.  Other subclasses
203.2044 +     * should also provide overrides of this function that do the right thing.
203.2045 +     *
203.2046 +     * @param field the calendar field.
203.2047 +     * @param amount the signed amount to add to the calendar <code>field</code>.
203.2048 +     * @since 1.2
203.2049 +     * @see #roll(int,boolean)
203.2050 +     * @see #add(int,int)
203.2051 +     * @see #set(int,int)
203.2052 +     */
203.2053 +    public void roll(int field, int amount)
203.2054 +    {
203.2055 +        while (amount > 0) {
203.2056 +            roll(field, true);
203.2057 +            amount--;
203.2058 +        }
203.2059 +        while (amount < 0) {
203.2060 +            roll(field, false);
203.2061 +            amount++;
203.2062 +        }
203.2063 +    }
203.2064 +
203.2065 +    /**
203.2066 +     * Sets the time zone with the given time zone value.
203.2067 +     *
203.2068 +     * @param value the given time zone.
203.2069 +     */
203.2070 +    public void setTimeZone(TimeZone value)
203.2071 +    {
203.2072 +        zone = value;
203.2073 +        sharedZone = false;
203.2074 +        /* Recompute the fields from the time using the new zone.  This also
203.2075 +         * works if isTimeSet is false (after a call to set()).  In that case
203.2076 +         * the time will be computed from the fields using the new zone, then
203.2077 +         * the fields will get recomputed from that.  Consider the sequence of
203.2078 +         * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
203.2079 +         * Is cal set to 1 o'clock EST or 1 o'clock PST?  Answer: PST.  More
203.2080 +         * generally, a call to setTimeZone() affects calls to set() BEFORE AND
203.2081 +         * AFTER it up to the next call to complete().
203.2082 +         */
203.2083 +        areAllFieldsSet = areFieldsSet = false;
203.2084 +    }
203.2085 +
203.2086 +    /**
203.2087 +     * Gets the time zone.
203.2088 +     *
203.2089 +     * @return the time zone object associated with this calendar.
203.2090 +     */
203.2091 +    public TimeZone getTimeZone()
203.2092 +    {
203.2093 +        // If the TimeZone object is shared by other Calendar instances, then
203.2094 +        // create a clone.
203.2095 +        if (sharedZone) {
203.2096 +            zone = (TimeZone) zone.clone();
203.2097 +            sharedZone = false;
203.2098 +        }
203.2099 +        return zone;
203.2100 +    }
203.2101 +
203.2102 +    /**
203.2103 +     * Returns the time zone (without cloning).
203.2104 +     */
203.2105 +    TimeZone getZone() {
203.2106 +        return zone;
203.2107 +    }
203.2108 +
203.2109 +    /**
203.2110 +     * Sets the sharedZone flag to <code>shared</code>.
203.2111 +     */
203.2112 +    void setZoneShared(boolean shared) {
203.2113 +        sharedZone = shared;
203.2114 +    }
203.2115 +
203.2116 +    /**
203.2117 +     * Specifies whether or not date/time interpretation is to be lenient.  With
203.2118 +     * lenient interpretation, a date such as "February 942, 1996" will be
203.2119 +     * treated as being equivalent to the 941st day after February 1, 1996.
203.2120 +     * With strict (non-lenient) interpretation, such dates will cause an exception to be
203.2121 +     * thrown. The default is lenient.
203.2122 +     *
203.2123 +     * @param lenient <code>true</code> if the lenient mode is to be turned
203.2124 +     * on; <code>false</code> if it is to be turned off.
203.2125 +     * @see #isLenient()
203.2126 +     * @see java.text.DateFormat#setLenient
203.2127 +     */
203.2128 +    public void setLenient(boolean lenient)
203.2129 +    {
203.2130 +        this.lenient = lenient;
203.2131 +    }
203.2132 +
203.2133 +    /**
203.2134 +     * Tells whether date/time interpretation is to be lenient.
203.2135 +     *
203.2136 +     * @return <code>true</code> if the interpretation mode of this calendar is lenient;
203.2137 +     * <code>false</code> otherwise.
203.2138 +     * @see #setLenient(boolean)
203.2139 +     */
203.2140 +    public boolean isLenient()
203.2141 +    {
203.2142 +        return lenient;
203.2143 +    }
203.2144 +
203.2145 +    /**
203.2146 +     * Sets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S.,
203.2147 +     * <code>MONDAY</code> in France.
203.2148 +     *
203.2149 +     * @param value the given first day of the week.
203.2150 +     * @see #getFirstDayOfWeek()
203.2151 +     * @see #getMinimalDaysInFirstWeek()
203.2152 +     */
203.2153 +    public void setFirstDayOfWeek(int value)
203.2154 +    {
203.2155 +        if (firstDayOfWeek == value) {
203.2156 +            return;
203.2157 +        }
203.2158 +        firstDayOfWeek = value;
203.2159 +        invalidateWeekFields();
203.2160 +    }
203.2161 +
203.2162 +    /**
203.2163 +     * Gets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S.,
203.2164 +     * <code>MONDAY</code> in France.
203.2165 +     *
203.2166 +     * @return the first day of the week.
203.2167 +     * @see #setFirstDayOfWeek(int)
203.2168 +     * @see #getMinimalDaysInFirstWeek()
203.2169 +     */
203.2170 +    public int getFirstDayOfWeek()
203.2171 +    {
203.2172 +        return firstDayOfWeek;
203.2173 +    }
203.2174 +
203.2175 +    /**
203.2176 +     * Sets what the minimal days required in the first week of the year are;
203.2177 +     * For example, if the first week is defined as one that contains the first
203.2178 +     * day of the first month of a year, call this method with value 1. If it
203.2179 +     * must be a full week, use value 7.
203.2180 +     *
203.2181 +     * @param value the given minimal days required in the first week
203.2182 +     * of the year.
203.2183 +     * @see #getMinimalDaysInFirstWeek()
203.2184 +     */
203.2185 +    public void setMinimalDaysInFirstWeek(int value)
203.2186 +    {
203.2187 +        if (minimalDaysInFirstWeek == value) {
203.2188 +            return;
203.2189 +        }
203.2190 +        minimalDaysInFirstWeek = value;
203.2191 +        invalidateWeekFields();
203.2192 +    }
203.2193 +
203.2194 +    /**
203.2195 +     * Gets what the minimal days required in the first week of the year are;
203.2196 +     * e.g., if the first week is defined as one that contains the first day
203.2197 +     * of the first month of a year, this method returns 1. If
203.2198 +     * the minimal days required must be a full week, this method
203.2199 +     * returns 7.
203.2200 +     *
203.2201 +     * @return the minimal days required in the first week of the year.
203.2202 +     * @see #setMinimalDaysInFirstWeek(int)
203.2203 +     */
203.2204 +    public int getMinimalDaysInFirstWeek()
203.2205 +    {
203.2206 +        return minimalDaysInFirstWeek;
203.2207 +    }
203.2208 +
203.2209 +    /**
203.2210 +     * Returns whether this {@code Calendar} supports week dates.
203.2211 +     *
203.2212 +     * <p>The default implementation of this method returns {@code false}.
203.2213 +     *
203.2214 +     * @return {@code true} if this {@code Calendar} supports week dates;
203.2215 +     *         {@code false} otherwise.
203.2216 +     * @see #getWeekYear()
203.2217 +     * @see #setWeekDate(int,int,int)
203.2218 +     * @see #getWeeksInWeekYear()
203.2219 +     * @since 1.7
203.2220 +     */
203.2221 +    public boolean isWeekDateSupported() {
203.2222 +        return false;
203.2223 +    }
203.2224 +
203.2225 +    /**
203.2226 +     * Returns the week year represented by this {@code Calendar}. The
203.2227 +     * week year is in sync with the week cycle. The {@linkplain
203.2228 +     * #getFirstDayOfWeek() first day of the first week} is the first
203.2229 +     * day of the week year.
203.2230 +     *
203.2231 +     * <p>The default implementation of this method throws an
203.2232 +     * {@link UnsupportedOperationException}.
203.2233 +     *
203.2234 +     * @return the week year of this {@code Calendar}
203.2235 +     * @exception UnsupportedOperationException
203.2236 +     *            if any week year numbering isn't supported
203.2237 +     *            in this {@code Calendar}.
203.2238 +     * @see #isWeekDateSupported()
203.2239 +     * @see #getFirstDayOfWeek()
203.2240 +     * @see #getMinimalDaysInFirstWeek()
203.2241 +     * @since 1.7
203.2242 +     */
203.2243 +    public int getWeekYear() {
203.2244 +        throw new UnsupportedOperationException();
203.2245 +    }
203.2246 +
203.2247 +    /**
203.2248 +     * Sets the date of this {@code Calendar} with the the given date
203.2249 +     * specifiers - week year, week of year, and day of week.
203.2250 +     *
203.2251 +     * <p>Unlike the {@code set} method, all of the calendar fields
203.2252 +     * and {@code time} values are calculated upon return.
203.2253 +     *
203.2254 +     * <p>If {@code weekOfYear} is out of the valid week-of-year range
203.2255 +     * in {@code weekYear}, the {@code weekYear} and {@code
203.2256 +     * weekOfYear} values are adjusted in lenient mode, or an {@code
203.2257 +     * IllegalArgumentException} is thrown in non-lenient mode.
203.2258 +     *
203.2259 +     * <p>The default implementation of this method throws an
203.2260 +     * {@code UnsupportedOperationException}.
203.2261 +     *
203.2262 +     * @param weekYear   the week year
203.2263 +     * @param weekOfYear the week number based on {@code weekYear}
203.2264 +     * @param dayOfWeek  the day of week value: one of the constants
203.2265 +     *                   for the {@link #DAY_OF_WEEK} field: {@link
203.2266 +     *                   #SUNDAY}, ..., {@link #SATURDAY}.
203.2267 +     * @exception IllegalArgumentException
203.2268 +     *            if any of the given date specifiers is invalid
203.2269 +     *            or any of the calendar fields are inconsistent
203.2270 +     *            with the given date specifiers in non-lenient mode
203.2271 +     * @exception UnsupportedOperationException
203.2272 +     *            if any week year numbering isn't supported in this
203.2273 +     *            {@code Calendar}.
203.2274 +     * @see #isWeekDateSupported()
203.2275 +     * @see #getFirstDayOfWeek()
203.2276 +     * @see #getMinimalDaysInFirstWeek()
203.2277 +     * @since 1.7
203.2278 +     */
203.2279 +    public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
203.2280 +        throw new UnsupportedOperationException();
203.2281 +    }
203.2282 +
203.2283 +    /**
203.2284 +     * Returns the number of weeks in the week year represented by this
203.2285 +     * {@code Calendar}.
203.2286 +     *
203.2287 +     * <p>The default implementation of this method throws an
203.2288 +     * {@code UnsupportedOperationException}.
203.2289 +     *
203.2290 +     * @return the number of weeks in the week year.
203.2291 +     * @exception UnsupportedOperationException
203.2292 +     *            if any week year numbering isn't supported in this
203.2293 +     *            {@code Calendar}.
203.2294 +     * @see #WEEK_OF_YEAR
203.2295 +     * @see #isWeekDateSupported()
203.2296 +     * @see #getWeekYear()
203.2297 +     * @see #getActualMaximum(int)
203.2298 +     * @since 1.7
203.2299 +     */
203.2300 +    public int getWeeksInWeekYear() {
203.2301 +        throw new UnsupportedOperationException();
203.2302 +    }
203.2303 +
203.2304 +    /**
203.2305 +     * Returns the minimum value for the given calendar field of this
203.2306 +     * <code>Calendar</code> instance. The minimum value is defined as
203.2307 +     * the smallest value returned by the {@link #get(int) get} method
203.2308 +     * for any possible time value.  The minimum value depends on
203.2309 +     * calendar system specific parameters of the instance.
203.2310 +     *
203.2311 +     * @param field the calendar field.
203.2312 +     * @return the minimum value for the given calendar field.
203.2313 +     * @see #getMaximum(int)
203.2314 +     * @see #getGreatestMinimum(int)
203.2315 +     * @see #getLeastMaximum(int)
203.2316 +     * @see #getActualMinimum(int)
203.2317 +     * @see #getActualMaximum(int)
203.2318 +     */
203.2319 +    abstract public int getMinimum(int field);
203.2320 +
203.2321 +    /**
203.2322 +     * Returns the maximum value for the given calendar field of this
203.2323 +     * <code>Calendar</code> instance. The maximum value is defined as
203.2324 +     * the largest value returned by the {@link #get(int) get} method
203.2325 +     * for any possible time value. The maximum value depends on
203.2326 +     * calendar system specific parameters of the instance.
203.2327 +     *
203.2328 +     * @param field the calendar field.
203.2329 +     * @return the maximum value for the given calendar field.
203.2330 +     * @see #getMinimum(int)
203.2331 +     * @see #getGreatestMinimum(int)
203.2332 +     * @see #getLeastMaximum(int)
203.2333 +     * @see #getActualMinimum(int)
203.2334 +     * @see #getActualMaximum(int)
203.2335 +     */
203.2336 +    abstract public int getMaximum(int field);
203.2337 +
203.2338 +    /**
203.2339 +     * Returns the highest minimum value for the given calendar field
203.2340 +     * of this <code>Calendar</code> instance. The highest minimum
203.2341 +     * value is defined as the largest value returned by {@link
203.2342 +     * #getActualMinimum(int)} for any possible time value. The
203.2343 +     * greatest minimum value depends on calendar system specific
203.2344 +     * parameters of the instance.
203.2345 +     *
203.2346 +     * @param field the calendar field.
203.2347 +     * @return the highest minimum value for the given calendar field.
203.2348 +     * @see #getMinimum(int)
203.2349 +     * @see #getMaximum(int)
203.2350 +     * @see #getLeastMaximum(int)
203.2351 +     * @see #getActualMinimum(int)
203.2352 +     * @see #getActualMaximum(int)
203.2353 +     */
203.2354 +    abstract public int getGreatestMinimum(int field);
203.2355 +
203.2356 +    /**
203.2357 +     * Returns the lowest maximum value for the given calendar field
203.2358 +     * of this <code>Calendar</code> instance. The lowest maximum
203.2359 +     * value is defined as the smallest value returned by {@link
203.2360 +     * #getActualMaximum(int)} for any possible time value. The least
203.2361 +     * maximum value depends on calendar system specific parameters of
203.2362 +     * the instance. For example, a <code>Calendar</code> for the
203.2363 +     * Gregorian calendar system returns 28 for the
203.2364 +     * <code>DAY_OF_MONTH</code> field, because the 28th is the last
203.2365 +     * day of the shortest month of this calendar, February in a
203.2366 +     * common year.
203.2367 +     *
203.2368 +     * @param field the calendar field.
203.2369 +     * @return the lowest maximum value for the given calendar field.
203.2370 +     * @see #getMinimum(int)
203.2371 +     * @see #getMaximum(int)
203.2372 +     * @see #getGreatestMinimum(int)
203.2373 +     * @see #getActualMinimum(int)
203.2374 +     * @see #getActualMaximum(int)
203.2375 +     */
203.2376 +    abstract public int getLeastMaximum(int field);
203.2377 +
203.2378 +    /**
203.2379 +     * Returns the minimum value that the specified calendar field
203.2380 +     * could have, given the time value of this <code>Calendar</code>.
203.2381 +     *
203.2382 +     * <p>The default implementation of this method uses an iterative
203.2383 +     * algorithm to determine the actual minimum value for the
203.2384 +     * calendar field. Subclasses should, if possible, override this
203.2385 +     * with a more efficient implementation - in many cases, they can
203.2386 +     * simply return <code>getMinimum()</code>.
203.2387 +     *
203.2388 +     * @param field the calendar field
203.2389 +     * @return the minimum of the given calendar field for the time
203.2390 +     * value of this <code>Calendar</code>
203.2391 +     * @see #getMinimum(int)
203.2392 +     * @see #getMaximum(int)
203.2393 +     * @see #getGreatestMinimum(int)
203.2394 +     * @see #getLeastMaximum(int)
203.2395 +     * @see #getActualMaximum(int)
203.2396 +     * @since 1.2
203.2397 +     */
203.2398 +    public int getActualMinimum(int field) {
203.2399 +        int fieldValue = getGreatestMinimum(field);
203.2400 +        int endValue = getMinimum(field);
203.2401 +
203.2402 +        // if we know that the minimum value is always the same, just return it
203.2403 +        if (fieldValue == endValue) {
203.2404 +            return fieldValue;
203.2405 +        }
203.2406 +
203.2407 +        // clone the calendar so we don't mess with the real one, and set it to
203.2408 +        // accept anything for the field values
203.2409 +        Calendar work = (Calendar)this.clone();
203.2410 +        work.setLenient(true);
203.2411 +
203.2412 +        // now try each value from getLeastMaximum() to getMaximum() one by one until
203.2413 +        // we get a value that normalizes to another value.  The last value that
203.2414 +        // normalizes to itself is the actual minimum for the current date
203.2415 +        int result = fieldValue;
203.2416 +
203.2417 +        do {
203.2418 +            work.set(field, fieldValue);
203.2419 +            if (work.get(field) != fieldValue) {
203.2420 +                break;
203.2421 +            } else {
203.2422 +                result = fieldValue;
203.2423 +                fieldValue--;
203.2424 +            }
203.2425 +        } while (fieldValue >= endValue);
203.2426 +
203.2427 +        return result;
203.2428 +    }
203.2429 +
203.2430 +    /**
203.2431 +     * Returns the maximum value that the specified calendar field
203.2432 +     * could have, given the time value of this
203.2433 +     * <code>Calendar</code>. For example, the actual maximum value of
203.2434 +     * the <code>MONTH</code> field is 12 in some years, and 13 in
203.2435 +     * other years in the Hebrew calendar system.
203.2436 +     *
203.2437 +     * <p>The default implementation of this method uses an iterative
203.2438 +     * algorithm to determine the actual maximum value for the
203.2439 +     * calendar field. Subclasses should, if possible, override this
203.2440 +     * with a more efficient implementation.
203.2441 +     *
203.2442 +     * @param field the calendar field
203.2443 +     * @return the maximum of the given calendar field for the time
203.2444 +     * value of this <code>Calendar</code>
203.2445 +     * @see #getMinimum(int)
203.2446 +     * @see #getMaximum(int)
203.2447 +     * @see #getGreatestMinimum(int)
203.2448 +     * @see #getLeastMaximum(int)
203.2449 +     * @see #getActualMinimum(int)
203.2450 +     * @since 1.2
203.2451 +     */
203.2452 +    public int getActualMaximum(int field) {
203.2453 +        int fieldValue = getLeastMaximum(field);
203.2454 +        int endValue = getMaximum(field);
203.2455 +
203.2456 +        // if we know that the maximum value is always the same, just return it.
203.2457 +        if (fieldValue == endValue) {
203.2458 +            return fieldValue;
203.2459 +        }
203.2460 +
203.2461 +        // clone the calendar so we don't mess with the real one, and set it to
203.2462 +        // accept anything for the field values.
203.2463 +        Calendar work = (Calendar)this.clone();
203.2464 +        work.setLenient(true);
203.2465 +
203.2466 +        // if we're counting weeks, set the day of the week to Sunday.  We know the
203.2467 +        // last week of a month or year will contain the first day of the week.
203.2468 +        if (field == WEEK_OF_YEAR || field == WEEK_OF_MONTH)
203.2469 +            work.set(DAY_OF_WEEK, firstDayOfWeek);
203.2470 +
203.2471 +        // now try each value from getLeastMaximum() to getMaximum() one by one until
203.2472 +        // we get a value that normalizes to another value.  The last value that
203.2473 +        // normalizes to itself is the actual maximum for the current date
203.2474 +        int result = fieldValue;
203.2475 +
203.2476 +        do {
203.2477 +            work.set(field, fieldValue);
203.2478 +            if (work.get(field) != fieldValue) {
203.2479 +                break;
203.2480 +            } else {
203.2481 +                result = fieldValue;
203.2482 +                fieldValue++;
203.2483 +            }
203.2484 +        } while (fieldValue <= endValue);
203.2485 +
203.2486 +        return result;
203.2487 +    }
203.2488 +
203.2489 +    /**
203.2490 +     * Creates and returns a copy of this object.
203.2491 +     *
203.2492 +     * @return a copy of this object.
203.2493 +     */
203.2494 +    public Object clone()
203.2495 +    {
203.2496 +        try {
203.2497 +            Calendar other = (Calendar) super.clone();
203.2498 +
203.2499 +            other.fields = new int[FIELD_COUNT];
203.2500 +            other.isSet = new boolean[FIELD_COUNT];
203.2501 +            other.stamp = new int[FIELD_COUNT];
203.2502 +            for (int i = 0; i < FIELD_COUNT; i++) {
203.2503 +                other.fields[i] = fields[i];
203.2504 +                other.stamp[i] = stamp[i];
203.2505 +                other.isSet[i] = isSet[i];
203.2506 +            }
203.2507 +            other.zone = (TimeZone) zone.clone();
203.2508 +            return other;
203.2509 +        }
203.2510 +        catch (CloneNotSupportedException e) {
203.2511 +            // this shouldn't happen, since we are Cloneable
203.2512 +            throw new InternalError();
203.2513 +        }
203.2514 +    }
203.2515 +
203.2516 +    private static final String[] FIELD_NAME = {
203.2517 +        "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
203.2518 +        "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
203.2519 +        "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
203.2520 +        "DST_OFFSET"
203.2521 +    };
203.2522 +
203.2523 +    /**
203.2524 +     * Returns the name of the specified calendar field.
203.2525 +     *
203.2526 +     * @param field the calendar field
203.2527 +     * @return the calendar field name
203.2528 +     * @exception IndexOutOfBoundsException if <code>field</code> is negative,
203.2529 +     * equal to or greater then <code>FIELD_COUNT</code>.
203.2530 +     */
203.2531 +    static final String getFieldName(int field) {
203.2532 +        return FIELD_NAME[field];
203.2533 +    }
203.2534 +
203.2535 +    /**
203.2536 +     * Return a string representation of this calendar. This method
203.2537 +     * is intended to be used only for debugging purposes, and the
203.2538 +     * format of the returned string may vary between implementations.
203.2539 +     * The returned string may be empty but may not be <code>null</code>.
203.2540 +     *
203.2541 +     * @return  a string representation of this calendar.
203.2542 +     */
203.2543 +    public String toString() {
203.2544 +        // NOTE: BuddhistCalendar.toString() interprets the string
203.2545 +        // produced by this method so that the Gregorian year number
203.2546 +        // is substituted by its B.E. year value. It relies on
203.2547 +        // "...,YEAR=<year>,..." or "...,YEAR=?,...".
203.2548 +        StringBuilder buffer = new StringBuilder(800);
203.2549 +        buffer.append(getClass().getName()).append('[');
203.2550 +        appendValue(buffer, "time", isTimeSet, time);
203.2551 +        buffer.append(",areFieldsSet=").append(areFieldsSet);
203.2552 +        buffer.append(",areAllFieldsSet=").append(areAllFieldsSet);
203.2553 +        buffer.append(",lenient=").append(lenient);
203.2554 +        buffer.append(",zone=").append(zone);
203.2555 +        appendValue(buffer, ",firstDayOfWeek", true, (long) firstDayOfWeek);
203.2556 +        appendValue(buffer, ",minimalDaysInFirstWeek", true, (long) minimalDaysInFirstWeek);
203.2557 +        for (int i = 0; i < FIELD_COUNT; ++i) {
203.2558 +            buffer.append(',');
203.2559 +            appendValue(buffer, FIELD_NAME[i], isSet(i), (long) fields[i]);
203.2560 +        }
203.2561 +        buffer.append(']');
203.2562 +        return buffer.toString();
203.2563 +    }
203.2564 +
203.2565 +    // =======================privates===============================
203.2566 +
203.2567 +    private static final void appendValue(StringBuilder sb, String item, boolean valid, long value) {
203.2568 +        sb.append(item).append('=');
203.2569 +        if (valid) {
203.2570 +            sb.append(value);
203.2571 +        } else {
203.2572 +            sb.append('?');
203.2573 +        }
203.2574 +    }
203.2575 +
203.2576 +    /**
203.2577 +     * Both firstDayOfWeek and minimalDaysInFirstWeek are locale-dependent.
203.2578 +     * They are used to figure out the week count for a specific date for
203.2579 +     * a given locale. These must be set when a Calendar is constructed.
203.2580 +     * @param desiredLocale the given locale.
203.2581 +     */
203.2582 +    private void setWeekCountData(Locale desiredLocale)
203.2583 +    {
203.2584 +        /* try to get the Locale data from the cache */
203.2585 +        int[] data = cachedLocaleData.get(desiredLocale);
203.2586 +        if (data == null) {  /* cache miss */
203.2587 +//            ResourceBundle bundle = LocaleData.getCalendarData(desiredLocale);
203.2588 +            data = new int[2];
203.2589 +//            data[0] = Integer.parseInt(bundle.getString("firstDayOfWeek"));
203.2590 +//            data[1] = Integer.parseInt(bundle.getString("minimalDaysInFirstWeek"));
203.2591 +            cachedLocaleData.putIfAbsent(desiredLocale, data);
203.2592 +        }
203.2593 +        firstDayOfWeek = data[0];
203.2594 +        minimalDaysInFirstWeek = data[1];
203.2595 +    }
203.2596 +
203.2597 +    /**
203.2598 +     * Recomputes the time and updates the status fields isTimeSet
203.2599 +     * and areFieldsSet.  Callers should check isTimeSet and only
203.2600 +     * call this method if isTimeSet is false.
203.2601 +     */
203.2602 +    private void updateTime() {
203.2603 +        computeTime();
203.2604 +        // The areFieldsSet and areAllFieldsSet values are no longer
203.2605 +        // controlled here (as of 1.5).
203.2606 +        isTimeSet = true;
203.2607 +    }
203.2608 +
203.2609 +    private int compareTo(long t) {
203.2610 +        long thisTime = getMillisOf(this);
203.2611 +        return (thisTime > t) ? 1 : (thisTime == t) ? 0 : -1;
203.2612 +    }
203.2613 +
203.2614 +    private static final long getMillisOf(Calendar calendar) {
203.2615 +        if (calendar.isTimeSet) {
203.2616 +            return calendar.time;
203.2617 +        }
203.2618 +        Calendar cal = (Calendar) calendar.clone();
203.2619 +        cal.setLenient(true);
203.2620 +        return cal.getTimeInMillis();
203.2621 +    }
203.2622 +
203.2623 +    /**
203.2624 +     * Adjusts the stamp[] values before nextStamp overflow. nextStamp
203.2625 +     * is set to the next stamp value upon the return.
203.2626 +     */
203.2627 +    private final void adjustStamp() {
203.2628 +        int max = MINIMUM_USER_STAMP;
203.2629 +        int newStamp = MINIMUM_USER_STAMP;
203.2630 +
203.2631 +        for (;;) {
203.2632 +            int min = Integer.MAX_VALUE;
203.2633 +            for (int i = 0; i < stamp.length; i++) {
203.2634 +                int v = stamp[i];
203.2635 +                if (v >= newStamp && min > v) {
203.2636 +                    min = v;
203.2637 +                }
203.2638 +                if (max < v) {
203.2639 +                    max = v;
203.2640 +                }
203.2641 +            }
203.2642 +            if (max != min && min == Integer.MAX_VALUE) {
203.2643 +                break;
203.2644 +            }
203.2645 +            for (int i = 0; i < stamp.length; i++) {
203.2646 +                if (stamp[i] == min) {
203.2647 +                    stamp[i] = newStamp;
203.2648 +                }
203.2649 +            }
203.2650 +            newStamp++;
203.2651 +            if (min == max) {
203.2652 +                break;
203.2653 +            }
203.2654 +        }
203.2655 +        nextStamp = newStamp;
203.2656 +    }
203.2657 +
203.2658 +    /**
203.2659 +     * Sets the WEEK_OF_MONTH and WEEK_OF_YEAR fields to new values with the
203.2660 +     * new parameter value if they have been calculated internally.
203.2661 +     */
203.2662 +    private void invalidateWeekFields()
203.2663 +    {
203.2664 +        if (stamp[WEEK_OF_MONTH] != COMPUTED &&
203.2665 +            stamp[WEEK_OF_YEAR] != COMPUTED) {
203.2666 +            return;
203.2667 +        }
203.2668 +
203.2669 +        // We have to check the new values of these fields after changing
203.2670 +        // firstDayOfWeek and/or minimalDaysInFirstWeek. If the field values
203.2671 +        // have been changed, then set the new values. (4822110)
203.2672 +        Calendar cal = (Calendar) clone();
203.2673 +        cal.setLenient(true);
203.2674 +        cal.clear(WEEK_OF_MONTH);
203.2675 +        cal.clear(WEEK_OF_YEAR);
203.2676 +
203.2677 +        if (stamp[WEEK_OF_MONTH] == COMPUTED) {
203.2678 +            int weekOfMonth = cal.get(WEEK_OF_MONTH);
203.2679 +            if (fields[WEEK_OF_MONTH] != weekOfMonth) {
203.2680 +                fields[WEEK_OF_MONTH] = weekOfMonth;
203.2681 +            }
203.2682 +        }
203.2683 +
203.2684 +        if (stamp[WEEK_OF_YEAR] == COMPUTED) {
203.2685 +            int weekOfYear = cal.get(WEEK_OF_YEAR);
203.2686 +            if (fields[WEEK_OF_YEAR] != weekOfYear) {
203.2687 +                fields[WEEK_OF_YEAR] = weekOfYear;
203.2688 +            }
203.2689 +        }
203.2690 +    }
203.2691 +
203.2692 +    /**
203.2693 +     * Save the state of this object to a stream (i.e., serialize it).
203.2694 +     *
203.2695 +     * Ideally, <code>Calendar</code> would only write out its state data and
203.2696 +     * the current time, and not write any field data out, such as
203.2697 +     * <code>fields[]</code>, <code>isTimeSet</code>, <code>areFieldsSet</code>,
203.2698 +     * and <code>isSet[]</code>.  <code>nextStamp</code> also should not be part
203.2699 +     * of the persistent state. Unfortunately, this didn't happen before JDK 1.1
203.2700 +     * shipped. To be compatible with JDK 1.1, we will always have to write out
203.2701 +     * the field values and state flags.  However, <code>nextStamp</code> can be
203.2702 +     * removed from the serialization stream; this will probably happen in the
203.2703 +     * near future.
203.2704 +     */
203.2705 +    private void writeObject(ObjectOutputStream stream)
203.2706 +         throws IOException
203.2707 +    {
203.2708 +        // Try to compute the time correctly, for the future (stream
203.2709 +        // version 2) in which we don't write out fields[] or isSet[].
203.2710 +        if (!isTimeSet) {
203.2711 +            try {
203.2712 +                updateTime();
203.2713 +            }
203.2714 +            catch (IllegalArgumentException e) {}
203.2715 +        }
203.2716 +
203.2717 +        // If this Calendar has a ZoneInfo, save it and set a
203.2718 +        // SimpleTimeZone equivalent (as a single DST schedule) for
203.2719 +        // backward compatibility.
203.2720 +        TimeZone savedZone = null;
203.2721 +//        if (zone instanceof ZoneInfo) {
203.2722 +//            SimpleTimeZone stz = ((ZoneInfo)zone).getLastRuleInstance();
203.2723 +//            if (stz == null) {
203.2724 +//                stz = new SimpleTimeZone(zone.getRawOffset(), zone.getID());
203.2725 +//            }
203.2726 +//            savedZone = zone;
203.2727 +//            zone = stz;
203.2728 +//        }
203.2729 +
203.2730 +        // Write out the 1.1 FCS object.
203.2731 +        stream.defaultWriteObject();
203.2732 +
203.2733 +        // Write out the ZoneInfo object
203.2734 +        // 4802409: we write out even if it is null, a temporary workaround
203.2735 +        // the real fix for bug 4844924 in corba-iiop
203.2736 +        stream.writeObject(savedZone);
203.2737 +        if (savedZone != null) {
203.2738 +            zone = savedZone;
203.2739 +        }
203.2740 +    }
203.2741 +
203.2742 +    /**
203.2743 +     * Reconstitutes this object from a stream (i.e., deserialize it).
203.2744 +     */
203.2745 +    private void readObject(ObjectInputStream stream)
203.2746 +         throws IOException, ClassNotFoundException
203.2747 +    {
203.2748 +        final ObjectInputStream input = stream;
203.2749 +        input.defaultReadObject();
203.2750 +
203.2751 +        stamp = new int[FIELD_COUNT];
203.2752 +
203.2753 +        // Starting with version 2 (not implemented yet), we expect that
203.2754 +        // fields[], isSet[], isTimeSet, and areFieldsSet may not be
203.2755 +        // streamed out anymore.  We expect 'time' to be correct.
203.2756 +        if (serialVersionOnStream >= 2)
203.2757 +        {
203.2758 +            isTimeSet = true;
203.2759 +            if (fields == null) fields = new int[FIELD_COUNT];
203.2760 +            if (isSet == null) isSet = new boolean[FIELD_COUNT];
203.2761 +        }
203.2762 +        else if (serialVersionOnStream >= 0)
203.2763 +        {
203.2764 +            for (int i=0; i<FIELD_COUNT; ++i)
203.2765 +                stamp[i] = isSet[i] ? COMPUTED : UNSET;
203.2766 +        }
203.2767 +
203.2768 +        serialVersionOnStream = currentSerialVersion;
203.2769 +
203.2770 +        // If there's a ZoneInfo object, use it for zone.
203.2771 +        TimeZone zi = null;
203.2772 +//        try {
203.2773 +//            zi = AccessController.doPrivileged(
203.2774 +//                    new PrivilegedExceptionAction<ZoneInfo>() {
203.2775 +//                        public ZoneInfo run() throws Exception {
203.2776 +//                            return (ZoneInfo) input.readObject();
203.2777 +//                        }
203.2778 +//                    },
203.2779 +//                    CalendarAccessControlContext.INSTANCE);
203.2780 +//        } catch (PrivilegedActionException pae) {
203.2781 +//            Exception e = pae.getException();
203.2782 +//            if (!(e instanceof OptionalDataException)) {
203.2783 +//                if (e instanceof RuntimeException) {
203.2784 +//                    throw (RuntimeException) e;
203.2785 +//                } else if (e instanceof IOException) {
203.2786 +//                    throw (IOException) e;
203.2787 +//                } else if (e instanceof ClassNotFoundException) {
203.2788 +//                    throw (ClassNotFoundException) e;
203.2789 +//                }
203.2790 +//                throw new RuntimeException(e);
203.2791 +//            }
203.2792 +//        }
203.2793 +        if (zi != null) {
203.2794 +            zone = zi;
203.2795 +        }
203.2796 +
203.2797 +        // If the deserialized object has a SimpleTimeZone, try to
203.2798 +        // replace it with a ZoneInfo equivalent (as of 1.4) in order
203.2799 +        // to be compatible with the SimpleTimeZone-based
203.2800 +        // implementation as much as possible.
203.2801 +        if (zone instanceof SimpleTimeZone) {
203.2802 +            String id = zone.getID();
203.2803 +            TimeZone tz = TimeZone.getTimeZone(id);
203.2804 +            if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {
203.2805 +                zone = tz;
203.2806 +            }
203.2807 +        }
203.2808 +    }
203.2809 +}
   204.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   204.2 +++ b/rt/emul/compact/src/main/java/java/util/Currency.java	Wed Apr 30 15:04:10 2014 +0200
   204.3 @@ -0,0 +1,735 @@
   204.4 +/*
   204.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   204.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   204.7 + *
   204.8 + * This code is free software; you can redistribute it and/or modify it
   204.9 + * under the terms of the GNU General Public License version 2 only, as
  204.10 + * published by the Free Software Foundation.  Oracle designates this
  204.11 + * particular file as subject to the "Classpath" exception as provided
  204.12 + * by Oracle in the LICENSE file that accompanied this code.
  204.13 + *
  204.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  204.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  204.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  204.17 + * version 2 for more details (a copy is included in the LICENSE file that
  204.18 + * accompanied this code).
  204.19 + *
  204.20 + * You should have received a copy of the GNU General Public License version
  204.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  204.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  204.23 + *
  204.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  204.25 + * or visit www.oracle.com if you need additional information or have any
  204.26 + * questions.
  204.27 + */
  204.28 +
  204.29 +package java.util;
  204.30 +
  204.31 +import java.io.BufferedInputStream;
  204.32 +import java.io.DataInputStream;
  204.33 +import java.io.File;
  204.34 +import java.io.FileInputStream;
  204.35 +import java.io.FileReader;
  204.36 +import java.io.IOException;
  204.37 +import java.io.Serializable;
  204.38 +import java.security.AccessController;
  204.39 +import java.security.PrivilegedAction;
  204.40 +import java.util.logging.Level;
  204.41 +import java.util.logging.Logger;
  204.42 +
  204.43 +
  204.44 +/**
  204.45 + * Represents a currency. Currencies are identified by their ISO 4217 currency
  204.46 + * codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html">
  204.47 + * ISO web site</a> for more information, including a table of
  204.48 + * currency codes.
  204.49 + * <p>
  204.50 + * The class is designed so that there's never more than one
  204.51 + * <code>Currency</code> instance for any given currency. Therefore, there's
  204.52 + * no public constructor. You obtain a <code>Currency</code> instance using
  204.53 + * the <code>getInstance</code> methods.
  204.54 + * <p>
  204.55 + * Users can supersede the Java runtime currency data by creating a properties
  204.56 + * file named <code>&lt;JAVA_HOME&gt;/lib/currency.properties</code>.  The contents
  204.57 + * of the properties file are key/value pairs of the ISO 3166 country codes
  204.58 + * and the ISO 4217 currency data respectively.  The value part consists of
  204.59 + * three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric
  204.60 + * code, and a minor unit.  Those three ISO 4217 values are separated by commas.
  204.61 + * The lines which start with '#'s are considered comment lines.  For example,
  204.62 + * <p>
  204.63 + * <code>
  204.64 + * #Sample currency properties<br>
  204.65 + * JP=JPZ,999,0
  204.66 + * </code>
  204.67 + * <p>
  204.68 + * will supersede the currency data for Japan.
  204.69 + *
  204.70 + * @since 1.4
  204.71 + */
  204.72 +public final class Currency implements Serializable {
  204.73 +
  204.74 +    private static final long serialVersionUID = -158308464356906721L;
  204.75 +
  204.76 +    /**
  204.77 +     * ISO 4217 currency code for this currency.
  204.78 +     *
  204.79 +     * @serial
  204.80 +     */
  204.81 +    private final String currencyCode;
  204.82 +
  204.83 +    /**
  204.84 +     * Default fraction digits for this currency.
  204.85 +     * Set from currency data tables.
  204.86 +     */
  204.87 +    transient private final int defaultFractionDigits;
  204.88 +
  204.89 +    /**
  204.90 +     * ISO 4217 numeric code for this currency.
  204.91 +     * Set from currency data tables.
  204.92 +     */
  204.93 +    transient private final int numericCode;
  204.94 +
  204.95 +
  204.96 +    // class data: instance map
  204.97 +
  204.98 +    private static HashMap<String, Currency> instances = new HashMap<String, Currency>(7);
  204.99 +    private static HashSet<Currency> available;
 204.100 +
 204.101 +
 204.102 +    // Class data: currency data obtained from currency.data file.
 204.103 +    // Purpose:
 204.104 +    // - determine valid country codes
 204.105 +    // - determine valid currency codes
 204.106 +    // - map country codes to currency codes
 204.107 +    // - obtain default fraction digits for currency codes
 204.108 +    //
 204.109 +    // sc = special case; dfd = default fraction digits
 204.110 +    // Simple countries are those where the country code is a prefix of the
 204.111 +    // currency code, and there are no known plans to change the currency.
 204.112 +    //
 204.113 +    // table formats:
 204.114 +    // - mainTable:
 204.115 +    //   - maps country code to 32-bit int
 204.116 +    //   - 26*26 entries, corresponding to [A-Z]*[A-Z]
 204.117 +    //   - \u007F -> not valid country
 204.118 +    //   - bits 18-31: unused
 204.119 +    //   - bits 8-17: numeric code (0 to 1023)
 204.120 +    //   - bit 7: 1 - special case, bits 0-4 indicate which one
 204.121 +    //            0 - simple country, bits 0-4 indicate final char of currency code
 204.122 +    //   - bits 5-6: fraction digits for simple countries, 0 for special cases
 204.123 +    //   - bits 0-4: final char for currency code for simple country, or ID of special case
 204.124 +    // - special case IDs:
 204.125 +    //   - 0: country has no currency
 204.126 +    //   - other: index into sc* arrays + 1
 204.127 +    // - scCutOverTimes: cut-over time in millis as returned by
 204.128 +    //   System.currentTimeMillis for special case countries that are changing
 204.129 +    //   currencies; Long.MAX_VALUE for countries that are not changing currencies
 204.130 +    // - scOldCurrencies: old currencies for special case countries
 204.131 +    // - scNewCurrencies: new currencies for special case countries that are
 204.132 +    //   changing currencies; null for others
 204.133 +    // - scOldCurrenciesDFD: default fraction digits for old currencies
 204.134 +    // - scNewCurrenciesDFD: default fraction digits for new currencies, 0 for
 204.135 +    //   countries that are not changing currencies
 204.136 +    // - otherCurrencies: concatenation of all currency codes that are not the
 204.137 +    //   main currency of a simple country, separated by "-"
 204.138 +    // - otherCurrenciesDFD: decimal format digits for currencies in otherCurrencies, same order
 204.139 +
 204.140 +    static int formatVersion;
 204.141 +    static int dataVersion;
 204.142 +    static int[] mainTable;
 204.143 +    static long[] scCutOverTimes;
 204.144 +    static String[] scOldCurrencies;
 204.145 +    static String[] scNewCurrencies;
 204.146 +    static int[] scOldCurrenciesDFD;
 204.147 +    static int[] scNewCurrenciesDFD;
 204.148 +    static int[] scOldCurrenciesNumericCode;
 204.149 +    static int[] scNewCurrenciesNumericCode;
 204.150 +    static String otherCurrencies;
 204.151 +    static int[] otherCurrenciesDFD;
 204.152 +    static int[] otherCurrenciesNumericCode;
 204.153 +
 204.154 +    // handy constants - must match definitions in GenerateCurrencyData
 204.155 +    // magic number
 204.156 +    private static final int MAGIC_NUMBER = 0x43757244;
 204.157 +    // number of characters from A to Z
 204.158 +    private static final int A_TO_Z = ('Z' - 'A') + 1;
 204.159 +    // entry for invalid country codes
 204.160 +    private static final int INVALID_COUNTRY_ENTRY = 0x007F;
 204.161 +    // entry for countries without currency
 204.162 +    private static final int COUNTRY_WITHOUT_CURRENCY_ENTRY = 0x0080;
 204.163 +    // mask for simple case country entries
 204.164 +    private static final int SIMPLE_CASE_COUNTRY_MASK = 0x0000;
 204.165 +    // mask for simple case country entry final character
 204.166 +    private static final int SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK = 0x001F;
 204.167 +    // mask for simple case country entry default currency digits
 204.168 +    private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK = 0x0060;
 204.169 +    // shift count for simple case country entry default currency digits
 204.170 +    private static final int SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT = 5;
 204.171 +    // mask for special case country entries
 204.172 +    private static final int SPECIAL_CASE_COUNTRY_MASK = 0x0080;
 204.173 +    // mask for special case country index
 204.174 +    private static final int SPECIAL_CASE_COUNTRY_INDEX_MASK = 0x001F;
 204.175 +    // delta from entry index component in main table to index into special case tables
 204.176 +    private static final int SPECIAL_CASE_COUNTRY_INDEX_DELTA = 1;
 204.177 +    // mask for distinguishing simple and special case countries
 204.178 +    private static final int COUNTRY_TYPE_MASK = SIMPLE_CASE_COUNTRY_MASK | SPECIAL_CASE_COUNTRY_MASK;
 204.179 +    // mask for the numeric code of the currency
 204.180 +    private static final int NUMERIC_CODE_MASK = 0x0003FF00;
 204.181 +    // shift count for the numeric code of the currency
 204.182 +    private static final int NUMERIC_CODE_SHIFT = 8;
 204.183 +
 204.184 +    // Currency data format version
 204.185 +    private static final int VALID_FORMAT_VERSION = 1;
 204.186 +
 204.187 +    static {
 204.188 +        AccessController.doPrivileged(new PrivilegedAction() {
 204.189 +            public Object run() {
 204.190 +                String homeDir = System.getProperty("java.home");
 204.191 +                try {
 204.192 +                    String dataFile = homeDir + File.separator +
 204.193 +                            "lib" + File.separator + "currency.data";
 204.194 +                    DataInputStream dis = new DataInputStream(
 204.195 +                        new BufferedInputStream(
 204.196 +                        new FileInputStream(dataFile)));
 204.197 +                    if (dis.readInt() != MAGIC_NUMBER) {
 204.198 +                        throw new InternalError("Currency data is possibly corrupted");
 204.199 +                    }
 204.200 +                    formatVersion = dis.readInt();
 204.201 +                    if (formatVersion != VALID_FORMAT_VERSION) {
 204.202 +                        throw new InternalError("Currency data format is incorrect");
 204.203 +                    }
 204.204 +                    dataVersion = dis.readInt();
 204.205 +                    mainTable = readIntArray(dis, A_TO_Z * A_TO_Z);
 204.206 +                    int scCount = dis.readInt();
 204.207 +                    scCutOverTimes = readLongArray(dis, scCount);
 204.208 +                    scOldCurrencies = readStringArray(dis, scCount);
 204.209 +                    scNewCurrencies = readStringArray(dis, scCount);
 204.210 +                    scOldCurrenciesDFD = readIntArray(dis, scCount);
 204.211 +                    scNewCurrenciesDFD = readIntArray(dis, scCount);
 204.212 +                    scOldCurrenciesNumericCode = readIntArray(dis, scCount);
 204.213 +                    scNewCurrenciesNumericCode = readIntArray(dis, scCount);
 204.214 +                    int ocCount = dis.readInt();
 204.215 +                    otherCurrencies = dis.readUTF();
 204.216 +                    otherCurrenciesDFD = readIntArray(dis, ocCount);
 204.217 +                    otherCurrenciesNumericCode = readIntArray(dis, ocCount);
 204.218 +                    dis.close();
 204.219 +                } catch (IOException e) {
 204.220 +                    InternalError ie = new InternalError();
 204.221 +                    ie.initCause(e);
 204.222 +                    throw ie;
 204.223 +                }
 204.224 +
 204.225 +                // look for the properties file for overrides
 204.226 +//                try {
 204.227 +                    File propFile = new File(homeDir + File.separator +
 204.228 +                                             "lib" + File.separator +
 204.229 +                                             "currency.properties");
 204.230 +//                    if (propFile.exists()) {
 204.231 +//                        Properties props = new Properties();
 204.232 +//                        try (FileReader fr = new FileReader(propFile)) {
 204.233 +//                            props.load(fr);
 204.234 +//                        }
 204.235 +//                        Set<String> keys = props.stringPropertyNames();
 204.236 +//                        Pattern propertiesPattern =
 204.237 +//                            Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*([0-3])");
 204.238 +//                        for (String key : keys) {
 204.239 +//                           replaceCurrencyData(propertiesPattern,
 204.240 +//                               key.toUpperCase(Locale.ROOT),
 204.241 +//                               props.getProperty(key).toUpperCase(Locale.ROOT));
 204.242 +//                        }
 204.243 +//                    }
 204.244 +//                } catch (IOException e) {
 204.245 +//                    info("currency.properties is ignored because of an IOException", e);
 204.246 +//                }
 204.247 +                return null;
 204.248 +            }
 204.249 +        });
 204.250 +    }
 204.251 +
 204.252 +    /**
 204.253 +     * Constants for retrieving localized names from the name providers.
 204.254 +     */
 204.255 +    private static final int SYMBOL = 0;
 204.256 +    private static final int DISPLAYNAME = 1;
 204.257 +
 204.258 +
 204.259 +    /**
 204.260 +     * Constructs a <code>Currency</code> instance. The constructor is private
 204.261 +     * so that we can insure that there's never more than one instance for a
 204.262 +     * given currency.
 204.263 +     */
 204.264 +    private Currency(String currencyCode, int defaultFractionDigits, int numericCode) {
 204.265 +        this.currencyCode = currencyCode;
 204.266 +        this.defaultFractionDigits = defaultFractionDigits;
 204.267 +        this.numericCode = numericCode;
 204.268 +    }
 204.269 +
 204.270 +    /**
 204.271 +     * Returns the <code>Currency</code> instance for the given currency code.
 204.272 +     *
 204.273 +     * @param currencyCode the ISO 4217 code of the currency
 204.274 +     * @return the <code>Currency</code> instance for the given currency code
 204.275 +     * @exception NullPointerException if <code>currencyCode</code> is null
 204.276 +     * @exception IllegalArgumentException if <code>currencyCode</code> is not
 204.277 +     * a supported ISO 4217 code.
 204.278 +     */
 204.279 +    public static Currency getInstance(String currencyCode) {
 204.280 +        return getInstance(currencyCode, Integer.MIN_VALUE, 0);
 204.281 +    }
 204.282 +
 204.283 +    private static Currency getInstance(String currencyCode, int defaultFractionDigits,
 204.284 +        int numericCode) {
 204.285 +        synchronized (instances) {
 204.286 +            // Try to look up the currency code in the instances table.
 204.287 +            // This does the null pointer check as a side effect.
 204.288 +            // Also, if there already is an entry, the currencyCode must be valid.
 204.289 +            Currency instance = instances.get(currencyCode);
 204.290 +            if (instance != null) {
 204.291 +                return instance;
 204.292 +            }
 204.293 +
 204.294 +            if (defaultFractionDigits == Integer.MIN_VALUE) {
 204.295 +                // Currency code not internally generated, need to verify first
 204.296 +                // A currency code must have 3 characters and exist in the main table
 204.297 +                // or in the list of other currencies.
 204.298 +                if (currencyCode.length() != 3) {
 204.299 +                    throw new IllegalArgumentException();
 204.300 +                }
 204.301 +                char char1 = currencyCode.charAt(0);
 204.302 +                char char2 = currencyCode.charAt(1);
 204.303 +                int tableEntry = getMainTableEntry(char1, char2);
 204.304 +                if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
 204.305 +                        && tableEntry != INVALID_COUNTRY_ENTRY
 204.306 +                        && currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) {
 204.307 +                    defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
 204.308 +                    numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
 204.309 +                } else {
 204.310 +                    // Check for '-' separately so we don't get false hits in the table.
 204.311 +                    if (currencyCode.charAt(2) == '-') {
 204.312 +                        throw new IllegalArgumentException();
 204.313 +                    }
 204.314 +                    int index = otherCurrencies.indexOf(currencyCode);
 204.315 +                    if (index == -1) {
 204.316 +                        throw new IllegalArgumentException();
 204.317 +                    }
 204.318 +                    defaultFractionDigits = otherCurrenciesDFD[index / 4];
 204.319 +                    numericCode = otherCurrenciesNumericCode[index / 4];
 204.320 +                }
 204.321 +            }
 204.322 +
 204.323 +            instance = new Currency(currencyCode, defaultFractionDigits, numericCode);
 204.324 +            instances.put(currencyCode, instance);
 204.325 +            return instance;
 204.326 +        }
 204.327 +    }
 204.328 +
 204.329 +    /**
 204.330 +     * Returns the <code>Currency</code> instance for the country of the
 204.331 +     * given locale. The language and variant components of the locale
 204.332 +     * are ignored. The result may vary over time, as countries change their
 204.333 +     * currencies. For example, for the original member countries of the
 204.334 +     * European Monetary Union, the method returns the old national currencies
 204.335 +     * until December 31, 2001, and the Euro from January 1, 2002, local time
 204.336 +     * of the respective countries.
 204.337 +     * <p>
 204.338 +     * The method returns <code>null</code> for territories that don't
 204.339 +     * have a currency, such as Antarctica.
 204.340 +     *
 204.341 +     * @param locale the locale for whose country a <code>Currency</code>
 204.342 +     * instance is needed
 204.343 +     * @return the <code>Currency</code> instance for the country of the given
 204.344 +     * locale, or null
 204.345 +     * @exception NullPointerException if <code>locale</code> or its country
 204.346 +     * code is null
 204.347 +     * @exception IllegalArgumentException if the country of the given locale
 204.348 +     * is not a supported ISO 3166 country code.
 204.349 +     */
 204.350 +    public static Currency getInstance(Locale locale) {
 204.351 +        String country = locale.getCountry();
 204.352 +        if (country == null) {
 204.353 +            throw new NullPointerException();
 204.354 +        }
 204.355 +
 204.356 +        if (country.length() != 2) {
 204.357 +            throw new IllegalArgumentException();
 204.358 +        }
 204.359 +
 204.360 +        char char1 = country.charAt(0);
 204.361 +        char char2 = country.charAt(1);
 204.362 +        int tableEntry = getMainTableEntry(char1, char2);
 204.363 +        if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
 204.364 +                    && tableEntry != INVALID_COUNTRY_ENTRY) {
 204.365 +            char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
 204.366 +            int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
 204.367 +            int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
 204.368 +            StringBuffer sb = new StringBuffer(country);
 204.369 +            sb.append(finalChar);
 204.370 +            return getInstance(sb.toString(), defaultFractionDigits, numericCode);
 204.371 +        } else {
 204.372 +            // special cases
 204.373 +            if (tableEntry == INVALID_COUNTRY_ENTRY) {
 204.374 +                throw new IllegalArgumentException();
 204.375 +            }
 204.376 +            if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) {
 204.377 +                return null;
 204.378 +            } else {
 204.379 +                int index = (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
 204.380 +                if (scCutOverTimes[index] == Long.MAX_VALUE || System.currentTimeMillis() < scCutOverTimes[index]) {
 204.381 +                    return getInstance(scOldCurrencies[index], scOldCurrenciesDFD[index],
 204.382 +                        scOldCurrenciesNumericCode[index]);
 204.383 +                } else {
 204.384 +                    return getInstance(scNewCurrencies[index], scNewCurrenciesDFD[index],
 204.385 +                        scNewCurrenciesNumericCode[index]);
 204.386 +                }
 204.387 +            }
 204.388 +        }
 204.389 +    }
 204.390 +
 204.391 +    /**
 204.392 +     * Gets the set of available currencies.  The returned set of currencies
 204.393 +     * contains all of the available currencies, which may include currencies
 204.394 +     * that represent obsolete ISO 4217 codes.  The set can be modified
 204.395 +     * without affecting the available currencies in the runtime.
 204.396 +     *
 204.397 +     * @return the set of available currencies.  If there is no currency
 204.398 +     *    available in the runtime, the returned set is empty.
 204.399 +     * @since 1.7
 204.400 +     */
 204.401 +    public static Set<Currency> getAvailableCurrencies() {
 204.402 +        synchronized(Currency.class) {
 204.403 +            if (available == null) {
 204.404 +                available = new HashSet<Currency>(256);
 204.405 +
 204.406 +                // Add simple currencies first
 204.407 +                for (char c1 = 'A'; c1 <= 'Z'; c1 ++) {
 204.408 +                    for (char c2 = 'A'; c2 <= 'Z'; c2 ++) {
 204.409 +                        int tableEntry = getMainTableEntry(c1, c2);
 204.410 +                        if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK
 204.411 +                             && tableEntry != INVALID_COUNTRY_ENTRY) {
 204.412 +                            char finalChar = (char) ((tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) + 'A');
 204.413 +                            int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
 204.414 +                            int numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
 204.415 +                            StringBuilder sb = new StringBuilder();
 204.416 +                            sb.append(c1);
 204.417 +                            sb.append(c2);
 204.418 +                            sb.append(finalChar);
 204.419 +                            available.add(getInstance(sb.toString(), defaultFractionDigits, numericCode));
 204.420 +                        }
 204.421 +                    }
 204.422 +                }
 204.423 +
 204.424 +                // Now add other currencies
 204.425 +                StringTokenizer st = new StringTokenizer(otherCurrencies, "-");
 204.426 +                while (st.hasMoreElements()) {
 204.427 +                    available.add(getInstance((String)st.nextElement()));
 204.428 +                }
 204.429 +            }
 204.430 +        }
 204.431 +
 204.432 +        return (Set<Currency>) available.clone();
 204.433 +    }
 204.434 +
 204.435 +    /**
 204.436 +     * Gets the ISO 4217 currency code of this currency.
 204.437 +     *
 204.438 +     * @return the ISO 4217 currency code of this currency.
 204.439 +     */
 204.440 +    public String getCurrencyCode() {
 204.441 +        return currencyCode;
 204.442 +    }
 204.443 +
 204.444 +    /**
 204.445 +     * Gets the symbol of this currency for the default locale.
 204.446 +     * For example, for the US Dollar, the symbol is "$" if the default
 204.447 +     * locale is the US, while for other locales it may be "US$". If no
 204.448 +     * symbol can be determined, the ISO 4217 currency code is returned.
 204.449 +     *
 204.450 +     * @return the symbol of this currency for the default locale
 204.451 +     */
 204.452 +    public String getSymbol() {
 204.453 +        return getSymbol(Locale.getDefault(Locale.Category.DISPLAY));
 204.454 +    }
 204.455 +
 204.456 +    /**
 204.457 +     * Gets the symbol of this currency for the specified locale.
 204.458 +     * For example, for the US Dollar, the symbol is "$" if the specified
 204.459 +     * locale is the US, while for other locales it may be "US$". If no
 204.460 +     * symbol can be determined, the ISO 4217 currency code is returned.
 204.461 +     *
 204.462 +     * @param locale the locale for which a display name for this currency is
 204.463 +     * needed
 204.464 +     * @return the symbol of this currency for the specified locale
 204.465 +     * @exception NullPointerException if <code>locale</code> is null
 204.466 +     */
 204.467 +    public String getSymbol(Locale locale) {
 204.468 +        try {
 204.469 +            // Check whether a provider can provide an implementation that's closer
 204.470 +            // to the requested locale than what the Java runtime itself can provide.
 204.471 +            /*
 204.472 +            LocaleServiceProviderPool pool =
 204.473 +                LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
 204.474 +
 204.475 +            if (pool.hasProviders()) {
 204.476 +                // Assuming that all the country locales include necessary currency
 204.477 +                // symbols in the Java runtime's resources,  so there is no need to
 204.478 +                // examine whether Java runtime's currency resource bundle is missing
 204.479 +                // names.  Therefore, no resource bundle is provided for calling this
 204.480 +                // method.
 204.481 +                String symbol = pool.getLocalizedObject(
 204.482 +                                    CurrencyNameGetter.INSTANCE,
 204.483 +                                    locale, (OpenListResourceBundle)null,
 204.484 +                                    currencyCode, SYMBOL);
 204.485 +                if (symbol != null) {
 204.486 +                    return symbol;
 204.487 +                }
 204.488 +            }
 204.489 +            */
 204.490 +            ResourceBundle bundle = null; //LocaleData.getCurrencyNames(locale);
 204.491 +            return bundle.getString(currencyCode);
 204.492 +        } catch (MissingResourceException e) {
 204.493 +            // use currency code as symbol of last resort
 204.494 +            return currencyCode;
 204.495 +        }
 204.496 +    }
 204.497 +
 204.498 +    /**
 204.499 +     * Gets the default number of fraction digits used with this currency.
 204.500 +     * For example, the default number of fraction digits for the Euro is 2,
 204.501 +     * while for the Japanese Yen it's 0.
 204.502 +     * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
 204.503 +     * -1 is returned.
 204.504 +     *
 204.505 +     * @return the default number of fraction digits used with this currency
 204.506 +     */
 204.507 +    public int getDefaultFractionDigits() {
 204.508 +        return defaultFractionDigits;
 204.509 +    }
 204.510 +
 204.511 +    /**
 204.512 +     * Returns the ISO 4217 numeric code of this currency.
 204.513 +     *
 204.514 +     * @return the ISO 4217 numeric code of this currency
 204.515 +     * @since 1.7
 204.516 +     */
 204.517 +    public int getNumericCode() {
 204.518 +        return numericCode;
 204.519 +    }
 204.520 +
 204.521 +    /**
 204.522 +     * Gets the name that is suitable for displaying this currency for
 204.523 +     * the default locale.  If there is no suitable display name found
 204.524 +     * for the default locale, the ISO 4217 currency code is returned.
 204.525 +     *
 204.526 +     * @return the display name of this currency for the default locale
 204.527 +     * @since 1.7
 204.528 +     */
 204.529 +    public String getDisplayName() {
 204.530 +        return getDisplayName(Locale.getDefault(Locale.Category.DISPLAY));
 204.531 +    }
 204.532 +
 204.533 +    /**
 204.534 +     * Gets the name that is suitable for displaying this currency for
 204.535 +     * the specified locale.  If there is no suitable display name found
 204.536 +     * for the specified locale, the ISO 4217 currency code is returned.
 204.537 +     *
 204.538 +     * @param locale the locale for which a display name for this currency is
 204.539 +     * needed
 204.540 +     * @return the display name of this currency for the specified locale
 204.541 +     * @exception NullPointerException if <code>locale</code> is null
 204.542 +     * @since 1.7
 204.543 +     */
 204.544 +    public String getDisplayName(Locale locale) {
 204.545 +//        try {
 204.546 +//            OpenListResourceBundle bundle = LocaleData.getCurrencyNames(locale);
 204.547 +//            String result = null;
 204.548 +//            String bundleKey = currencyCode.toLowerCase(Locale.ROOT);
 204.549 +//
 204.550 +//            // Check whether a provider can provide an implementation that's closer
 204.551 +//            // to the requested locale than what the Java runtime itself can provide.
 204.552 +//            LocaleServiceProviderPool pool =
 204.553 +//                LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
 204.554 +//            if (pool.hasProviders()) {
 204.555 +//                result = pool.getLocalizedObject(
 204.556 +//                                    CurrencyNameGetter.INSTANCE,
 204.557 +//                                    locale, bundleKey, bundle, currencyCode, DISPLAYNAME);
 204.558 +//            }
 204.559 +//
 204.560 +//            if (result == null) {
 204.561 +//                result = bundle.getString(bundleKey);
 204.562 +//            }
 204.563 +//
 204.564 +//            if (result != null) {
 204.565 +//                return result;
 204.566 +//            }
 204.567 +//        } catch (MissingResourceException e) {
 204.568 +//            // fall through
 204.569 +//        }
 204.570 +
 204.571 +        // use currency code as symbol of last resort
 204.572 +        return currencyCode;
 204.573 +    }
 204.574 +
 204.575 +    /**
 204.576 +     * Returns the ISO 4217 currency code of this currency.
 204.577 +     *
 204.578 +     * @return the ISO 4217 currency code of this currency
 204.579 +     */
 204.580 +    public String toString() {
 204.581 +        return currencyCode;
 204.582 +    }
 204.583 +
 204.584 +    /**
 204.585 +     * Resolves instances being deserialized to a single instance per currency.
 204.586 +     */
 204.587 +    private Object readResolve() {
 204.588 +        return getInstance(currencyCode);
 204.589 +    }
 204.590 +
 204.591 +    /**
 204.592 +     * Gets the main table entry for the country whose country code consists
 204.593 +     * of char1 and char2.
 204.594 +     */
 204.595 +    private static int getMainTableEntry(char char1, char char2) {
 204.596 +        if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
 204.597 +            throw new IllegalArgumentException();
 204.598 +        }
 204.599 +        return mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')];
 204.600 +    }
 204.601 +
 204.602 +    /**
 204.603 +     * Sets the main table entry for the country whose country code consists
 204.604 +     * of char1 and char2.
 204.605 +     */
 204.606 +    private static void setMainTableEntry(char char1, char char2, int entry) {
 204.607 +        if (char1 < 'A' || char1 > 'Z' || char2 < 'A' || char2 > 'Z') {
 204.608 +            throw new IllegalArgumentException();
 204.609 +        }
 204.610 +        mainTable[(char1 - 'A') * A_TO_Z + (char2 - 'A')] = entry;
 204.611 +    }
 204.612 +
 204.613 +    /**
 204.614 +     * Obtains a localized currency names from a CurrencyNameProvider
 204.615 +     * implementation.
 204.616 +    private static class CurrencyNameGetter
 204.617 +        implements LocaleServiceProviderPool.LocalizedObjectGetter<CurrencyNameProvider,
 204.618 +                                                                   String> {
 204.619 +        private static final CurrencyNameGetter INSTANCE = new CurrencyNameGetter();
 204.620 +
 204.621 +        public String getObject(CurrencyNameProvider currencyNameProvider,
 204.622 +                                Locale locale,
 204.623 +                                String key,
 204.624 +                                Object... params) {
 204.625 +            assert params.length == 1;
 204.626 +            int type = (Integer)params[0];
 204.627 +
 204.628 +            switch(type) {
 204.629 +            case SYMBOL:
 204.630 +                return currencyNameProvider.getSymbol(key, locale);
 204.631 +            case DISPLAYNAME:
 204.632 +                return currencyNameProvider.getDisplayName(key, locale);
 204.633 +            default:
 204.634 +                assert false; // shouldn't happen
 204.635 +            }
 204.636 +
 204.637 +            return null;
 204.638 +        }
 204.639 +    }
 204.640 +     */
 204.641 +
 204.642 +    private static int[] readIntArray(DataInputStream dis, int count) throws IOException {
 204.643 +        int[] ret = new int[count];
 204.644 +        for (int i = 0; i < count; i++) {
 204.645 +            ret[i] = dis.readInt();
 204.646 +        }
 204.647 +
 204.648 +        return ret;
 204.649 +    }
 204.650 +
 204.651 +    private static long[] readLongArray(DataInputStream dis, int count) throws IOException {
 204.652 +        long[] ret = new long[count];
 204.653 +        for (int i = 0; i < count; i++) {
 204.654 +            ret[i] = dis.readLong();
 204.655 +        }
 204.656 +
 204.657 +        return ret;
 204.658 +    }
 204.659 +
 204.660 +    private static String[] readStringArray(DataInputStream dis, int count) throws IOException {
 204.661 +        String[] ret = new String[count];
 204.662 +        for (int i = 0; i < count; i++) {
 204.663 +            ret[i] = dis.readUTF();
 204.664 +        }
 204.665 +
 204.666 +        return ret;
 204.667 +    }
 204.668 +
 204.669 +    /**
 204.670 +     * Replaces currency data found in the currencydata.properties file
 204.671 +     *
 204.672 +     * @param pattern regex pattern for the properties
 204.673 +     * @param ctry country code
 204.674 +     * @param data currency data.  This is a comma separated string that
 204.675 +     *    consists of "three-letter alphabet code", "three-digit numeric code",
 204.676 +     *    and "one-digit (0,1,2, or 3) default fraction digit".
 204.677 +     *    For example, "JPZ,392,0".
 204.678 +     * @throws
 204.679 +    private static void replaceCurrencyData(Pattern pattern, String ctry, String curdata) {
 204.680 +
 204.681 +        if (ctry.length() != 2) {
 204.682 +            // ignore invalid country code
 204.683 +            String message = new StringBuilder()
 204.684 +                .append("The entry in currency.properties for ")
 204.685 +                .append(ctry).append(" is ignored because of the invalid country code.")
 204.686 +                .toString();
 204.687 +            info(message, null);
 204.688 +            return;
 204.689 +        }
 204.690 +
 204.691 +        Matcher m = pattern.matcher(curdata);
 204.692 +        if (!m.find()) {
 204.693 +            // format is not recognized.  ignore the data
 204.694 +            String message = new StringBuilder()
 204.695 +                .append("The entry in currency.properties for ")
 204.696 +                .append(ctry)
 204.697 +                .append(" is ignored because the value format is not recognized.")
 204.698 +                .toString();
 204.699 +            info(message, null);
 204.700 +            return;
 204.701 +        }
 204.702 +
 204.703 +        String code = m.group(1);
 204.704 +        int numeric = Integer.parseInt(m.group(2));
 204.705 +        int fraction = Integer.parseInt(m.group(3));
 204.706 +        int entry = numeric << NUMERIC_CODE_SHIFT;
 204.707 +
 204.708 +        int index;
 204.709 +        for (index = 0; index < scOldCurrencies.length; index++) {
 204.710 +            if (scOldCurrencies[index].equals(code)) {
 204.711 +                break;
 204.712 +            }
 204.713 +        }
 204.714 +
 204.715 +        if (index == scOldCurrencies.length) {
 204.716 +            // simple case
 204.717 +            entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT) |
 204.718 +                     (code.charAt(2) - 'A');
 204.719 +        } else {
 204.720 +            // special case
 204.721 +            entry |= SPECIAL_CASE_COUNTRY_MASK |
 204.722 +                     (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA);
 204.723 +        }
 204.724 +        setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
 204.725 +    }
 204.726 +     */
 204.727 +
 204.728 +    private static void info(String message, Throwable t) {
 204.729 +        Logger logger = Logger.getLogger("java.util.Currency");
 204.730 +        if (logger.isLoggable(Level.INFO)) {
 204.731 +            if (t != null) {
 204.732 +                logger.log(Level.INFO, message, t);
 204.733 +            } else {
 204.734 +                logger.info(message);
 204.735 +            }
 204.736 +        }
 204.737 +    }
 204.738 +}
   205.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.2 +++ b/rt/emul/compact/src/main/java/java/util/CurrencyData.properties	Wed Apr 30 15:04:10 2014 +0200
   205.3 @@ -0,0 +1,586 @@
   205.4 +#
   205.5 +# Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
   205.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   205.7 +#
   205.8 +# This code is free software; you can redistribute it and/or modify it
   205.9 +# under the terms of the GNU General Public License version 2 only, as
  205.10 +# published by the Free Software Foundation.  Oracle designates this
  205.11 +# particular file as subject to the "Classpath" exception as provided
  205.12 +# by Oracle in the LICENSE file that accompanied this code.
  205.13 +#
  205.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
  205.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  205.16 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  205.17 +# version 2 for more details (a copy is included in the LICENSE file that
  205.18 +# accompanied this code).
  205.19 +#
  205.20 +# You should have received a copy of the GNU General Public License version
  205.21 +# 2 along with this work; if not, write to the Free Software Foundation,
  205.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  205.23 +#
  205.24 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  205.25 +# or visit www.oracle.com if you need additional information or have any
  205.26 +# questions.
  205.27 +#
  205.28 +
  205.29 +formatVersion=1
  205.30 +
  205.31 +# Version of the currency code information in this class.
  205.32 +# It is a serial number that accompanies with each amendment, such as 
  205.33 +# 'MAxxx.doc'
  205.34 +
  205.35 +dataVersion=140
  205.36 +
  205.37 +# List of all valid ISO 4217 currency codes.
  205.38 +# To ensure compatibility, do not remove codes.
  205.39 +
  205.40 +all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036-\
  205.41 +    AWG533-AYM945-AZM031-AZN944-BAM977-BBD052-BDT050-BEF056-BGL100-BGN975-BHD048-BIF108-\
  205.42 +    BMD060-BND096-BOB068-BOV984-BRL986-BSD044-BTN064-BWP072-BYB112-BYR974-\
  205.43 +    BZD084-CAD124-CDF976-CHF756-CLF990-CLP152-CNY156-COP170-CRC188-CSD891-CUP192-\
  205.44 +    CVE132-CYP196-CZK203-DEM276-DJF262-DKK208-DOP214-DZD012-EEK233-EGP818-\
  205.45 +    ERN232-ESP724-ETB230-EUR978-FIM246-FJD242-FKP238-FRF250-GBP826-GEL981-\
  205.46 +    GHC288-GHS936-GIP292-GMD270-GNF324-GRD300-GTQ320-GWP624-GYD328-HKD344-HNL340-\
  205.47 +    HRK191-HTG332-HUF348-IDR360-IEP372-ILS376-INR356-IQD368-IRR364-ISK352-\
  205.48 +    ITL380-JMD388-JOD400-JPY392-KES404-KGS417-KHR116-KMF174-KPW408-KRW410-\
  205.49 +    KWD414-KYD136-KZT398-LAK418-LBP422-LKR144-LRD430-LSL426-LTL440-LUF442-\
  205.50 +    LVL428-LYD434-MAD504-MDL498-MGA969-MGF450-MKD807-MMK104-MNT496-MOP446-MRO478-\
  205.51 +    MTL470-MUR480-MVR462-MWK454-MXN484-MXV979-MYR458-MZM508-MZN943-NAD516-NGN566-\
  205.52 +    NIO558-NLG528-NOK578-NPR524-NZD554-OMR512-PAB590-PEN604-PGK598-PHP608-\
  205.53 +    PKR586-PLN985-PTE620-PYG600-QAR634-ROL946-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\
  205.54 +    SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLL694-SOS706-\
  205.55 +    SRD968-SRG740-STD678-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TND788-TOP776-\
  205.56 +    TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-\
  205.57 +    UYU858-UZS860-VEB862-VEF937-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
  205.58 +    XBB956-XBC957-XBD958-XCD951-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
  205.59 +    XPT962-XTS963-XXX999-YER886-YUM891-ZAR710-ZMK894-ZWD716-ZWN942
  205.60 +
  205.61 +
  205.62 +# Mappings from ISO 3166 country codes to ISO 4217 currency codes.
  205.63 +#
  205.64 +# Three forms are used:
  205.65 +# Form 1: <country code>=<currency code>
  205.66 +# Form 2: <country code>=<currency code 1>;<time stamp>;<currency code 2>
  205.67 +# Form 3: <country code>=
  205.68 +# Form 1 is used if no future change in currency is known.
  205.69 +# Form 2 indicates that before the specified time currency 1 is used, from
  205.70 +# the specified time currency 2. The time is given in SimpleDateFormat's
  205.71 +# yyyy-MM-dd-HH-mm-ss format in the GMT time zone.
  205.72 +# Form 3 indicates the country doesn't have a currency (the entry is still
  205.73 +# needed to verify that the country code is valid).
  205.74 +#
  205.75 +# The table is based on the following web sites:
  205.76 +# http://www.din.de/gremien/nas/nabd/iso3166ma/codlstp1/db_en.html
  205.77 +# http://www.bsi-global.com/iso4217currency
  205.78 +# http://www.cia.gov/cia/publications/factbook/indexgeo.html
  205.79 +
  205.80 +# AFGHANISTAN
  205.81 +AF=AFN
  205.82 +# \u00c5LAND ISLANDS
  205.83 +AX=EUR
  205.84 +# ALBANIA
  205.85 +AL=ALL
  205.86 +# ALGERIA
  205.87 +DZ=DZD
  205.88 +# AMERICAN SAMOA
  205.89 +AS=USD
  205.90 +# ANDORRA
  205.91 +AD=EUR
  205.92 +# ANGOLA
  205.93 +AO=AOA
  205.94 +# ANGUILLA
  205.95 +AI=XCD
  205.96 +# ANTARCTICA
  205.97 +AQ=
  205.98 +# ANTIGUA AND BARBUDA
  205.99 +AG=XCD
 205.100 +# ARGENTINA
 205.101 +AR=ARS
 205.102 +# ARMENIA
 205.103 +AM=AMD
 205.104 +# ARUBA
 205.105 +AW=AWG
 205.106 +# AUSTRALIA
 205.107 +AU=AUD
 205.108 +# AUSTRIA
 205.109 +AT=EUR
 205.110 +# AZERBAIJAN
 205.111 +AZ=AZM;2005-12-31-20-00-00;AZN
 205.112 +# BAHAMAS
 205.113 +BS=BSD
 205.114 +# BAHRAIN
 205.115 +BH=BHD
 205.116 +# BANGLADESH
 205.117 +BD=BDT
 205.118 +# BARBADOS
 205.119 +BB=BBD
 205.120 +# BELARUS
 205.121 +BY=BYR
 205.122 +# BELGIUM
 205.123 +BE=EUR
 205.124 +# BELIZE
 205.125 +BZ=BZD
 205.126 +# BENIN
 205.127 +BJ=XOF
 205.128 +# BERMUDA
 205.129 +BM=BMD
 205.130 +# BHUTAN
 205.131 +BT=BTN
 205.132 +# BOLIVIA
 205.133 +BO=BOB
 205.134 +# BOSNIA AND HERZEGOVINA
 205.135 +BA=BAM
 205.136 +# BOTSWANA
 205.137 +BW=BWP
 205.138 +# BOUVET ISLAND
 205.139 +BV=NOK
 205.140 +# BRAZIL
 205.141 +BR=BRL
 205.142 +# BRITISH INDIAN OCEAN TERRITORY
 205.143 +IO=USD
 205.144 +# BRUNEI DARUSSALAM
 205.145 +BN=BND
 205.146 +# BULGARIA
 205.147 +BG=BGN
 205.148 +# BURKINA FASO
 205.149 +BF=XOF
 205.150 +# BURUNDI
 205.151 +BI=BIF
 205.152 +# CAMBODIA
 205.153 +KH=KHR
 205.154 +# CAMEROON
 205.155 +CM=XAF
 205.156 +# CANADA
 205.157 +CA=CAD
 205.158 +# CAPE VERDE
 205.159 +CV=CVE
 205.160 +# CAYMAN ISLANDS
 205.161 +KY=KYD
 205.162 +# CENTRAL AFRICAN REPUBLIC
 205.163 +CF=XAF
 205.164 +# CHAD
 205.165 +TD=XAF
 205.166 +# CHILE
 205.167 +CL=CLP
 205.168 +# CHINA
 205.169 +CN=CNY
 205.170 +# CHRISTMAS ISLAND
 205.171 +CX=AUD
 205.172 +# COCOS (KEELING) ISLANDS
 205.173 +CC=AUD
 205.174 +# COLOMBIA
 205.175 +CO=COP
 205.176 +# COMOROS
 205.177 +KM=KMF
 205.178 +# CONGO
 205.179 +CG=XAF
 205.180 +# CONGO, THE DEMOCRATIC REPUBLIC OF THE
 205.181 +CD=CDF
 205.182 +# COOK ISLANDS
 205.183 +CK=NZD
 205.184 +# COSTA RICA
 205.185 +CR=CRC
 205.186 +# COTE D'IVOIRE
 205.187 +CI=XOF
 205.188 +# CROATIA
 205.189 +HR=HRK
 205.190 +# CUBA
 205.191 +CU=CUP
 205.192 +# CYPRUS
 205.193 +CY=EUR
 205.194 +# CZECH REPUBLIC
 205.195 +CZ=CZK
 205.196 +# DENMARK
 205.197 +DK=DKK
 205.198 +# DJIBOUTI
 205.199 +DJ=DJF
 205.200 +# DOMINICA
 205.201 +DM=XCD
 205.202 +# DOMINICAN REPUBLIC
 205.203 +DO=DOP
 205.204 +# ECUADOR
 205.205 +EC=USD
 205.206 +# EGYPT
 205.207 +EG=EGP
 205.208 +# EL SALVADOR
 205.209 +# USD is also legal currency as of 2001/01/01
 205.210 +SV=SVC
 205.211 +# EQUATORIAL GUINEA
 205.212 +GQ=XAF
 205.213 +# ERITREA
 205.214 +ER=ERN
 205.215 +# ESTONIA
 205.216 +EE=EEK
 205.217 +# ETHIOPIA
 205.218 +ET=ETB
 205.219 +# FALKLAND ISLANDS (MALVINAS)
 205.220 +FK=FKP
 205.221 +# FAROE ISLANDS
 205.222 +FO=DKK
 205.223 +# FIJI
 205.224 +FJ=FJD
 205.225 +# FINLAND
 205.226 +FI=EUR
 205.227 +# FRANCE
 205.228 +FR=EUR
 205.229 +# FRENCH GUIANA
 205.230 +GF=EUR
 205.231 +# FRENCH POLYNESIA
 205.232 +PF=XPF
 205.233 +# FRENCH SOUTHERN TERRITORIES
 205.234 +TF=EUR
 205.235 +# GABON
 205.236 +GA=XAF
 205.237 +# GAMBIA
 205.238 +GM=GMD
 205.239 +# GEORGIA
 205.240 +GE=GEL
 205.241 +# GERMANY
 205.242 +DE=EUR
 205.243 +# GHANA
 205.244 +GH=GHS
 205.245 +# GIBRALTAR
 205.246 +GI=GIP
 205.247 +# GREECE
 205.248 +GR=EUR
 205.249 +# GREENLAND
 205.250 +GL=DKK
 205.251 +# GRENADA
 205.252 +GD=XCD
 205.253 +# GUADELOUPE
 205.254 +GP=EUR
 205.255 +# GUAM
 205.256 +GU=USD
 205.257 +# GUATEMALA
 205.258 +GT=GTQ
 205.259 +# GUERNSEY
 205.260 +GG=GBP
 205.261 +# GUINEA
 205.262 +GN=GNF
 205.263 +# GUINEA-BISSAU
 205.264 +GW=XOF
 205.265 +# GUYANA
 205.266 +GY=GYD
 205.267 +# HAITI
 205.268 +HT=HTG
 205.269 +# HEARD ISLAND AND MCDONALD ISLANDS
 205.270 +HM=AUD
 205.271 +# HOLY SEE (VATICAN CITY STATE)
 205.272 +VA=EUR
 205.273 +# HONDURAS
 205.274 +HN=HNL
 205.275 +# HONG KONG
 205.276 +HK=HKD
 205.277 +# HUNGARY
 205.278 +HU=HUF
 205.279 +# ICELAND
 205.280 +IS=ISK
 205.281 +# INDIA
 205.282 +IN=INR
 205.283 +# INDONESIA
 205.284 +ID=IDR
 205.285 +# IRAN, ISLAMIC REPUBLIC OF
 205.286 +IR=IRR
 205.287 +# IRAQ
 205.288 +IQ=IQD
 205.289 +# IRELAND
 205.290 +IE=EUR
 205.291 +# ISLE OF MAN
 205.292 +IM=GBP
 205.293 +# ISRAEL
 205.294 +IL=ILS
 205.295 +# ITALY
 205.296 +IT=EUR
 205.297 +# JAMAICA
 205.298 +JM=JMD
 205.299 +# JAPAN
 205.300 +JP=JPY
 205.301 +# JERSEY
 205.302 +JE=GBP
 205.303 +# JORDAN
 205.304 +JO=JOD
 205.305 +# KAZAKSTAN
 205.306 +KZ=KZT
 205.307 +# KENYA
 205.308 +KE=KES
 205.309 +# KIRIBATI
 205.310 +KI=AUD
 205.311 +# KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF
 205.312 +KP=KPW
 205.313 +# KOREA, REPUBLIC OF
 205.314 +KR=KRW
 205.315 +# KUWAIT
 205.316 +KW=KWD
 205.317 +# KYRGYZSTAN
 205.318 +KG=KGS
 205.319 +# LAO PEOPLE'S DEMOCRATIC REPUBLIC
 205.320 +LA=LAK
 205.321 +# LATVIA
 205.322 +LV=LVL
 205.323 +# LEBANON
 205.324 +LB=LBP
 205.325 +# LESOTHO
 205.326 +LS=LSL
 205.327 +# LIBERIA
 205.328 +LR=LRD
 205.329 +# LIBYAN ARAB JAMAHIRIYA
 205.330 +LY=LYD
 205.331 +# LIECHTENSTEIN
 205.332 +LI=CHF
 205.333 +# LITHUANIA
 205.334 +LT=LTL
 205.335 +# LUXEMBOURG
 205.336 +LU=EUR
 205.337 +# MACAU
 205.338 +MO=MOP
 205.339 +# MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF
 205.340 +MK=MKD
 205.341 +# MADAGASCAR
 205.342 +MG=MGA
 205.343 +# MALAWI
 205.344 +MW=MWK
 205.345 +# MALAYSIA
 205.346 +MY=MYR
 205.347 +# MALDIVES
 205.348 +MV=MVR
 205.349 +# MALI
 205.350 +ML=XOF
 205.351 +# MALTA
 205.352 +MT=EUR
 205.353 +# MARSHALL ISLANDS
 205.354 +MH=USD
 205.355 +# MARTINIQUE
 205.356 +MQ=EUR
 205.357 +# MAURITANIA
 205.358 +MR=MRO
 205.359 +# MAURITIUS
 205.360 +MU=MUR
 205.361 +# MAYOTTE
 205.362 +YT=EUR
 205.363 +# MEXICO
 205.364 +MX=MXN
 205.365 +# MICRONESIA, FEDERATED STATES OF
 205.366 +FM=USD
 205.367 +# MOLDOVA, REPUBLIC OF
 205.368 +MD=MDL
 205.369 +# MONACO
 205.370 +MC=EUR
 205.371 +# MONGOLIA
 205.372 +MN=MNT
 205.373 +# MONTENEGRO
 205.374 +ME=EUR
 205.375 +# MONTSERRAT
 205.376 +MS=XCD
 205.377 +# MOROCCO
 205.378 +MA=MAD
 205.379 +# MOZAMBIQUE
 205.380 +MZ=MZM;2006-06-30-22-00-00;MZN
 205.381 +# MYANMAR
 205.382 +MM=MMK
 205.383 +# NAMIBIA
 205.384 +NA=NAD
 205.385 +# NAURU
 205.386 +NR=AUD
 205.387 +# NEPAL
 205.388 +NP=NPR
 205.389 +# NETHERLANDS
 205.390 +NL=EUR
 205.391 +# NETHERLANDS ANTILLES
 205.392 +AN=ANG
 205.393 +# NEW CALEDONIA
 205.394 +NC=XPF
 205.395 +# NEW ZEALAND
 205.396 +NZ=NZD
 205.397 +# NICARAGUA
 205.398 +NI=NIO
 205.399 +# NIGER
 205.400 +NE=XOF
 205.401 +# NIGERIA
 205.402 +NG=NGN
 205.403 +# NIUE
 205.404 +NU=NZD
 205.405 +# NORFOLK ISLAND
 205.406 +NF=AUD
 205.407 +# NORTHERN MARIANA ISLANDS
 205.408 +MP=USD
 205.409 +# NORWAY
 205.410 +NO=NOK
 205.411 +# OMAN
 205.412 +OM=OMR
 205.413 +# PAKISTAN
 205.414 +PK=PKR
 205.415 +# PALAU
 205.416 +PW=USD
 205.417 +# PALESTINIAN TERRITORY, OCCUPIED
 205.418 +PS=ILS
 205.419 +# PANAMA
 205.420 +PA=PAB
 205.421 +# PAPUA NEW GUINEA
 205.422 +PG=PGK
 205.423 +# PARAGUAY
 205.424 +PY=PYG
 205.425 +# PERU
 205.426 +PE=PEN
 205.427 +# PHILIPPINES
 205.428 +PH=PHP
 205.429 +# PITCAIRN
 205.430 +PN=NZD
 205.431 +# POLAND
 205.432 +PL=PLN
 205.433 +# PORTUGAL
 205.434 +PT=EUR
 205.435 +# PUERTO RICO
 205.436 +PR=USD
 205.437 +# QATAR
 205.438 +QA=QAR
 205.439 +# REUNION
 205.440 +RE=EUR
 205.441 +# ROMANIA
 205.442 +RO=ROL;2005-06-30-21-00-00;RON
 205.443 +# RUSSIAN FEDERATION
 205.444 +RU=RUB
 205.445 +# RWANDA
 205.446 +RW=RWF
 205.447 +# SAINT BARTHELEMY
 205.448 +BL=EUR
 205.449 +# SAINT HELENA
 205.450 +SH=SHP
 205.451 +# SAINT KITTS AND NEVIS
 205.452 +KN=XCD
 205.453 +# SAINT LUCIA
 205.454 +LC=XCD
 205.455 +# SAINT MARTIN
 205.456 +MF=EUR
 205.457 +# SAINT PIERRE AND MIQUELON
 205.458 +PM=EUR
 205.459 +# SAINT VINCENT AND THE GRENADINES
 205.460 +VC=XCD
 205.461 +# SAMOA
 205.462 +WS=WST
 205.463 +# SAN MARINO
 205.464 +SM=EUR
 205.465 +# SAO TOME AND PRINCIPE
 205.466 +ST=STD
 205.467 +# SAUDI ARABIA
 205.468 +SA=SAR
 205.469 +# SENEGAL
 205.470 +SN=XOF
 205.471 +# SERBIA
 205.472 +RS=RSD
 205.473 +# SERBIA AND MONTENEGRO
 205.474 +CS=CSD
 205.475 +# SEYCHELLES
 205.476 +SC=SCR
 205.477 +# SIERRA LEONE
 205.478 +SL=SLL
 205.479 +# SINGAPORE
 205.480 +SG=SGD
 205.481 +# SLOVAKIA
 205.482 +SK=SKK
 205.483 +# SLOVENIA
 205.484 +SI=EUR
 205.485 +# SOLOMON ISLANDS
 205.486 +SB=SBD
 205.487 +# SOMALIA
 205.488 +SO=SOS
 205.489 +# SOUTH AFRICA
 205.490 +ZA=ZAR
 205.491 +# SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS
 205.492 +GS=GBP
 205.493 +# SPAIN
 205.494 +ES=EUR
 205.495 +# SRI LANKA
 205.496 +LK=LKR
 205.497 +# SUDAN
 205.498 +SD=SDG
 205.499 +# SURINAME
 205.500 +SR=SRD
 205.501 +# SVALBARD AND JAN MAYEN
 205.502 +SJ=NOK
 205.503 +# SWAZILAND
 205.504 +SZ=SZL
 205.505 +# SWEDEN
 205.506 +SE=SEK
 205.507 +# SWITZERLAND
 205.508 +CH=CHF
 205.509 +# SYRIAN ARAB REPUBLIC
 205.510 +SY=SYP
 205.511 +# TAIWAN
 205.512 +TW=TWD
 205.513 +# TAJIKISTAN
 205.514 +TJ=TJS
 205.515 +# TANZANIA, UNITED REPUBLIC OF
 205.516 +TZ=TZS
 205.517 +# THAILAND
 205.518 +TH=THB
 205.519 +# TIMOR-LESTE
 205.520 +TL=USD
 205.521 +# TOGO
 205.522 +TG=XOF
 205.523 +# TOKELAU
 205.524 +TK=NZD
 205.525 +# TONGA
 205.526 +TO=TOP
 205.527 +# TRINIDAD AND TOBAGO
 205.528 +TT=TTD
 205.529 +# TUNISIA
 205.530 +TN=TND
 205.531 +# TURKEY
 205.532 +TR=TRL;2004-12-31-22-00-00;TRY
 205.533 +# TURKMENISTAN
 205.534 +TM=TMM
 205.535 +# TURKS AND CAICOS ISLANDS
 205.536 +TC=USD
 205.537 +# TUVALU
 205.538 +TV=AUD
 205.539 +# UGANDA
 205.540 +UG=UGX
 205.541 +# UKRAINE
 205.542 +UA=UAH
 205.543 +# UNITED ARAB EMIRATES
 205.544 +AE=AED
 205.545 +# UNITED KINGDOM
 205.546 +GB=GBP
 205.547 +# UNITED STATES
 205.548 +US=USD
 205.549 +# UNITED STATES MINOR OUTLYING ISLANDS
 205.550 +UM=USD
 205.551 +# URUGUAY
 205.552 +UY=UYU
 205.553 +# UZBEKISTAN
 205.554 +UZ=UZS
 205.555 +# VANUATU
 205.556 +VU=VUV
 205.557 +# VENEZUELA
 205.558 +VE=VEB;2008-01-01-04-00-00;VEF
 205.559 +# VIET NAM
 205.560 +VN=VND
 205.561 +# VIRGIN ISLANDS, BRITISH
 205.562 +VG=USD
 205.563 +# VIRGIN ISLANDS, U.S.
 205.564 +VI=USD
 205.565 +# WALLIS AND FUTUNA
 205.566 +WF=XPF
 205.567 +# WESTERN SAHARA
 205.568 +EH=MAD
 205.569 +# YEMEN
 205.570 +YE=YER
 205.571 +# ZAMBIA
 205.572 +ZM=ZMK
 205.573 +# ZIMBABWE
 205.574 +ZW=ZWD
 205.575 +
 205.576 +
 205.577 +# List of currencies with 0, 1, OR 3 decimals for minor units, or where there
 205.578 +# are no minor units defined. All others use 2 decimals.
 205.579 +
 205.580 +minor0=\
 205.581 +    ADP-BEF-BIF-BYB-BYR-CLF-CLP-DJF-ESP-GNF-\
 205.582 +    GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-RWF-\
 205.583 +    TPE-TRL-VUV-XAF-XOF-XPF
 205.584 +minor1=
 205.585 +minor3=\
 205.586 +    BHD-IQD-JOD-KWD-LYD-OMR-TND
 205.587 +minorUndefined=\
 205.588 +    XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-\
 205.589 +    XPT-XTS-XXX
   206.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.2 +++ b/rt/emul/compact/src/main/java/java/util/Date.java	Wed Apr 30 15:04:10 2014 +0200
   206.3 @@ -0,0 +1,1430 @@
   206.4 +/*
   206.5 + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
   206.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   206.7 + *
   206.8 + * This code is free software; you can redistribute it and/or modify it
   206.9 + * under the terms of the GNU General Public License version 2 only, as
  206.10 + * published by the Free Software Foundation.  Oracle designates this
  206.11 + * particular file as subject to the "Classpath" exception as provided
  206.12 + * by Oracle in the LICENSE file that accompanied this code.
  206.13 + *
  206.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  206.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  206.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  206.17 + * version 2 for more details (a copy is included in the LICENSE file that
  206.18 + * accompanied this code).
  206.19 + *
  206.20 + * You should have received a copy of the GNU General Public License version
  206.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  206.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  206.23 + *
  206.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  206.25 + * or visit www.oracle.com if you need additional information or have any
  206.26 + * questions.
  206.27 + */
  206.28 +
  206.29 +package java.util;
  206.30 +
  206.31 +import java.text.DateFormat;
  206.32 +import java.io.IOException;
  206.33 +import java.io.ObjectOutputStream;
  206.34 +import java.io.ObjectInputStream;
  206.35 +
  206.36 +/**
  206.37 + * The class <code>Date</code> represents a specific instant
  206.38 + * in time, with millisecond precision.
  206.39 + * <p>
  206.40 + * Prior to JDK&nbsp;1.1, the class <code>Date</code> had two additional
  206.41 + * functions.  It allowed the interpretation of dates as year, month, day, hour,
  206.42 + * minute, and second values.  It also allowed the formatting and parsing
  206.43 + * of date strings.  Unfortunately, the API for these functions was not
  206.44 + * amenable to internationalization.  As of JDK&nbsp;1.1, the
  206.45 + * <code>Calendar</code> class should be used to convert between dates and time
  206.46 + * fields and the <code>DateFormat</code> class should be used to format and
  206.47 + * parse date strings.
  206.48 + * The corresponding methods in <code>Date</code> are deprecated.
  206.49 + * <p>
  206.50 + * Although the <code>Date</code> class is intended to reflect
  206.51 + * coordinated universal time (UTC), it may not do so exactly,
  206.52 + * depending on the host environment of the Java Virtual Machine.
  206.53 + * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
  206.54 + * 24&nbsp;&times;&nbsp;60&nbsp;&times;&nbsp;60&nbsp;= 86400 seconds
  206.55 + * in all cases. In UTC, however, about once every year or two there
  206.56 + * is an extra second, called a "leap second." The leap
  206.57 + * second is always added as the last second of the day, and always
  206.58 + * on December 31 or June 30. For example, the last minute of the
  206.59 + * year 1995 was 61 seconds long, thanks to an added leap second.
  206.60 + * Most computer clocks are not accurate enough to be able to reflect
  206.61 + * the leap-second distinction.
  206.62 + * <p>
  206.63 + * Some computer standards are defined in terms of Greenwich mean
  206.64 + * time (GMT), which is equivalent to universal time (UT).  GMT is
  206.65 + * the "civil" name for the standard; UT is the
  206.66 + * "scientific" name for the same standard. The
  206.67 + * distinction between UTC and UT is that UTC is based on an atomic
  206.68 + * clock and UT is based on astronomical observations, which for all
  206.69 + * practical purposes is an invisibly fine hair to split. Because the
  206.70 + * earth's rotation is not uniform (it slows down and speeds up
  206.71 + * in complicated ways), UT does not always flow uniformly. Leap
  206.72 + * seconds are introduced as needed into UTC so as to keep UTC within
  206.73 + * 0.9 seconds of UT1, which is a version of UT with certain
  206.74 + * corrections applied. There are other time and date systems as
  206.75 + * well; for example, the time scale used by the satellite-based
  206.76 + * global positioning system (GPS) is synchronized to UTC but is
  206.77 + * <i>not</i> adjusted for leap seconds. An interesting source of
  206.78 + * further information is the U.S. Naval Observatory, particularly
  206.79 + * the Directorate of Time at:
  206.80 + * <blockquote><pre>
  206.81 + *     <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a>
  206.82 + * </pre></blockquote>
  206.83 + * <p>
  206.84 + * and their definitions of "Systems of Time" at:
  206.85 + * <blockquote><pre>
  206.86 + *     <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a>
  206.87 + * </pre></blockquote>
  206.88 + * <p>
  206.89 + * In all methods of class <code>Date</code> that accept or return
  206.90 + * year, month, date, hours, minutes, and seconds values, the
  206.91 + * following representations are used:
  206.92 + * <ul>
  206.93 + * <li>A year <i>y</i> is represented by the integer
  206.94 + *     <i>y</i>&nbsp;<code>-&nbsp;1900</code>.
  206.95 + * <li>A month is represented by an integer from 0 to 11; 0 is January,
  206.96 + *     1 is February, and so forth; thus 11 is December.
  206.97 + * <li>A date (day of month) is represented by an integer from 1 to 31
  206.98 + *     in the usual manner.
  206.99 + * <li>An hour is represented by an integer from 0 to 23. Thus, the hour
 206.100 + *     from midnight to 1 a.m. is hour 0, and the hour from noon to 1
 206.101 + *     p.m. is hour 12.
 206.102 + * <li>A minute is represented by an integer from 0 to 59 in the usual manner.
 206.103 + * <li>A second is represented by an integer from 0 to 61; the values 60 and
 206.104 + *     61 occur only for leap seconds and even then only in Java
 206.105 + *     implementations that actually track leap seconds correctly. Because
 206.106 + *     of the manner in which leap seconds are currently introduced, it is
 206.107 + *     extremely unlikely that two leap seconds will occur in the same
 206.108 + *     minute, but this specification follows the date and time conventions
 206.109 + *     for ISO C.
 206.110 + * </ul>
 206.111 + * <p>
 206.112 + * In all cases, arguments given to methods for these purposes need
 206.113 + * not fall within the indicated ranges; for example, a date may be
 206.114 + * specified as January 32 and is interpreted as meaning February 1.
 206.115 + *
 206.116 + * @author  James Gosling
 206.117 + * @author  Arthur van Hoff
 206.118 + * @author  Alan Liu
 206.119 + * @see     java.text.DateFormat
 206.120 + * @see     java.util.Calendar
 206.121 + * @see     java.util.TimeZone
 206.122 + * @since   JDK1.0
 206.123 + */
 206.124 +public class Date
 206.125 +    implements java.io.Serializable, Cloneable, Comparable<Date>
 206.126 +{
 206.127 +    private static final BaseCalendar gcal = new BaseCalendar();
 206.128 +                                
 206.129 +    private static BaseCalendar jcal;
 206.130 +
 206.131 +    private transient long fastTime;
 206.132 +
 206.133 +    /*
 206.134 +     * If cdate is null, then fastTime indicates the time in millis.
 206.135 +     * If cdate.isNormalized() is true, then fastTime and cdate are in
 206.136 +     * synch. Otherwise, fastTime is ignored, and cdate indicates the
 206.137 +     * time.
 206.138 +     */
 206.139 +    private transient BaseCalendar.Datum cdate;
 206.140 +
 206.141 +    // Initialized just before the value is used. See parse().
 206.142 +    private static int defaultCenturyStart;
 206.143 +
 206.144 +    /* use serialVersionUID from modified java.util.Date for
 206.145 +     * interoperability with JDK1.1. The Date was modified to write
 206.146 +     * and read only the UTC time.
 206.147 +     */
 206.148 +    private static final long serialVersionUID = 7523967970034938905L;
 206.149 +
 206.150 +    /**
 206.151 +     * Allocates a <code>Date</code> object and initializes it so that
 206.152 +     * it represents the time at which it was allocated, measured to the
 206.153 +     * nearest millisecond.
 206.154 +     *
 206.155 +     * @see     java.lang.System#currentTimeMillis()
 206.156 +     */
 206.157 +    public Date() {
 206.158 +        this(System.currentTimeMillis());
 206.159 +    }
 206.160 +
 206.161 +    /**
 206.162 +     * Allocates a <code>Date</code> object and initializes it to
 206.163 +     * represent the specified number of milliseconds since the
 206.164 +     * standard base time known as "the epoch", namely January 1,
 206.165 +     * 1970, 00:00:00 GMT.
 206.166 +     *
 206.167 +     * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
 206.168 +     * @see     java.lang.System#currentTimeMillis()
 206.169 +     */
 206.170 +    public Date(long date) {
 206.171 +        fastTime = date;
 206.172 +    }
 206.173 +
 206.174 +    /**
 206.175 +     * Allocates a <code>Date</code> object and initializes it so that
 206.176 +     * it represents midnight, local time, at the beginning of the day
 206.177 +     * specified by the <code>year</code>, <code>month</code>, and
 206.178 +     * <code>date</code> arguments.
 206.179 +     *
 206.180 +     * @param   year    the year minus 1900.
 206.181 +     * @param   month   the month between 0-11.
 206.182 +     * @param   date    the day of the month between 1-31.
 206.183 +     * @see     java.util.Calendar
 206.184 +     * @deprecated As of JDK version 1.1,
 206.185 +     * replaced by <code>Calendar.set(year + 1900, month, date)</code>
 206.186 +     * or <code>GregorianCalendar(year + 1900, month, date)</code>.
 206.187 +     */
 206.188 +    @Deprecated
 206.189 +    public Date(int year, int month, int date) {
 206.190 +        this(year, month, date, 0, 0, 0);
 206.191 +    }
 206.192 +
 206.193 +    /**
 206.194 +     * Allocates a <code>Date</code> object and initializes it so that
 206.195 +     * it represents the instant at the start of the minute specified by
 206.196 +     * the <code>year</code>, <code>month</code>, <code>date</code>,
 206.197 +     * <code>hrs</code>, and <code>min</code> arguments, in the local
 206.198 +     * time zone.
 206.199 +     *
 206.200 +     * @param   year    the year minus 1900.
 206.201 +     * @param   month   the month between 0-11.
 206.202 +     * @param   date    the day of the month between 1-31.
 206.203 +     * @param   hrs     the hours between 0-23.
 206.204 +     * @param   min     the minutes between 0-59.
 206.205 +     * @see     java.util.Calendar
 206.206 +     * @deprecated As of JDK version 1.1,
 206.207 +     * replaced by <code>Calendar.set(year + 1900, month, date,
 206.208 +     * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
 206.209 +     * month, date, hrs, min)</code>.
 206.210 +     */
 206.211 +    @Deprecated
 206.212 +    public Date(int year, int month, int date, int hrs, int min) {
 206.213 +        this(year, month, date, hrs, min, 0);
 206.214 +    }
 206.215 +
 206.216 +    /**
 206.217 +     * Allocates a <code>Date</code> object and initializes it so that
 206.218 +     * it represents the instant at the start of the second specified
 206.219 +     * by the <code>year</code>, <code>month</code>, <code>date</code>,
 206.220 +     * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments,
 206.221 +     * in the local time zone.
 206.222 +     *
 206.223 +     * @param   year    the year minus 1900.
 206.224 +     * @param   month   the month between 0-11.
 206.225 +     * @param   date    the day of the month between 1-31.
 206.226 +     * @param   hrs     the hours between 0-23.
 206.227 +     * @param   min     the minutes between 0-59.
 206.228 +     * @param   sec     the seconds between 0-59.
 206.229 +     * @see     java.util.Calendar
 206.230 +     * @deprecated As of JDK version 1.1,
 206.231 +     * replaced by <code>Calendar.set(year + 1900, month, date,
 206.232 +     * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
 206.233 +     * month, date, hrs, min, sec)</code>.
 206.234 +     */
 206.235 +    @Deprecated
 206.236 +    public Date(int year, int month, int date, int hrs, int min, int sec) {
 206.237 +        int y = year + 1900;
 206.238 +        // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
 206.239 +        if (month >= 12) {
 206.240 +            y += month / 12;
 206.241 +            month %= 12;
 206.242 +        } else if (month < 0) {
 206.243 +            y += month / 12;
 206.244 +            month = month % 12;
 206.245 +        }
 206.246 +        BaseCalendar cal = getCalendarSystem(y);
 206.247 +        cdate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.getDefaultRef());
 206.248 +        cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
 206.249 +        getTimeImpl();
 206.250 +        cdate = null;
 206.251 +    }
 206.252 +
 206.253 +    /**
 206.254 +     * Allocates a <code>Date</code> object and initializes it so that
 206.255 +     * it represents the date and time indicated by the string
 206.256 +     * <code>s</code>, which is interpreted as if by the
 206.257 +     * {@link Date#parse} method.
 206.258 +     *
 206.259 +     * @param   s   a string representation of the date.
 206.260 +     * @see     java.text.DateFormat
 206.261 +     * @see     java.util.Date#parse(java.lang.String)
 206.262 +     * @deprecated As of JDK version 1.1,
 206.263 +     * replaced by <code>DateFormat.parse(String s)</code>.
 206.264 +     */
 206.265 +    @Deprecated
 206.266 +    public Date(String s) {
 206.267 +        this(parse(s));
 206.268 +    }
 206.269 +
 206.270 +    /**
 206.271 +     * Return a copy of this object.
 206.272 +     */
 206.273 +    public Object clone() {
 206.274 +        Date d = null;
 206.275 +        try {
 206.276 +            d = (Date)super.clone();
 206.277 +            if (cdate != null) {
 206.278 +                d.cdate = (BaseCalendar.Datum) cdate.clone();
 206.279 +            }
 206.280 +        } catch (CloneNotSupportedException e) {} // Won't happen
 206.281 +        return d;
 206.282 +    }
 206.283 +
 206.284 +    /**
 206.285 +     * Determines the date and time based on the arguments. The
 206.286 +     * arguments are interpreted as a year, month, day of the month,
 206.287 +     * hour of the day, minute within the hour, and second within the
 206.288 +     * minute, exactly as for the <tt>Date</tt> constructor with six
 206.289 +     * arguments, except that the arguments are interpreted relative
 206.290 +     * to UTC rather than to the local time zone. The time indicated is
 206.291 +     * returned represented as the distance, measured in milliseconds,
 206.292 +     * of that time from the epoch (00:00:00 GMT on January 1, 1970).
 206.293 +     *
 206.294 +     * @param   year    the year minus 1900.
 206.295 +     * @param   month   the month between 0-11.
 206.296 +     * @param   date    the day of the month between 1-31.
 206.297 +     * @param   hrs     the hours between 0-23.
 206.298 +     * @param   min     the minutes between 0-59.
 206.299 +     * @param   sec     the seconds between 0-59.
 206.300 +     * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT for
 206.301 +     *          the date and time specified by the arguments.
 206.302 +     * @see     java.util.Calendar
 206.303 +     * @deprecated As of JDK version 1.1,
 206.304 +     * replaced by <code>Calendar.set(year + 1900, month, date,
 206.305 +     * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
 206.306 +     * month, date, hrs, min, sec)</code>, using a UTC
 206.307 +     * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>.
 206.308 +     */
 206.309 +    @Deprecated
 206.310 +    public static long UTC(int year, int month, int date,
 206.311 +                           int hrs, int min, int sec) {
 206.312 +        int y = year + 1900;
 206.313 +        // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
 206.314 +        if (month >= 12) {
 206.315 +            y += month / 12;
 206.316 +            month %= 12;
 206.317 +        } else if (month < 0) {
 206.318 +            y += month / 12;
 206.319 +            month = month % 12;
 206.320 +        }
 206.321 +        int m = month + 1;
 206.322 +        BaseCalendar cal = getCalendarSystem(y);
 206.323 +        BaseCalendar.Datum udate = (BaseCalendar.Datum) cal.newCalendarDate(null);
 206.324 +        udate.setNormalizedDate(y, m, date).setTimeOfDay(hrs, min, sec, 0);
 206.325 +
 206.326 +        // Use a Date instance to perform normalization. Its fastTime
 206.327 +        // is the UTC value after the normalization.
 206.328 +        Date d = new Date(0);
 206.329 +        d.normalize(udate);
 206.330 +        return d.fastTime;
 206.331 +    }
 206.332 +
 206.333 +    /**
 206.334 +     * Attempts to interpret the string <tt>s</tt> as a representation
 206.335 +     * of a date and time. If the attempt is successful, the time
 206.336 +     * indicated is returned represented as the distance, measured in
 206.337 +     * milliseconds, of that time from the epoch (00:00:00 GMT on
 206.338 +     * January 1, 1970). If the attempt fails, an
 206.339 +     * <tt>IllegalArgumentException</tt> is thrown.
 206.340 +     * <p>
 206.341 +     * It accepts many syntaxes; in particular, it recognizes the IETF
 206.342 +     * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
 206.343 +     * understands the continental U.S. time-zone abbreviations, but for
 206.344 +     * general use, a time-zone offset should be used: "Sat, 12 Aug 1995
 206.345 +     * 13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
 206.346 +     * meridian). If no time zone is specified, the local time zone is
 206.347 +     * assumed. GMT and UTC are considered equivalent.
 206.348 +     * <p>
 206.349 +     * The string <tt>s</tt> is processed from left to right, looking for
 206.350 +     * data of interest. Any material in <tt>s</tt> that is within the
 206.351 +     * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored.
 206.352 +     * Parentheses may be nested. Otherwise, the only characters permitted
 206.353 +     * within <tt>s</tt> are these ASCII characters:
 206.354 +     * <blockquote><pre>
 206.355 +     * abcdefghijklmnopqrstuvwxyz
 206.356 +     * ABCDEFGHIJKLMNOPQRSTUVWXYZ
 206.357 +     * 0123456789,+-:/</pre></blockquote>
 206.358 +     * and whitespace characters.<p>
 206.359 +     * A consecutive sequence of decimal digits is treated as a decimal
 206.360 +     * number:<ul>
 206.361 +     * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year
 206.362 +     *     has already been recognized, then the number is a time-zone
 206.363 +     *     offset. If the number is less than 24, it is an offset measured
 206.364 +     *     in hours. Otherwise, it is regarded as an offset in minutes,
 206.365 +     *     expressed in 24-hour time format without punctuation. A
 206.366 +     *     preceding <tt>-</tt> means a westward offset. Time zone offsets
 206.367 +     *     are always relative to UTC (Greenwich). Thus, for example,
 206.368 +     *     <tt>-5</tt> occurring in the string would mean "five hours west
 206.369 +     *     of Greenwich" and <tt>+0430</tt> would mean "four hours and
 206.370 +     *     thirty minutes east of Greenwich." It is permitted for the
 206.371 +     *     string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt>
 206.372 +     *     redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>.
 206.373 +     * <li>The number is regarded as a year number if one of the
 206.374 +     *     following conditions is true:
 206.375 +     * <ul>
 206.376 +     *     <li>The number is equal to or greater than 70 and followed by a
 206.377 +     *         space, comma, slash, or end of string
 206.378 +     *     <li>The number is less than 70, and both a month and a day of
 206.379 +     *         the month have already been recognized</li>
 206.380 +     * </ul>
 206.381 +     *     If the recognized year number is less than 100, it is
 206.382 +     *     interpreted as an abbreviated year relative to a century of
 206.383 +     *     which dates are within 80 years before and 19 years after
 206.384 +     *     the time when the Date class is initialized.
 206.385 +     *     After adjusting the year number, 1900 is subtracted from
 206.386 +     *     it. For example, if the current year is 1999 then years in
 206.387 +     *     the range 19 to 99 are assumed to mean 1919 to 1999, while
 206.388 +     *     years from 0 to 18 are assumed to mean 2000 to 2018.  Note
 206.389 +     *     that this is slightly different from the interpretation of
 206.390 +     *     years less than 100 that is used in {@link java.text.SimpleDateFormat}.
 206.391 +     * <li>If the number is followed by a colon, it is regarded as an hour,
 206.392 +     *     unless an hour has already been recognized, in which case it is
 206.393 +     *     regarded as a minute.
 206.394 +     * <li>If the number is followed by a slash, it is regarded as a month
 206.395 +     *     (it is decreased by 1 to produce a number in the range <tt>0</tt>
 206.396 +     *     to <tt>11</tt>), unless a month has already been recognized, in
 206.397 +     *     which case it is regarded as a day of the month.
 206.398 +     * <li>If the number is followed by whitespace, a comma, a hyphen, or
 206.399 +     *     end of string, then if an hour has been recognized but not a
 206.400 +     *     minute, it is regarded as a minute; otherwise, if a minute has
 206.401 +     *     been recognized but not a second, it is regarded as a second;
 206.402 +     *     otherwise, it is regarded as a day of the month. </ul><p>
 206.403 +     * A consecutive sequence of letters is regarded as a word and treated
 206.404 +     * as follows:<ul>
 206.405 +     * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but
 206.406 +     *     the parse fails if an hour has not been recognized or is less
 206.407 +     *     than <tt>1</tt> or greater than <tt>12</tt>).
 206.408 +     * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt>
 206.409 +     *     to the hour (but the parse fails if an hour has not been
 206.410 +     *     recognized or is less than <tt>1</tt> or greater than <tt>12</tt>).
 206.411 +     * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY,
 206.412 +     *     WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring
 206.413 +     *     case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and
 206.414 +     *     <tt>Thurs</tt> are ignored.
 206.415 +     * <li>Otherwise, any word that matches any prefix of <tt>JANUARY,
 206.416 +     *     FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
 206.417 +     *     OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and
 206.418 +     *     considering them in the order given here, is recognized as
 206.419 +     *     specifying a month and is converted to a number (<tt>0</tt> to
 206.420 +     *     <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and
 206.421 +     *     <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which
 206.422 +     *     is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>.
 206.423 +     * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring
 206.424 +     *     case, is treated as referring to UTC.
 206.425 +     * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>,
 206.426 +     *     ignoring case, is recognized as referring to the time zone in
 206.427 +     *     North America that is five, six, seven, or eight hours west of
 206.428 +     *     Greenwich, respectively. Any word that matches <tt>EDT, CDT,
 206.429 +     *     MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as
 206.430 +     *     referring to the same time zone, respectively, during daylight
 206.431 +     *     saving time.</ul><p>
 206.432 +     * Once the entire string s has been scanned, it is converted to a time
 206.433 +     * result in one of two ways. If a time zone or time-zone offset has been
 206.434 +     * recognized, then the year, month, day of month, hour, minute, and
 206.435 +     * second are interpreted in UTC and then the time-zone offset is
 206.436 +     * applied. Otherwise, the year, month, day of month, hour, minute, and
 206.437 +     * second are interpreted in the local time zone.
 206.438 +     *
 206.439 +     * @param   s   a string to be parsed as a date.
 206.440 +     * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
 206.441 +     *          represented by the string argument.
 206.442 +     * @see     java.text.DateFormat
 206.443 +     * @deprecated As of JDK version 1.1,
 206.444 +     * replaced by <code>DateFormat.parse(String s)</code>.
 206.445 +     */
 206.446 +    @Deprecated
 206.447 +    public static long parse(String s) {
 206.448 +        int year = Integer.MIN_VALUE;
 206.449 +        int mon = -1;
 206.450 +        int mday = -1;
 206.451 +        int hour = -1;
 206.452 +        int min = -1;
 206.453 +        int sec = -1;
 206.454 +        int millis = -1;
 206.455 +        int c = -1;
 206.456 +        int i = 0;
 206.457 +        int n = -1;
 206.458 +        int wst = -1;
 206.459 +        int tzoffset = -1;
 206.460 +        int prevc = 0;
 206.461 +    syntax:
 206.462 +        {
 206.463 +            if (s == null)
 206.464 +                break syntax;
 206.465 +            int limit = s.length();
 206.466 +            while (i < limit) {
 206.467 +                c = s.charAt(i);
 206.468 +                i++;
 206.469 +                if (c <= ' ' || c == ',')
 206.470 +                    continue;
 206.471 +                if (c == '(') { // skip comments
 206.472 +                    int depth = 1;
 206.473 +                    while (i < limit) {
 206.474 +                        c = s.charAt(i);
 206.475 +                        i++;
 206.476 +                        if (c == '(') depth++;
 206.477 +                        else if (c == ')')
 206.478 +                            if (--depth <= 0)
 206.479 +                                break;
 206.480 +                    }
 206.481 +                    continue;
 206.482 +                }
 206.483 +                if ('0' <= c && c <= '9') {
 206.484 +                    n = c - '0';
 206.485 +                    while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
 206.486 +                        n = n * 10 + c - '0';
 206.487 +                        i++;
 206.488 +                    }
 206.489 +                    if (prevc == '+' || prevc == '-' && year != Integer.MIN_VALUE) {
 206.490 +                        // timezone offset
 206.491 +                        if (n < 24)
 206.492 +                            n = n * 60; // EG. "GMT-3"
 206.493 +                        else
 206.494 +                            n = n % 100 + n / 100 * 60; // eg "GMT-0430"
 206.495 +                        if (prevc == '+')   // plus means east of GMT
 206.496 +                            n = -n;
 206.497 +                        if (tzoffset != 0 && tzoffset != -1)
 206.498 +                            break syntax;
 206.499 +                        tzoffset = n;
 206.500 +                    } else if (n >= 70)
 206.501 +                        if (year != Integer.MIN_VALUE)
 206.502 +                            break syntax;
 206.503 +                        else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
 206.504 +                            // year = n < 1900 ? n : n - 1900;
 206.505 +                            year = n;
 206.506 +                        else
 206.507 +                            break syntax;
 206.508 +                    else if (c == ':')
 206.509 +                        if (hour < 0)
 206.510 +                            hour = (byte) n;
 206.511 +                        else if (min < 0)
 206.512 +                            min = (byte) n;
 206.513 +                        else
 206.514 +                            break syntax;
 206.515 +                    else if (c == '/')
 206.516 +                        if (mon < 0)
 206.517 +                            mon = (byte) (n - 1);
 206.518 +                        else if (mday < 0)
 206.519 +                            mday = (byte) n;
 206.520 +                        else
 206.521 +                            break syntax;
 206.522 +                    else if (i < limit && c != ',' && c > ' ' && c != '-')
 206.523 +                        break syntax;
 206.524 +                    else if (hour >= 0 && min < 0)
 206.525 +                        min = (byte) n;
 206.526 +                    else if (min >= 0 && sec < 0)
 206.527 +                        sec = (byte) n;
 206.528 +                    else if (mday < 0)
 206.529 +                        mday = (byte) n;
 206.530 +                    // Handle two-digit years < 70 (70-99 handled above).
 206.531 +                    else if (year == Integer.MIN_VALUE && mon >= 0 && mday >= 0)
 206.532 +                        year = n;
 206.533 +                    else
 206.534 +                        break syntax;
 206.535 +                    prevc = 0;
 206.536 +                } else if (c == '/' || c == ':' || c == '+' || c == '-')
 206.537 +                    prevc = c;
 206.538 +                else {
 206.539 +                    int st = i - 1;
 206.540 +                    while (i < limit) {
 206.541 +                        c = s.charAt(i);
 206.542 +                        if (!('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'))
 206.543 +                            break;
 206.544 +                        i++;
 206.545 +                    }
 206.546 +                    if (i <= st + 1)
 206.547 +                        break syntax;
 206.548 +                    int k;
 206.549 +                    for (k = wtb.length; --k >= 0;)
 206.550 +                        if (wtb[k].regionMatches(true, 0, s, st, i - st)) {
 206.551 +                            int action = ttb[k];
 206.552 +                            if (action != 0) {
 206.553 +                                if (action == 1) {  // pm
 206.554 +                                    if (hour > 12 || hour < 1)
 206.555 +                                        break syntax;
 206.556 +                                    else if (hour < 12)
 206.557 +                                        hour += 12;
 206.558 +                                } else if (action == 14) {  // am
 206.559 +                                    if (hour > 12 || hour < 1)
 206.560 +                                        break syntax;
 206.561 +                                    else if (hour == 12)
 206.562 +                                        hour = 0;
 206.563 +                                } else if (action <= 13) {  // month!
 206.564 +                                    if (mon < 0)
 206.565 +                                        mon = (byte) (action - 2);
 206.566 +                                    else
 206.567 +                                        break syntax;
 206.568 +                                } else {
 206.569 +                                    tzoffset = action - 10000;
 206.570 +                                }
 206.571 +                            }
 206.572 +                            break;
 206.573 +                        }
 206.574 +                    if (k < 0)
 206.575 +                        break syntax;
 206.576 +                    prevc = 0;
 206.577 +                }
 206.578 +            }
 206.579 +            if (year == Integer.MIN_VALUE || mon < 0 || mday < 0)
 206.580 +                break syntax;
 206.581 +            // Parse 2-digit years within the correct default century.
 206.582 +            if (year < 100) {
 206.583 +                synchronized (Date.class) {
 206.584 +                    if (defaultCenturyStart == 0) {
 206.585 +                        defaultCenturyStart = gcal.getCalendarDate().getYear() - 80;
 206.586 +                    }
 206.587 +                }
 206.588 +                year += (defaultCenturyStart / 100) * 100;
 206.589 +                if (year < defaultCenturyStart) year += 100;
 206.590 +            }
 206.591 +            if (sec < 0)
 206.592 +                sec = 0;
 206.593 +            if (min < 0)
 206.594 +                min = 0;
 206.595 +            if (hour < 0)
 206.596 +                hour = 0;
 206.597 +            BaseCalendar cal = getCalendarSystem(year);
 206.598 +            if (tzoffset == -1)  { // no time zone specified, have to use local
 206.599 +                BaseCalendar.Datum ldate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.getDefaultRef());
 206.600 +                ldate.setDate(year, mon + 1, mday);
 206.601 +                ldate.setTimeOfDay(hour, min, sec, 0);
 206.602 +                return cal.getTime(ldate);
 206.603 +            }
 206.604 +            BaseCalendar.Datum udate = (BaseCalendar.Datum) cal.newCalendarDate(null); // no time zone
 206.605 +            udate.setDate(year, mon + 1, mday);
 206.606 +            udate.setTimeOfDay(hour, min, sec, 0);
 206.607 +            return cal.getTime(udate) + tzoffset * (60 * 1000);
 206.608 +        }
 206.609 +        // syntax error
 206.610 +        throw new IllegalArgumentException();
 206.611 +    }
 206.612 +    private final static String wtb[] = {
 206.613 +        "am", "pm",
 206.614 +        "monday", "tuesday", "wednesday", "thursday", "friday",
 206.615 +        "saturday", "sunday",
 206.616 +        "january", "february", "march", "april", "may", "june",
 206.617 +        "july", "august", "september", "october", "november", "december",
 206.618 +        "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
 206.619 +        "mst", "mdt", "pst", "pdt"
 206.620 +    };
 206.621 +    private final static int ttb[] = {
 206.622 +        14, 1, 0, 0, 0, 0, 0, 0, 0,
 206.623 +        2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
 206.624 +        10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
 206.625 +        10000 + 5 * 60, 10000 + 4 * 60,     // EST/EDT
 206.626 +        10000 + 6 * 60, 10000 + 5 * 60,     // CST/CDT
 206.627 +        10000 + 7 * 60, 10000 + 6 * 60,     // MST/MDT
 206.628 +        10000 + 8 * 60, 10000 + 7 * 60      // PST/PDT
 206.629 +    };
 206.630 +
 206.631 +    /**
 206.632 +     * Returns a value that is the result of subtracting 1900 from the
 206.633 +     * year that contains or begins with the instant in time represented
 206.634 +     * by this <code>Date</code> object, as interpreted in the local
 206.635 +     * time zone.
 206.636 +     *
 206.637 +     * @return  the year represented by this date, minus 1900.
 206.638 +     * @see     java.util.Calendar
 206.639 +     * @deprecated As of JDK version 1.1,
 206.640 +     * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
 206.641 +     */
 206.642 +    @Deprecated
 206.643 +    public int getYear() {
 206.644 +        return normalize().getYear() - 1900;
 206.645 +    }
 206.646 +
 206.647 +    /**
 206.648 +     * Sets the year of this <tt>Date</tt> object to be the specified
 206.649 +     * value plus 1900. This <code>Date</code> object is modified so
 206.650 +     * that it represents a point in time within the specified year,
 206.651 +     * with the month, date, hour, minute, and second the same as
 206.652 +     * before, as interpreted in the local time zone. (Of course, if
 206.653 +     * the date was February 29, for example, and the year is set to a
 206.654 +     * non-leap year, then the new date will be treated as if it were
 206.655 +     * on March 1.)
 206.656 +     *
 206.657 +     * @param   year    the year value.
 206.658 +     * @see     java.util.Calendar
 206.659 +     * @deprecated As of JDK version 1.1,
 206.660 +     * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
 206.661 +     */
 206.662 +    @Deprecated
 206.663 +    public void setYear(int year) {
 206.664 +        getCalendarDate().setNormalizedYear(year + 1900);
 206.665 +    }
 206.666 +
 206.667 +    /**
 206.668 +     * Returns a number representing the month that contains or begins
 206.669 +     * with the instant in time represented by this <tt>Date</tt> object.
 206.670 +     * The value returned is between <code>0</code> and <code>11</code>,
 206.671 +     * with the value <code>0</code> representing January.
 206.672 +     *
 206.673 +     * @return  the month represented by this date.
 206.674 +     * @see     java.util.Calendar
 206.675 +     * @deprecated As of JDK version 1.1,
 206.676 +     * replaced by <code>Calendar.get(Calendar.MONTH)</code>.
 206.677 +     */
 206.678 +    @Deprecated
 206.679 +    public int getMonth() {
 206.680 +        return normalize().getMonth() - 1; // adjust 1-based to 0-based
 206.681 +    }
 206.682 +
 206.683 +    /**
 206.684 +     * Sets the month of this date to the specified value. This
 206.685 +     * <tt>Date</tt> object is modified so that it represents a point
 206.686 +     * in time within the specified month, with the year, date, hour,
 206.687 +     * minute, and second the same as before, as interpreted in the
 206.688 +     * local time zone. If the date was October 31, for example, and
 206.689 +     * the month is set to June, then the new date will be treated as
 206.690 +     * if it were on July 1, because June has only 30 days.
 206.691 +     *
 206.692 +     * @param   month   the month value between 0-11.
 206.693 +     * @see     java.util.Calendar
 206.694 +     * @deprecated As of JDK version 1.1,
 206.695 +     * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
 206.696 +     */
 206.697 +    @Deprecated
 206.698 +    public void setMonth(int month) {
 206.699 +        int y = 0;
 206.700 +        if (month >= 12) {
 206.701 +            y = month / 12;
 206.702 +            month %= 12;
 206.703 +        } else if (month < 0) {
 206.704 +            y = month / 12;
 206.705 +            month = month % 12;
 206.706 +        }
 206.707 +        BaseCalendar.Datum d = getCalendarDate();
 206.708 +        if (y != 0) {
 206.709 +            d.setNormalizedYear(d.getNormalizedYear() + y);
 206.710 +        }
 206.711 +        d.setMonth(month + 1); // adjust 0-based to 1-based month numbering
 206.712 +    }
 206.713 +
 206.714 +    /**
 206.715 +     * Returns the day of the month represented by this <tt>Date</tt> object.
 206.716 +     * The value returned is between <code>1</code> and <code>31</code>
 206.717 +     * representing the day of the month that contains or begins with the
 206.718 +     * instant in time represented by this <tt>Date</tt> object, as
 206.719 +     * interpreted in the local time zone.
 206.720 +     *
 206.721 +     * @return  the day of the month represented by this date.
 206.722 +     * @see     java.util.Calendar
 206.723 +     * @deprecated As of JDK version 1.1,
 206.724 +     * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>.
 206.725 +     * @deprecated
 206.726 +     */
 206.727 +    @Deprecated
 206.728 +    public int getDate() {
 206.729 +        return normalize().getDayOfMonth();
 206.730 +    }
 206.731 +
 206.732 +    /**
 206.733 +     * Sets the day of the month of this <tt>Date</tt> object to the
 206.734 +     * specified value. This <tt>Date</tt> object is modified so that
 206.735 +     * it represents a point in time within the specified day of the
 206.736 +     * month, with the year, month, hour, minute, and second the same
 206.737 +     * as before, as interpreted in the local time zone. If the date
 206.738 +     * was April 30, for example, and the date is set to 31, then it
 206.739 +     * will be treated as if it were on May 1, because April has only
 206.740 +     * 30 days.
 206.741 +     *
 206.742 +     * @param   date   the day of the month value between 1-31.
 206.743 +     * @see     java.util.Calendar
 206.744 +     * @deprecated As of JDK version 1.1,
 206.745 +     * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
 206.746 +     */
 206.747 +    @Deprecated
 206.748 +    public void setDate(int date) {
 206.749 +        getCalendarDate().setDayOfMonth(date);
 206.750 +    }
 206.751 +
 206.752 +    /**
 206.753 +     * Returns the day of the week represented by this date. The
 206.754 +     * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday,
 206.755 +     * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> =
 206.756 +     * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday)
 206.757 +     * represents the day of the week that contains or begins with
 206.758 +     * the instant in time represented by this <tt>Date</tt> object,
 206.759 +     * as interpreted in the local time zone.
 206.760 +     *
 206.761 +     * @return  the day of the week represented by this date.
 206.762 +     * @see     java.util.Calendar
 206.763 +     * @deprecated As of JDK version 1.1,
 206.764 +     * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
 206.765 +     */
 206.766 +    @Deprecated
 206.767 +    public int getDay() {
 206.768 +        return normalize().getDayOfWeek() - 7;//gcal.SUNDAY;
 206.769 +    }
 206.770 +
 206.771 +    /**
 206.772 +     * Returns the hour represented by this <tt>Date</tt> object. The
 206.773 +     * returned value is a number (<tt>0</tt> through <tt>23</tt>)
 206.774 +     * representing the hour within the day that contains or begins
 206.775 +     * with the instant in time represented by this <tt>Date</tt>
 206.776 +     * object, as interpreted in the local time zone.
 206.777 +     *
 206.778 +     * @return  the hour represented by this date.
 206.779 +     * @see     java.util.Calendar
 206.780 +     * @deprecated As of JDK version 1.1,
 206.781 +     * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>.
 206.782 +     */
 206.783 +    @Deprecated
 206.784 +    public int getHours() {
 206.785 +        return normalize().getHours();
 206.786 +    }
 206.787 +
 206.788 +    /**
 206.789 +     * Sets the hour of this <tt>Date</tt> object to the specified value.
 206.790 +     * This <tt>Date</tt> object is modified so that it represents a point
 206.791 +     * in time within the specified hour of the day, with the year, month,
 206.792 +     * date, minute, and second the same as before, as interpreted in the
 206.793 +     * local time zone.
 206.794 +     *
 206.795 +     * @param   hours   the hour value.
 206.796 +     * @see     java.util.Calendar
 206.797 +     * @deprecated As of JDK version 1.1,
 206.798 +     * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
 206.799 +     */
 206.800 +    @Deprecated
 206.801 +    public void setHours(int hours) {
 206.802 +        getCalendarDate().setHours(hours);
 206.803 +    }
 206.804 +
 206.805 +    /**
 206.806 +     * Returns the number of minutes past the hour represented by this date,
 206.807 +     * as interpreted in the local time zone.
 206.808 +     * The value returned is between <code>0</code> and <code>59</code>.
 206.809 +     *
 206.810 +     * @return  the number of minutes past the hour represented by this date.
 206.811 +     * @see     java.util.Calendar
 206.812 +     * @deprecated As of JDK version 1.1,
 206.813 +     * replaced by <code>Calendar.get(Calendar.MINUTE)</code>.
 206.814 +     */
 206.815 +    @Deprecated
 206.816 +    public int getMinutes() {
 206.817 +        return normalize().getMinutes();
 206.818 +    }
 206.819 +
 206.820 +    /**
 206.821 +     * Sets the minutes of this <tt>Date</tt> object to the specified value.
 206.822 +     * This <tt>Date</tt> object is modified so that it represents a point
 206.823 +     * in time within the specified minute of the hour, with the year, month,
 206.824 +     * date, hour, and second the same as before, as interpreted in the
 206.825 +     * local time zone.
 206.826 +     *
 206.827 +     * @param   minutes   the value of the minutes.
 206.828 +     * @see     java.util.Calendar
 206.829 +     * @deprecated As of JDK version 1.1,
 206.830 +     * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
 206.831 +     */
 206.832 +    @Deprecated
 206.833 +    public void setMinutes(int minutes) {
 206.834 +        getCalendarDate().setMinutes(minutes);
 206.835 +    }
 206.836 +
 206.837 +    /**
 206.838 +     * Returns the number of seconds past the minute represented by this date.
 206.839 +     * The value returned is between <code>0</code> and <code>61</code>. The
 206.840 +     * values <code>60</code> and <code>61</code> can only occur on those
 206.841 +     * Java Virtual Machines that take leap seconds into account.
 206.842 +     *
 206.843 +     * @return  the number of seconds past the minute represented by this date.
 206.844 +     * @see     java.util.Calendar
 206.845 +     * @deprecated As of JDK version 1.1,
 206.846 +     * replaced by <code>Calendar.get(Calendar.SECOND)</code>.
 206.847 +     */
 206.848 +    @Deprecated
 206.849 +    public int getSeconds() {
 206.850 +        return normalize().getSeconds();
 206.851 +    }
 206.852 +
 206.853 +    /**
 206.854 +     * Sets the seconds of this <tt>Date</tt> to the specified value.
 206.855 +     * This <tt>Date</tt> object is modified so that it represents a
 206.856 +     * point in time within the specified second of the minute, with
 206.857 +     * the year, month, date, hour, and minute the same as before, as
 206.858 +     * interpreted in the local time zone.
 206.859 +     *
 206.860 +     * @param   seconds   the seconds value.
 206.861 +     * @see     java.util.Calendar
 206.862 +     * @deprecated As of JDK version 1.1,
 206.863 +     * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
 206.864 +     */
 206.865 +    @Deprecated
 206.866 +    public void setSeconds(int seconds) {
 206.867 +        getCalendarDate().setSeconds(seconds);
 206.868 +    }
 206.869 +
 206.870 +    /**
 206.871 +     * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
 206.872 +     * represented by this <tt>Date</tt> object.
 206.873 +     *
 206.874 +     * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
 206.875 +     *          represented by this date.
 206.876 +     */
 206.877 +    public long getTime() {
 206.878 +        return getTimeImpl();
 206.879 +    }
 206.880 +
 206.881 +    private final long getTimeImpl() {
 206.882 +        if (cdate != null && !cdate.isNormalized()) {
 206.883 +            normalize();
 206.884 +        }
 206.885 +        return fastTime;
 206.886 +    }
 206.887 +
 206.888 +    /**
 206.889 +     * Sets this <code>Date</code> object to represent a point in time that is
 206.890 +     * <code>time</code> milliseconds after January 1, 1970 00:00:00 GMT.
 206.891 +     *
 206.892 +     * @param   time   the number of milliseconds.
 206.893 +     */
 206.894 +    public void setTime(long time) {
 206.895 +        fastTime = time;
 206.896 +        cdate = null;
 206.897 +    }
 206.898 +
 206.899 +    /**
 206.900 +     * Tests if this date is before the specified date.
 206.901 +     *
 206.902 +     * @param   when   a date.
 206.903 +     * @return  <code>true</code> if and only if the instant of time
 206.904 +     *            represented by this <tt>Date</tt> object is strictly
 206.905 +     *            earlier than the instant represented by <tt>when</tt>;
 206.906 +     *          <code>false</code> otherwise.
 206.907 +     * @exception NullPointerException if <code>when</code> is null.
 206.908 +     */
 206.909 +    public boolean before(Date when) {
 206.910 +        return getMillisOf(this) < getMillisOf(when);
 206.911 +    }
 206.912 +
 206.913 +    /**
 206.914 +     * Tests if this date is after the specified date.
 206.915 +     *
 206.916 +     * @param   when   a date.
 206.917 +     * @return  <code>true</code> if and only if the instant represented
 206.918 +     *          by this <tt>Date</tt> object is strictly later than the
 206.919 +     *          instant represented by <tt>when</tt>;
 206.920 +     *          <code>false</code> otherwise.
 206.921 +     * @exception NullPointerException if <code>when</code> is null.
 206.922 +     */
 206.923 +    public boolean after(Date when) {
 206.924 +        return getMillisOf(this) > getMillisOf(when);
 206.925 +    }
 206.926 +
 206.927 +    /**
 206.928 +     * Compares two dates for equality.
 206.929 +     * The result is <code>true</code> if and only if the argument is
 206.930 +     * not <code>null</code> and is a <code>Date</code> object that
 206.931 +     * represents the same point in time, to the millisecond, as this object.
 206.932 +     * <p>
 206.933 +     * Thus, two <code>Date</code> objects are equal if and only if the
 206.934 +     * <code>getTime</code> method returns the same <code>long</code>
 206.935 +     * value for both.
 206.936 +     *
 206.937 +     * @param   obj   the object to compare with.
 206.938 +     * @return  <code>true</code> if the objects are the same;
 206.939 +     *          <code>false</code> otherwise.
 206.940 +     * @see     java.util.Date#getTime()
 206.941 +     */
 206.942 +    public boolean equals(Object obj) {
 206.943 +        return obj instanceof Date && getTime() == ((Date) obj).getTime();
 206.944 +    }
 206.945 +
 206.946 +    /**
 206.947 +     * Returns the millisecond value of this <code>Date</code> object
 206.948 +     * without affecting its internal state.
 206.949 +     */
 206.950 +    static final long getMillisOf(Date date) {
 206.951 +        if (date.cdate == null || date.cdate.isNormalized()) {
 206.952 +            return date.fastTime;
 206.953 +        }
 206.954 +        BaseCalendar.Datum d = (BaseCalendar.Datum) date.cdate.clone();
 206.955 +        return gcal.getTime(d);
 206.956 +    }
 206.957 +
 206.958 +    /**
 206.959 +     * Compares two Dates for ordering.
 206.960 +     *
 206.961 +     * @param   anotherDate   the <code>Date</code> to be compared.
 206.962 +     * @return  the value <code>0</code> if the argument Date is equal to
 206.963 +     *          this Date; a value less than <code>0</code> if this Date
 206.964 +     *          is before the Date argument; and a value greater than
 206.965 +     *      <code>0</code> if this Date is after the Date argument.
 206.966 +     * @since   1.2
 206.967 +     * @exception NullPointerException if <code>anotherDate</code> is null.
 206.968 +     */
 206.969 +    public int compareTo(Date anotherDate) {
 206.970 +        long thisTime = getMillisOf(this);
 206.971 +        long anotherTime = getMillisOf(anotherDate);
 206.972 +        return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
 206.973 +    }
 206.974 +
 206.975 +    /**
 206.976 +     * Returns a hash code value for this object. The result is the
 206.977 +     * exclusive OR of the two halves of the primitive <tt>long</tt>
 206.978 +     * value returned by the {@link Date#getTime}
 206.979 +     * method. That is, the hash code is the value of the expression:
 206.980 +     * <blockquote><pre>
 206.981 +     * (int)(this.getTime()^(this.getTime() >>> 32))</pre></blockquote>
 206.982 +     *
 206.983 +     * @return  a hash code value for this object.
 206.984 +     */
 206.985 +    public int hashCode() {
 206.986 +        long ht = this.getTime();
 206.987 +        return (int) ht ^ (int) (ht >> 32);
 206.988 +    }
 206.989 +
 206.990 +    /**
 206.991 +     * Converts this <code>Date</code> object to a <code>String</code>
 206.992 +     * of the form:
 206.993 +     * <blockquote><pre>
 206.994 +     * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
 206.995 +     * where:<ul>
 206.996 +     * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
 206.997 +     *     Thu, Fri, Sat</tt>).
 206.998 +     * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
 206.999 +     *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
206.1000 +     * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
206.1001 +     *     <tt>31</tt>), as two decimal digits.
206.1002 +     * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
206.1003 +     *     <tt>23</tt>), as two decimal digits.
206.1004 +     * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
206.1005 +     *     <tt>59</tt>), as two decimal digits.
206.1006 +     * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
206.1007 +     *     <tt>61</tt>, as two decimal digits.
206.1008 +     * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
206.1009 +     *     time). Standard time zone abbreviations include those
206.1010 +     *     recognized by the method <tt>parse</tt>. If time zone
206.1011 +     *     information is not available, then <tt>zzz</tt> is empty -
206.1012 +     *     that is, it consists of no characters at all.
206.1013 +     * <li><tt>yyyy</tt> is the year, as four decimal digits.
206.1014 +     * </ul>
206.1015 +     *
206.1016 +     * @return  a string representation of this date.
206.1017 +     * @see     java.util.Date#toLocaleString()
206.1018 +     * @see     java.util.Date#toGMTString()
206.1019 +     */
206.1020 +    public String toString() {
206.1021 +        // "EEE MMM dd HH:mm:ss zzz yyyy";
206.1022 +        BaseCalendar.Datum date = normalize();
206.1023 +        StringBuilder sb = new StringBuilder(28);
206.1024 +        int index = date.getDayOfWeek();
206.1025 +        if (index == 7) {
206.1026 +            index = 8;
206.1027 +        }
206.1028 +        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
206.1029 +        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
206.1030 +//        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
206.1031 +//
206.1032 +//        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
206.1033 +//        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
206.1034 +//        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
206.1035 +//        TimeZone zi = date.getZone();
206.1036 +//        if (zi != null) {
206.1037 +//            sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
206.1038 +//        } else {
206.1039 +//            sb.append("GMT");
206.1040 +//        }
206.1041 +        sb.append(' ').append(date.getYear());  // yyyy
206.1042 +        return sb.toString();
206.1043 +    }
206.1044 +
206.1045 +    /**
206.1046 +     * Converts the given name to its 3-letter abbreviation (e.g.,
206.1047 +     * "monday" -> "Mon") and stored the abbreviation in the given
206.1048 +     * <code>StringBuilder</code>.
206.1049 +     */
206.1050 +    private static final StringBuilder convertToAbbr(StringBuilder sb, String name) {
206.1051 +        sb.append(Character.toUpperCase(name.charAt(0)));
206.1052 +        sb.append(name.charAt(1)).append(name.charAt(2));
206.1053 +        return sb;
206.1054 +    }
206.1055 +
206.1056 +    /**
206.1057 +     * Creates a string representation of this <tt>Date</tt> object in an
206.1058 +     * implementation-dependent form. The intent is that the form should
206.1059 +     * be familiar to the user of the Java application, wherever it may
206.1060 +     * happen to be running. The intent is comparable to that of the
206.1061 +     * "<code>%c</code>" format supported by the <code>strftime()</code>
206.1062 +     * function of ISO&nbsp;C.
206.1063 +     *
206.1064 +     * @return  a string representation of this date, using the locale
206.1065 +     *          conventions.
206.1066 +     * @see     java.text.DateFormat
206.1067 +     * @see     java.util.Date#toString()
206.1068 +     * @see     java.util.Date#toGMTString()
206.1069 +     * @deprecated As of JDK version 1.1,
206.1070 +     * replaced by <code>DateFormat.format(Date date)</code>.
206.1071 +     */
206.1072 +    @Deprecated
206.1073 +    public String toLocaleString() {
206.1074 +        DateFormat formatter = DateFormat.getDateTimeInstance();
206.1075 +        return formatter.format(this);
206.1076 +    }
206.1077 +
206.1078 +    /**
206.1079 +     * Creates a string representation of this <tt>Date</tt> object of
206.1080 +     * the form:
206.1081 +     * <blockquote<pre>
206.1082 +     * d mon yyyy hh:mm:ss GMT</pre></blockquote>
206.1083 +     * where:<ul>
206.1084 +     * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>),
206.1085 +     *     as one or two decimal digits.
206.1086 +     * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul,
206.1087 +     *     Aug, Sep, Oct, Nov, Dec</tt>).
206.1088 +     * <li><i>yyyy</i> is the year, as four decimal digits.
206.1089 +     * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>),
206.1090 +     *     as two decimal digits.
206.1091 +     * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through
206.1092 +     *     <tt>59</tt>), as two decimal digits.
206.1093 +     * <li><i>ss</i> is the second within the minute (<tt>00</tt> through
206.1094 +     *     <tt>61</tt>), as two decimal digits.
206.1095 +     * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate
206.1096 +     *     Greenwich Mean Time.
206.1097 +     * </ul><p>
206.1098 +     * The result does not depend on the local time zone.
206.1099 +     *
206.1100 +     * @return  a string representation of this date, using the Internet GMT
206.1101 +     *          conventions.
206.1102 +     * @see     java.text.DateFormat
206.1103 +     * @see     java.util.Date#toString()
206.1104 +     * @see     java.util.Date#toLocaleString()
206.1105 +     * @deprecated As of JDK version 1.1,
206.1106 +     * replaced by <code>DateFormat.format(Date date)</code>, using a
206.1107 +     * GMT <code>TimeZone</code>.
206.1108 +     */
206.1109 +    @Deprecated
206.1110 +    public String toGMTString() {
206.1111 +        // d MMM yyyy HH:mm:ss 'GMT'
206.1112 +        long t = getTime();
206.1113 +        BaseCalendar cal = getCalendarSystem(t);
206.1114 +        StringBuilder sb = new StringBuilder(32);
206.1115 +//        BaseCalendar.Datum date =
206.1116 +//            (BaseCalendar.Datum) cal.getCalendarDate(getTime(), (TimeZone)null);
206.1117 +//        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 1).append(' '); // d
206.1118 +//        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
206.1119 +//        sb.append(date.getYear()).append(' ');                            // yyyy
206.1120 +//        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');      // HH
206.1121 +//        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':');    // mm
206.1122 +//        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2);                // ss
206.1123 +        sb.append(" GMT");                                                // ' GMT'
206.1124 +        return sb.toString();
206.1125 +    }
206.1126 +
206.1127 +    /**
206.1128 +     * Returns the offset, measured in minutes, for the local time zone
206.1129 +     * relative to UTC that is appropriate for the time represented by
206.1130 +     * this <code>Date</code> object.
206.1131 +     * <p>
206.1132 +     * For example, in Massachusetts, five time zones west of Greenwich:
206.1133 +     * <blockquote><pre>
206.1134 +     * new Date(96, 1, 14).getTimezoneOffset() returns 300</pre></blockquote>
206.1135 +     * because on February 14, 1996, standard time (Eastern Standard Time)
206.1136 +     * is in use, which is offset five hours from UTC; but:
206.1137 +     * <blockquote><pre>
206.1138 +     * new Date(96, 5, 1).getTimezoneOffset() returns 240</pre></blockquote>
206.1139 +     * because on June 1, 1996, daylight saving time (Eastern Daylight Time)
206.1140 +     * is in use, which is offset only four hours from UTC.<p>
206.1141 +     * This method produces the same result as if it computed:
206.1142 +     * <blockquote><pre>
206.1143 +     * (this.getTime() - UTC(this.getYear(),
206.1144 +     *                       this.getMonth(),
206.1145 +     *                       this.getDate(),
206.1146 +     *                       this.getHours(),
206.1147 +     *                       this.getMinutes(),
206.1148 +     *                       this.getSeconds())) / (60 * 1000)
206.1149 +     * </pre></blockquote>
206.1150 +     *
206.1151 +     * @return  the time-zone offset, in minutes, for the current time zone.
206.1152 +     * @see     java.util.Calendar#ZONE_OFFSET
206.1153 +     * @see     java.util.Calendar#DST_OFFSET
206.1154 +     * @see     java.util.TimeZone#getDefault
206.1155 +     * @deprecated As of JDK version 1.1,
206.1156 +     * replaced by <code>-(Calendar.get(Calendar.ZONE_OFFSET) +
206.1157 +     * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)</code>.
206.1158 +     */
206.1159 +    @Deprecated
206.1160 +    public int getTimezoneOffset() {
206.1161 +        int zoneOffset;
206.1162 +        if (cdate == null) {
206.1163 +            TimeZone tz = TimeZone.getDefaultRef();
206.1164 +            zoneOffset = tz.getOffset(fastTime);
206.1165 +        } else {
206.1166 +            normalize();
206.1167 +            zoneOffset = cdate.getZoneOffset();
206.1168 +        }
206.1169 +        return -zoneOffset/60000;  // convert to minutes
206.1170 +    }
206.1171 +
206.1172 +    private final BaseCalendar.Datum getCalendarDate() {
206.1173 +        if (cdate == null) {
206.1174 +//            BaseCalendar cal = getCalendarSystem(fastTime);
206.1175 +//            cdate = (BaseCalendar.Datum) cal.getCalendarDate(fastTime,
206.1176 +//                                                            TimeZone.getDefaultRef());
206.1177 +        }
206.1178 +        return cdate;
206.1179 +    }
206.1180 +
206.1181 +    private final BaseCalendar.Datum normalize() {
206.1182 +        if (cdate == null) {
206.1183 +//            BaseCalendar cal = getCalendarSystem(fastTime);
206.1184 +//            cdate = (BaseCalendar.Datum) cal.getCalendarDate(fastTime,
206.1185 +//                                                            TimeZone.getDefaultRef());
206.1186 +//            return cdate;
206.1187 +        }
206.1188 +
206.1189 +        // Normalize cdate with the TimeZone in cdate first. This is
206.1190 +        // required for the compatible behavior.
206.1191 +        if (!cdate.isNormalized()) {
206.1192 +            cdate = normalize(cdate);
206.1193 +        }
206.1194 +
206.1195 +        // If the default TimeZone has changed, then recalculate the
206.1196 +        // fields with the new TimeZone.
206.1197 +        TimeZone tz = TimeZone.getDefaultRef();
206.1198 +        if (tz != cdate.getZone()) {
206.1199 +//            cdate.setZone(tz);
206.1200 +//            CalendarSystem cal = getCalendarSystem(cdate);
206.1201 +//            cal.getCalendarDate(fastTime, cdate);
206.1202 +        }
206.1203 +        return cdate;
206.1204 +    }
206.1205 +
206.1206 +    // fastTime and the returned data are in sync upon return.
206.1207 +    private final BaseCalendar.Datum normalize(BaseCalendar.Datum date) {
206.1208 +        int y = date.getNormalizedYear();
206.1209 +        int m = date.getMonth();
206.1210 +        int d = date.getDayOfMonth();
206.1211 +        int hh = date.getHours();
206.1212 +        int mm = date.getMinutes();
206.1213 +        int ss = date.getSeconds();
206.1214 +        int ms = date.getMillis();
206.1215 +        TimeZone tz = date.getZone();
206.1216 +
206.1217 +        // If the specified year can't be handled using a long value
206.1218 +        // in milliseconds, GregorianCalendar is used for full
206.1219 +        // compatibility with underflow and overflow. This is required
206.1220 +        // by some JCK tests. The limits are based max year values -
206.1221 +        // years that can be represented by max values of d, hh, mm,
206.1222 +        // ss and ms. Also, let GregorianCalendar handle the default
206.1223 +        // cutover year so that we don't need to worry about the
206.1224 +        // transition here.
206.1225 +//        if (y == 1582 || y > 280000000 || y < -280000000) {
206.1226 +//            if (tz == null) {
206.1227 +//                tz = TimeZone.getTimeZone("GMT");
206.1228 +//            }
206.1229 +//            GregorianCalendar gc = new GregorianCalendar(tz);
206.1230 +//            gc.clear();
206.1231 +//            gc.set(gc.MILLISECOND, ms);
206.1232 +//            gc.set(y, m-1, d, hh, mm, ss);
206.1233 +//            fastTime = gc.getTimeInMillis();
206.1234 +//            BaseCalendar cal = getCalendarSystem(fastTime);
206.1235 +//            date = (BaseCalendar.Datum) cal.getCalendarDate(fastTime, tz);
206.1236 +//            return date;
206.1237 +//        }
206.1238 +
206.1239 +        BaseCalendar cal = getCalendarSystem(y);
206.1240 +        if (cal != getCalendarSystem(date)) {
206.1241 +            date = (BaseCalendar.Datum) cal.newCalendarDate(tz);
206.1242 +            date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
206.1243 +        }
206.1244 +        // Perform the GregorianCalendar-style normalization.
206.1245 +        fastTime = cal.getTime(date);
206.1246 +
206.1247 +        // In case the normalized date requires the other calendar
206.1248 +        // system, we need to recalculate it using the other one.
206.1249 +        BaseCalendar ncal = getCalendarSystem(fastTime);
206.1250 +        if (ncal != cal) {
206.1251 +            date = (BaseCalendar.Datum) ncal.newCalendarDate(tz);
206.1252 +            date.setNormalizedDate(y, m, d).setTimeOfDay(hh, mm, ss, ms);
206.1253 +            fastTime = ncal.getTime(date);
206.1254 +        }
206.1255 +        return date;
206.1256 +    }
206.1257 +
206.1258 +    /**
206.1259 +     * Returns the Gregorian or Julian calendar system to use with the
206.1260 +     * given date. Use Gregorian from October 15, 1582.
206.1261 +     *
206.1262 +     * @param year normalized calendar year (not -1900)
206.1263 +     * @return the CalendarSystem to use for the specified date
206.1264 +     */
206.1265 +    private static final BaseCalendar getCalendarSystem(int year) {
206.1266 +        if (year >= 1582) {
206.1267 +            return gcal;
206.1268 +        }
206.1269 +        return getJulianCalendar();
206.1270 +    }
206.1271 +
206.1272 +    private static final BaseCalendar getCalendarSystem(long utc) {
206.1273 +        // Quickly check if the time stamp given by `utc' is the Epoch
206.1274 +        // or later. If it's before 1970, we convert the cutover to
206.1275 +        // local time to compare.
206.1276 +//        if (utc >= 0
206.1277 +//            || utc >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER
206.1278 +//                        - TimeZone.getDefaultRef().getOffset(utc)) {
206.1279 +            return gcal;
206.1280 +//        }
206.1281 +//        return getJulianCalendar();
206.1282 +    }
206.1283 +
206.1284 +    private static final BaseCalendar getCalendarSystem(BaseCalendar.Datum cdate) {
206.1285 +        if (jcal == null) {
206.1286 +            return gcal;
206.1287 +        }
206.1288 +        if (cdate.getEra() != null) {
206.1289 +            return jcal;
206.1290 +        }
206.1291 +        return gcal;
206.1292 +    }
206.1293 +
206.1294 +    synchronized private static final BaseCalendar getJulianCalendar() {
206.1295 +        if (jcal == null) {
206.1296 +//            jcal = (BaseCalendar) CalendarSystem.forName("julian");
206.1297 +        }
206.1298 +        return jcal;
206.1299 +    }
206.1300 +
206.1301 +    /**
206.1302 +     * Save the state of this object to a stream (i.e., serialize it).
206.1303 +     *
206.1304 +     * @serialData The value returned by <code>getTime()</code>
206.1305 +     *             is emitted (long).  This represents the offset from
206.1306 +     *             January 1, 1970, 00:00:00 GMT in milliseconds.
206.1307 +     */
206.1308 +    private void writeObject(ObjectOutputStream s)
206.1309 +         throws IOException
206.1310 +    {
206.1311 +        s.writeLong(getTimeImpl());
206.1312 +    }
206.1313 +
206.1314 +    /**
206.1315 +     * Reconstitute this object from a stream (i.e., deserialize it).
206.1316 +     */
206.1317 +    private void readObject(ObjectInputStream s)
206.1318 +         throws IOException, ClassNotFoundException
206.1319 +    {
206.1320 +        fastTime = s.readLong();
206.1321 +    }
206.1322 +    
206.1323 +    static final class BaseCalendar {
206.1324 +        Datum newCalendarDate(TimeZone t) {
206.1325 +            return new Datum();
206.1326 +        }
206.1327 +        
206.1328 +        Datum getNthDayOfWeek(int a, int b, Datum c) {
206.1329 +            return new Datum();
206.1330 +        }
206.1331 +
206.1332 +        Datum getCalendarDate() {
206.1333 +            return new Datum();
206.1334 +        }
206.1335 +
206.1336 +        int getTime(Datum udate) {
206.1337 +            return 0;
206.1338 +        }
206.1339 +
206.1340 +        int getMonthLength(Datum cdate) {
206.1341 +            return 0;
206.1342 +        }
206.1343 +
206.1344 +        void getCalendarDate(long l, Datum cdate) {
206.1345 +        }
206.1346 +        
206.1347 +        static class Datum implements Cloneable {
206.1348 +            public Datum clone() {
206.1349 +                return new Datum();
206.1350 +            }
206.1351 +            
206.1352 +            Datum setNormalizedDate(int y, int i, int date) {
206.1353 +                return this;
206.1354 +            }
206.1355 +
206.1356 +            void setTimeOfDay(int hrs, int min, int sec, int i) {
206.1357 +            }
206.1358 +
206.1359 +            int getYear() {
206.1360 +                return 0;
206.1361 +            }
206.1362 +
206.1363 +            void setDate(int year, int i, int mday) {
206.1364 +            }
206.1365 +
206.1366 +            void setNormalizedYear(int i) {
206.1367 +            }
206.1368 +
206.1369 +            int getMonth() {
206.1370 +                return 0;
206.1371 +            }
206.1372 +
206.1373 +            int getNormalizedYear() {
206.1374 +                return 0;
206.1375 +            }
206.1376 +
206.1377 +            void setMonth(int i) {
206.1378 +            }
206.1379 +
206.1380 +            int getDayOfMonth() {
206.1381 +                return 0;
206.1382 +            }
206.1383 +
206.1384 +            void setDayOfMonth(int date) {
206.1385 +            }
206.1386 +
206.1387 +            int getDayOfWeek() {
206.1388 +                return 0;
206.1389 +            }
206.1390 +
206.1391 +            int getHours() {
206.1392 +                return 0;
206.1393 +            }
206.1394 +
206.1395 +            void setHours(int hours) {
206.1396 +            }
206.1397 +
206.1398 +            int getMinutes() {
206.1399 +                return 0;
206.1400 +            }
206.1401 +
206.1402 +            void setMinutes(int minutes) {
206.1403 +            }
206.1404 +
206.1405 +            int getSeconds() {
206.1406 +                return 0;
206.1407 +            }
206.1408 +
206.1409 +            void setSeconds(int seconds) {
206.1410 +            }
206.1411 +
206.1412 +            boolean isNormalized() {
206.1413 +                return false;
206.1414 +            }
206.1415 +
206.1416 +            Object getEra() {
206.1417 +                return this;
206.1418 +            }
206.1419 +
206.1420 +            int getMillis() {
206.1421 +                return 0;
206.1422 +            }
206.1423 +
206.1424 +            TimeZone getZone() {
206.1425 +                return TimeZone.NO_TIMEZONE;
206.1426 +            }
206.1427 +
206.1428 +            int getZoneOffset() {
206.1429 +                return 0;
206.1430 +            }
206.1431 +        }
206.1432 +    }
206.1433 +}
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/rt/emul/compact/src/main/java/java/util/EnumMap.java	Wed Apr 30 15:04:10 2014 +0200
   207.3 @@ -0,0 +1,797 @@
   207.4 +/*
   207.5 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   207.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   207.7 + *
   207.8 + * This code is free software; you can redistribute it and/or modify it
   207.9 + * under the terms of the GNU General Public License version 2 only, as
  207.10 + * published by the Free Software Foundation.  Oracle designates this
  207.11 + * particular file as subject to the "Classpath" exception as provided
  207.12 + * by Oracle in the LICENSE file that accompanied this code.
  207.13 + *
  207.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  207.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  207.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  207.17 + * version 2 for more details (a copy is included in the LICENSE file that
  207.18 + * accompanied this code).
  207.19 + *
  207.20 + * You should have received a copy of the GNU General Public License version
  207.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  207.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  207.23 + *
  207.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  207.25 + * or visit www.oracle.com if you need additional information or have any
  207.26 + * questions.
  207.27 + */
  207.28 +
  207.29 +package java.util;
  207.30 +
  207.31 +import java.util.Map.Entry;
  207.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  207.33 +
  207.34 +/**
  207.35 + * A specialized {@link Map} implementation for use with enum type keys.  All
  207.36 + * of the keys in an enum map must come from a single enum type that is
  207.37 + * specified, explicitly or implicitly, when the map is created.  Enum maps
  207.38 + * are represented internally as arrays.  This representation is extremely
  207.39 + * compact and efficient.
  207.40 + *
  207.41 + * <p>Enum maps are maintained in the <i>natural order</i> of their keys
  207.42 + * (the order in which the enum constants are declared).  This is reflected
  207.43 + * in the iterators returned by the collections views ({@link #keySet()},
  207.44 + * {@link #entrySet()}, and {@link #values()}).
  207.45 + *
  207.46 + * <p>Iterators returned by the collection views are <i>weakly consistent</i>:
  207.47 + * they will never throw {@link ConcurrentModificationException} and they may
  207.48 + * or may not show the effects of any modifications to the map that occur while
  207.49 + * the iteration is in progress.
  207.50 + *
  207.51 + * <p>Null keys are not permitted.  Attempts to insert a null key will
  207.52 + * throw {@link NullPointerException}.  Attempts to test for the
  207.53 + * presence of a null key or to remove one will, however, function properly.
  207.54 + * Null values are permitted.
  207.55 +
  207.56 + * <P>Like most collection implementations <tt>EnumMap</tt> is not
  207.57 + * synchronized. If multiple threads access an enum map concurrently, and at
  207.58 + * least one of the threads modifies the map, it should be synchronized
  207.59 + * externally.  This is typically accomplished by synchronizing on some
  207.60 + * object that naturally encapsulates the enum map.  If no such object exists,
  207.61 + * the map should be "wrapped" using the {@link Collections#synchronizedMap}
  207.62 + * method.  This is best done at creation time, to prevent accidental
  207.63 + * unsynchronized access:
  207.64 + *
  207.65 + * <pre>
  207.66 + *     Map&lt;EnumKey, V&gt; m
  207.67 + *         = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
  207.68 + * </pre>
  207.69 + *
  207.70 + * <p>Implementation note: All basic operations execute in constant time.
  207.71 + * They are likely (though not guaranteed) to be faster than their
  207.72 + * {@link HashMap} counterparts.
  207.73 + *
  207.74 + * <p>This class is a member of the
  207.75 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  207.76 + * Java Collections Framework</a>.
  207.77 + *
  207.78 + * @author Josh Bloch
  207.79 + * @see EnumSet
  207.80 + * @since 1.5
  207.81 + */
  207.82 +public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
  207.83 +    implements java.io.Serializable, Cloneable
  207.84 +{
  207.85 +    /**
  207.86 +     * The <tt>Class</tt> object for the enum type of all the keys of this map.
  207.87 +     *
  207.88 +     * @serial
  207.89 +     */
  207.90 +    private final Class<K> keyType;
  207.91 +
  207.92 +    /**
  207.93 +     * All of the values comprising K.  (Cached for performance.)
  207.94 +     */
  207.95 +    private transient K[] keyUniverse;
  207.96 +
  207.97 +    /**
  207.98 +     * Array representation of this map.  The ith element is the value
  207.99 +     * to which universe[i] is currently mapped, or null if it isn't
 207.100 +     * mapped to anything, or NULL if it's mapped to null.
 207.101 +     */
 207.102 +    private transient Object[] vals;
 207.103 +
 207.104 +    /**
 207.105 +     * The number of mappings in this map.
 207.106 +     */
 207.107 +    private transient int size = 0;
 207.108 +
 207.109 +    /**
 207.110 +     * Distinguished non-null value for representing null values.
 207.111 +     */
 207.112 +    private static final Object NULL = new Integer(0);
 207.113 +
 207.114 +    private Object maskNull(Object value) {
 207.115 +        return (value == null ? NULL : value);
 207.116 +    }
 207.117 +
 207.118 +    private V unmaskNull(Object value) {
 207.119 +        return (V) (value == NULL ? null : value);
 207.120 +    }
 207.121 +
 207.122 +    private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
 207.123 +
 207.124 +    /**
 207.125 +     * Creates an empty enum map with the specified key type.
 207.126 +     *
 207.127 +     * @param keyType the class object of the key type for this enum map
 207.128 +     * @throws NullPointerException if <tt>keyType</tt> is null
 207.129 +     */
 207.130 +    public EnumMap(Class<K> keyType) {
 207.131 +        this.keyType = keyType;
 207.132 +        keyUniverse = getKeyUniverse(keyType);
 207.133 +        vals = new Object[keyUniverse.length];
 207.134 +    }
 207.135 +
 207.136 +    /**
 207.137 +     * Creates an enum map with the same key type as the specified enum
 207.138 +     * map, initially containing the same mappings (if any).
 207.139 +     *
 207.140 +     * @param m the enum map from which to initialize this enum map
 207.141 +     * @throws NullPointerException if <tt>m</tt> is null
 207.142 +     */
 207.143 +    public EnumMap(EnumMap<K, ? extends V> m) {
 207.144 +        keyType = m.keyType;
 207.145 +        keyUniverse = m.keyUniverse;
 207.146 +        vals = m.vals.clone();
 207.147 +        size = m.size;
 207.148 +    }
 207.149 +
 207.150 +    /**
 207.151 +     * Creates an enum map initialized from the specified map.  If the
 207.152 +     * specified map is an <tt>EnumMap</tt> instance, this constructor behaves
 207.153 +     * identically to {@link #EnumMap(EnumMap)}.  Otherwise, the specified map
 207.154 +     * must contain at least one mapping (in order to determine the new
 207.155 +     * enum map's key type).
 207.156 +     *
 207.157 +     * @param m the map from which to initialize this enum map
 207.158 +     * @throws IllegalArgumentException if <tt>m</tt> is not an
 207.159 +     *     <tt>EnumMap</tt> instance and contains no mappings
 207.160 +     * @throws NullPointerException if <tt>m</tt> is null
 207.161 +     */
 207.162 +    public EnumMap(Map<K, ? extends V> m) {
 207.163 +        if (m instanceof EnumMap) {
 207.164 +            EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
 207.165 +            keyType = em.keyType;
 207.166 +            keyUniverse = em.keyUniverse;
 207.167 +            vals = em.vals.clone();
 207.168 +            size = em.size;
 207.169 +        } else {
 207.170 +            if (m.isEmpty())
 207.171 +                throw new IllegalArgumentException("Specified map is empty");
 207.172 +            keyType = m.keySet().iterator().next().getDeclaringClass();
 207.173 +            keyUniverse = getKeyUniverse(keyType);
 207.174 +            vals = new Object[keyUniverse.length];
 207.175 +            putAll(m);
 207.176 +        }
 207.177 +    }
 207.178 +
 207.179 +    // Query Operations
 207.180 +
 207.181 +    /**
 207.182 +     * Returns the number of key-value mappings in this map.
 207.183 +     *
 207.184 +     * @return the number of key-value mappings in this map
 207.185 +     */
 207.186 +    public int size() {
 207.187 +        return size;
 207.188 +    }
 207.189 +
 207.190 +    /**
 207.191 +     * Returns <tt>true</tt> if this map maps one or more keys to the
 207.192 +     * specified value.
 207.193 +     *
 207.194 +     * @param value the value whose presence in this map is to be tested
 207.195 +     * @return <tt>true</tt> if this map maps one or more keys to this value
 207.196 +     */
 207.197 +    public boolean containsValue(Object value) {
 207.198 +        value = maskNull(value);
 207.199 +
 207.200 +        for (Object val : vals)
 207.201 +            if (value.equals(val))
 207.202 +                return true;
 207.203 +
 207.204 +        return false;
 207.205 +    }
 207.206 +
 207.207 +    /**
 207.208 +     * Returns <tt>true</tt> if this map contains a mapping for the specified
 207.209 +     * key.
 207.210 +     *
 207.211 +     * @param key the key whose presence in this map is to be tested
 207.212 +     * @return <tt>true</tt> if this map contains a mapping for the specified
 207.213 +     *            key
 207.214 +     */
 207.215 +    public boolean containsKey(Object key) {
 207.216 +        return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
 207.217 +    }
 207.218 +
 207.219 +    private boolean containsMapping(Object key, Object value) {
 207.220 +        return isValidKey(key) &&
 207.221 +            maskNull(value).equals(vals[((Enum)key).ordinal()]);
 207.222 +    }
 207.223 +
 207.224 +    /**
 207.225 +     * Returns the value to which the specified key is mapped,
 207.226 +     * or {@code null} if this map contains no mapping for the key.
 207.227 +     *
 207.228 +     * <p>More formally, if this map contains a mapping from a key
 207.229 +     * {@code k} to a value {@code v} such that {@code (key == k)},
 207.230 +     * then this method returns {@code v}; otherwise it returns
 207.231 +     * {@code null}.  (There can be at most one such mapping.)
 207.232 +     *
 207.233 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 207.234 +     * indicate that the map contains no mapping for the key; it's also
 207.235 +     * possible that the map explicitly maps the key to {@code null}.
 207.236 +     * The {@link #containsKey containsKey} operation may be used to
 207.237 +     * distinguish these two cases.
 207.238 +     */
 207.239 +    public V get(Object key) {
 207.240 +        return (isValidKey(key) ?
 207.241 +                unmaskNull(vals[((Enum)key).ordinal()]) : null);
 207.242 +    }
 207.243 +
 207.244 +    // Modification Operations
 207.245 +
 207.246 +    /**
 207.247 +     * Associates the specified value with the specified key in this map.
 207.248 +     * If the map previously contained a mapping for this key, the old
 207.249 +     * value is replaced.
 207.250 +     *
 207.251 +     * @param key the key with which the specified value is to be associated
 207.252 +     * @param value the value to be associated with the specified key
 207.253 +     *
 207.254 +     * @return the previous value associated with specified key, or
 207.255 +     *     <tt>null</tt> if there was no mapping for key.  (A <tt>null</tt>
 207.256 +     *     return can also indicate that the map previously associated
 207.257 +     *     <tt>null</tt> with the specified key.)
 207.258 +     * @throws NullPointerException if the specified key is null
 207.259 +     */
 207.260 +    public V put(K key, V value) {
 207.261 +        typeCheck(key);
 207.262 +
 207.263 +        int index = key.ordinal();
 207.264 +        Object oldValue = vals[index];
 207.265 +        vals[index] = maskNull(value);
 207.266 +        if (oldValue == null)
 207.267 +            size++;
 207.268 +        return unmaskNull(oldValue);
 207.269 +    }
 207.270 +
 207.271 +    /**
 207.272 +     * Removes the mapping for this key from this map if present.
 207.273 +     *
 207.274 +     * @param key the key whose mapping is to be removed from the map
 207.275 +     * @return the previous value associated with specified key, or
 207.276 +     *     <tt>null</tt> if there was no entry for key.  (A <tt>null</tt>
 207.277 +     *     return can also indicate that the map previously associated
 207.278 +     *     <tt>null</tt> with the specified key.)
 207.279 +     */
 207.280 +    public V remove(Object key) {
 207.281 +        if (!isValidKey(key))
 207.282 +            return null;
 207.283 +        int index = ((Enum)key).ordinal();
 207.284 +        Object oldValue = vals[index];
 207.285 +        vals[index] = null;
 207.286 +        if (oldValue != null)
 207.287 +            size--;
 207.288 +        return unmaskNull(oldValue);
 207.289 +    }
 207.290 +
 207.291 +    private boolean removeMapping(Object key, Object value) {
 207.292 +        if (!isValidKey(key))
 207.293 +            return false;
 207.294 +        int index = ((Enum)key).ordinal();
 207.295 +        if (maskNull(value).equals(vals[index])) {
 207.296 +            vals[index] = null;
 207.297 +            size--;
 207.298 +            return true;
 207.299 +        }
 207.300 +        return false;
 207.301 +    }
 207.302 +
 207.303 +    /**
 207.304 +     * Returns true if key is of the proper type to be a key in this
 207.305 +     * enum map.
 207.306 +     */
 207.307 +    private boolean isValidKey(Object key) {
 207.308 +        if (key == null)
 207.309 +            return false;
 207.310 +
 207.311 +        // Cheaper than instanceof Enum followed by getDeclaringClass
 207.312 +        Class keyClass = key.getClass();
 207.313 +        return keyClass == keyType || keyClass.getSuperclass() == keyType;
 207.314 +    }
 207.315 +
 207.316 +    // Bulk Operations
 207.317 +
 207.318 +    /**
 207.319 +     * Copies all of the mappings from the specified map to this map.
 207.320 +     * These mappings will replace any mappings that this map had for
 207.321 +     * any of the keys currently in the specified map.
 207.322 +     *
 207.323 +     * @param m the mappings to be stored in this map
 207.324 +     * @throws NullPointerException the specified map is null, or if
 207.325 +     *     one or more keys in the specified map are null
 207.326 +     */
 207.327 +    public void putAll(Map<? extends K, ? extends V> m) {
 207.328 +        if (m instanceof EnumMap) {
 207.329 +            EnumMap<? extends K, ? extends V> em =
 207.330 +                (EnumMap<? extends K, ? extends V>)m;
 207.331 +            if (em.keyType != keyType) {
 207.332 +                if (em.isEmpty())
 207.333 +                    return;
 207.334 +                throw new ClassCastException(em.keyType + " != " + keyType);
 207.335 +            }
 207.336 +
 207.337 +            for (int i = 0; i < keyUniverse.length; i++) {
 207.338 +                Object emValue = em.vals[i];
 207.339 +                if (emValue != null) {
 207.340 +                    if (vals[i] == null)
 207.341 +                        size++;
 207.342 +                    vals[i] = emValue;
 207.343 +                }
 207.344 +            }
 207.345 +        } else {
 207.346 +            super.putAll(m);
 207.347 +        }
 207.348 +    }
 207.349 +
 207.350 +    /**
 207.351 +     * Removes all mappings from this map.
 207.352 +     */
 207.353 +    public void clear() {
 207.354 +        Arrays.fill(vals, null);
 207.355 +        size = 0;
 207.356 +    }
 207.357 +
 207.358 +    // Views
 207.359 +
 207.360 +    /**
 207.361 +     * This field is initialized to contain an instance of the entry set
 207.362 +     * view the first time this view is requested.  The view is stateless,
 207.363 +     * so there's no reason to create more than one.
 207.364 +     */
 207.365 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 207.366 +
 207.367 +    /**
 207.368 +     * Returns a {@link Set} view of the keys contained in this map.
 207.369 +     * The returned set obeys the general contract outlined in
 207.370 +     * {@link Map#keySet()}.  The set's iterator will return the keys
 207.371 +     * in their natural order (the order in which the enum constants
 207.372 +     * are declared).
 207.373 +     *
 207.374 +     * @return a set view of the keys contained in this enum map
 207.375 +     */
 207.376 +    public Set<K> keySet() {
 207.377 +        Set<K> ks = keySet;
 207.378 +        if (ks != null)
 207.379 +            return ks;
 207.380 +        else
 207.381 +            return keySet = new KeySet();
 207.382 +    }
 207.383 +
 207.384 +    private class KeySet extends AbstractSet<K> {
 207.385 +        public Iterator<K> iterator() {
 207.386 +            return new KeyIterator();
 207.387 +        }
 207.388 +        public int size() {
 207.389 +            return size;
 207.390 +        }
 207.391 +        public boolean contains(Object o) {
 207.392 +            return containsKey(o);
 207.393 +        }
 207.394 +        public boolean remove(Object o) {
 207.395 +            int oldSize = size;
 207.396 +            EnumMap.this.remove(o);
 207.397 +            return size != oldSize;
 207.398 +        }
 207.399 +        public void clear() {
 207.400 +            EnumMap.this.clear();
 207.401 +        }
 207.402 +    }
 207.403 +
 207.404 +    /**
 207.405 +     * Returns a {@link Collection} view of the values contained in this map.
 207.406 +     * The returned collection obeys the general contract outlined in
 207.407 +     * {@link Map#values()}.  The collection's iterator will return the
 207.408 +     * values in the order their corresponding keys appear in map,
 207.409 +     * which is their natural order (the order in which the enum constants
 207.410 +     * are declared).
 207.411 +     *
 207.412 +     * @return a collection view of the values contained in this map
 207.413 +     */
 207.414 +    public Collection<V> values() {
 207.415 +        Collection<V> vs = values;
 207.416 +        if (vs != null)
 207.417 +            return vs;
 207.418 +        else
 207.419 +            return values = new Values();
 207.420 +    }
 207.421 +
 207.422 +    private class Values extends AbstractCollection<V> {
 207.423 +        public Iterator<V> iterator() {
 207.424 +            return new ValueIterator();
 207.425 +        }
 207.426 +        public int size() {
 207.427 +            return size;
 207.428 +        }
 207.429 +        public boolean contains(Object o) {
 207.430 +            return containsValue(o);
 207.431 +        }
 207.432 +        public boolean remove(Object o) {
 207.433 +            o = maskNull(o);
 207.434 +
 207.435 +            for (int i = 0; i < vals.length; i++) {
 207.436 +                if (o.equals(vals[i])) {
 207.437 +                    vals[i] = null;
 207.438 +                    size--;
 207.439 +                    return true;
 207.440 +                }
 207.441 +            }
 207.442 +            return false;
 207.443 +        }
 207.444 +        public void clear() {
 207.445 +            EnumMap.this.clear();
 207.446 +        }
 207.447 +    }
 207.448 +
 207.449 +    /**
 207.450 +     * Returns a {@link Set} view of the mappings contained in this map.
 207.451 +     * The returned set obeys the general contract outlined in
 207.452 +     * {@link Map#keySet()}.  The set's iterator will return the
 207.453 +     * mappings in the order their keys appear in map, which is their
 207.454 +     * natural order (the order in which the enum constants are declared).
 207.455 +     *
 207.456 +     * @return a set view of the mappings contained in this enum map
 207.457 +     */
 207.458 +    public Set<Map.Entry<K,V>> entrySet() {
 207.459 +        Set<Map.Entry<K,V>> es = entrySet;
 207.460 +        if (es != null)
 207.461 +            return es;
 207.462 +        else
 207.463 +            return entrySet = new EntrySet();
 207.464 +    }
 207.465 +
 207.466 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 207.467 +        public Iterator<Map.Entry<K,V>> iterator() {
 207.468 +            return new EntryIterator();
 207.469 +        }
 207.470 +
 207.471 +        public boolean contains(Object o) {
 207.472 +            if (!(o instanceof Map.Entry))
 207.473 +                return false;
 207.474 +            Map.Entry entry = (Map.Entry)o;
 207.475 +            return containsMapping(entry.getKey(), entry.getValue());
 207.476 +        }
 207.477 +        public boolean remove(Object o) {
 207.478 +            if (!(o instanceof Map.Entry))
 207.479 +                return false;
 207.480 +            Map.Entry entry = (Map.Entry)o;
 207.481 +            return removeMapping(entry.getKey(), entry.getValue());
 207.482 +        }
 207.483 +        public int size() {
 207.484 +            return size;
 207.485 +        }
 207.486 +        public void clear() {
 207.487 +            EnumMap.this.clear();
 207.488 +        }
 207.489 +        public Object[] toArray() {
 207.490 +            return fillEntryArray(new Object[size]);
 207.491 +        }
 207.492 +        @SuppressWarnings("unchecked")
 207.493 +        public <T> T[] toArray(T[] a) {
 207.494 +            int size = size();
 207.495 +            if (a.length < size)
 207.496 +                a = (T[])java.lang.reflect.Array
 207.497 +                    .newInstance(a.getClass().getComponentType(), size);
 207.498 +            if (a.length > size)
 207.499 +                a[size] = null;
 207.500 +            return (T[]) fillEntryArray(a);
 207.501 +        }
 207.502 +        private Object[] fillEntryArray(Object[] a) {
 207.503 +            int j = 0;
 207.504 +            for (int i = 0; i < vals.length; i++)
 207.505 +                if (vals[i] != null)
 207.506 +                    a[j++] = new AbstractMap.SimpleEntry<>(
 207.507 +                        keyUniverse[i], unmaskNull(vals[i]));
 207.508 +            return a;
 207.509 +        }
 207.510 +    }
 207.511 +
 207.512 +    private abstract class EnumMapIterator<T> implements Iterator<T> {
 207.513 +        // Lower bound on index of next element to return
 207.514 +        int index = 0;
 207.515 +
 207.516 +        // Index of last returned element, or -1 if none
 207.517 +        int lastReturnedIndex = -1;
 207.518 +
 207.519 +        public boolean hasNext() {
 207.520 +            while (index < vals.length && vals[index] == null)
 207.521 +                index++;
 207.522 +            return index != vals.length;
 207.523 +        }
 207.524 +
 207.525 +        public void remove() {
 207.526 +            checkLastReturnedIndex();
 207.527 +
 207.528 +            if (vals[lastReturnedIndex] != null) {
 207.529 +                vals[lastReturnedIndex] = null;
 207.530 +                size--;
 207.531 +            }
 207.532 +            lastReturnedIndex = -1;
 207.533 +        }
 207.534 +
 207.535 +        private void checkLastReturnedIndex() {
 207.536 +            if (lastReturnedIndex < 0)
 207.537 +                throw new IllegalStateException();
 207.538 +        }
 207.539 +    }
 207.540 +
 207.541 +    private class KeyIterator extends EnumMapIterator<K> {
 207.542 +        public K next() {
 207.543 +            if (!hasNext())
 207.544 +                throw new NoSuchElementException();
 207.545 +            lastReturnedIndex = index++;
 207.546 +            return keyUniverse[lastReturnedIndex];
 207.547 +        }
 207.548 +    }
 207.549 +
 207.550 +    private class ValueIterator extends EnumMapIterator<V> {
 207.551 +        public V next() {
 207.552 +            if (!hasNext())
 207.553 +                throw new NoSuchElementException();
 207.554 +            lastReturnedIndex = index++;
 207.555 +            return unmaskNull(vals[lastReturnedIndex]);
 207.556 +        }
 207.557 +    }
 207.558 +
 207.559 +    private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
 207.560 +        private Entry lastReturnedEntry = null;
 207.561 +
 207.562 +        public Map.Entry<K,V> next() {
 207.563 +            if (!hasNext())
 207.564 +                throw new NoSuchElementException();
 207.565 +            lastReturnedEntry = new Entry(index++);
 207.566 +            return lastReturnedEntry;
 207.567 +        }
 207.568 +
 207.569 +        public void remove() {
 207.570 +            lastReturnedIndex =
 207.571 +                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
 207.572 +            super.remove();
 207.573 +            lastReturnedEntry.index = lastReturnedIndex;
 207.574 +            lastReturnedEntry = null;
 207.575 +        }
 207.576 +
 207.577 +        private class Entry implements Map.Entry<K,V> {
 207.578 +            private int index;
 207.579 +
 207.580 +            private Entry(int index) {
 207.581 +                this.index = index;
 207.582 +            }
 207.583 +
 207.584 +            public K getKey() {
 207.585 +                checkIndexForEntryUse();
 207.586 +                return keyUniverse[index];
 207.587 +            }
 207.588 +
 207.589 +            public V getValue() {
 207.590 +                checkIndexForEntryUse();
 207.591 +                return unmaskNull(vals[index]);
 207.592 +            }
 207.593 +
 207.594 +            public V setValue(V value) {
 207.595 +                checkIndexForEntryUse();
 207.596 +                V oldValue = unmaskNull(vals[index]);
 207.597 +                vals[index] = maskNull(value);
 207.598 +                return oldValue;
 207.599 +            }
 207.600 +
 207.601 +            public boolean equals(Object o) {
 207.602 +                if (index < 0)
 207.603 +                    return o == this;
 207.604 +
 207.605 +                if (!(o instanceof Map.Entry))
 207.606 +                    return false;
 207.607 +
 207.608 +                Map.Entry e = (Map.Entry)o;
 207.609 +                V ourValue = unmaskNull(vals[index]);
 207.610 +                Object hisValue = e.getValue();
 207.611 +                return (e.getKey() == keyUniverse[index] &&
 207.612 +                        (ourValue == hisValue ||
 207.613 +                         (ourValue != null && ourValue.equals(hisValue))));
 207.614 +            }
 207.615 +
 207.616 +            public int hashCode() {
 207.617 +                if (index < 0)
 207.618 +                    return super.hashCode();
 207.619 +
 207.620 +                return entryHashCode(index);
 207.621 +            }
 207.622 +
 207.623 +            public String toString() {
 207.624 +                if (index < 0)
 207.625 +                    return super.toString();
 207.626 +
 207.627 +                return keyUniverse[index] + "="
 207.628 +                    + unmaskNull(vals[index]);
 207.629 +            }
 207.630 +
 207.631 +            private void checkIndexForEntryUse() {
 207.632 +                if (index < 0)
 207.633 +                    throw new IllegalStateException("Entry was removed");
 207.634 +            }
 207.635 +        }
 207.636 +    }
 207.637 +
 207.638 +    // Comparison and hashing
 207.639 +
 207.640 +    /**
 207.641 +     * Compares the specified object with this map for equality.  Returns
 207.642 +     * <tt>true</tt> if the given object is also a map and the two maps
 207.643 +     * represent the same mappings, as specified in the {@link
 207.644 +     * Map#equals(Object)} contract.
 207.645 +     *
 207.646 +     * @param o the object to be compared for equality with this map
 207.647 +     * @return <tt>true</tt> if the specified object is equal to this map
 207.648 +     */
 207.649 +    public boolean equals(Object o) {
 207.650 +        if (this == o)
 207.651 +            return true;
 207.652 +        if (o instanceof EnumMap)
 207.653 +            return equals((EnumMap)o);
 207.654 +        if (!(o instanceof Map))
 207.655 +            return false;
 207.656 +
 207.657 +        Map<K,V> m = (Map<K,V>)o;
 207.658 +        if (size != m.size())
 207.659 +            return false;
 207.660 +
 207.661 +        for (int i = 0; i < keyUniverse.length; i++) {
 207.662 +            if (null != vals[i]) {
 207.663 +                K key = keyUniverse[i];
 207.664 +                V value = unmaskNull(vals[i]);
 207.665 +                if (null == value) {
 207.666 +                    if (!((null == m.get(key)) && m.containsKey(key)))
 207.667 +                       return false;
 207.668 +                } else {
 207.669 +                   if (!value.equals(m.get(key)))
 207.670 +                      return false;
 207.671 +                }
 207.672 +            }
 207.673 +        }
 207.674 +
 207.675 +        return true;
 207.676 +    }
 207.677 +
 207.678 +    private boolean equals(EnumMap em) {
 207.679 +        if (em.keyType != keyType)
 207.680 +            return size == 0 && em.size == 0;
 207.681 +
 207.682 +        // Key types match, compare each value
 207.683 +        for (int i = 0; i < keyUniverse.length; i++) {
 207.684 +            Object ourValue =    vals[i];
 207.685 +            Object hisValue = em.vals[i];
 207.686 +            if (hisValue != ourValue &&
 207.687 +                (hisValue == null || !hisValue.equals(ourValue)))
 207.688 +                return false;
 207.689 +        }
 207.690 +        return true;
 207.691 +    }
 207.692 +
 207.693 +    /**
 207.694 +     * Returns the hash code value for this map.  The hash code of a map is
 207.695 +     * defined to be the sum of the hash codes of each entry in the map.
 207.696 +     */
 207.697 +    public int hashCode() {
 207.698 +        int h = 0;
 207.699 +
 207.700 +        for (int i = 0; i < keyUniverse.length; i++) {
 207.701 +            if (null != vals[i]) {
 207.702 +                h += entryHashCode(i);
 207.703 +            }
 207.704 +        }
 207.705 +
 207.706 +        return h;
 207.707 +    }
 207.708 +
 207.709 +    private int entryHashCode(int index) {
 207.710 +        return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
 207.711 +    }
 207.712 +
 207.713 +    /**
 207.714 +     * Returns a shallow copy of this enum map.  (The values themselves
 207.715 +     * are not cloned.
 207.716 +     *
 207.717 +     * @return a shallow copy of this enum map
 207.718 +     */
 207.719 +    public EnumMap<K, V> clone() {
 207.720 +        EnumMap<K, V> result = null;
 207.721 +        try {
 207.722 +            result = (EnumMap<K, V>) super.clone();
 207.723 +        } catch(CloneNotSupportedException e) {
 207.724 +            throw new AssertionError();
 207.725 +        }
 207.726 +        result.vals = result.vals.clone();
 207.727 +        return result;
 207.728 +    }
 207.729 +
 207.730 +    /**
 207.731 +     * Throws an exception if e is not of the correct type for this enum set.
 207.732 +     */
 207.733 +    private void typeCheck(K key) {
 207.734 +        Class keyClass = key.getClass();
 207.735 +        if (keyClass != keyType && keyClass.getSuperclass() != keyType)
 207.736 +            throw new ClassCastException(keyClass + " != " + keyType);
 207.737 +    }
 207.738 +
 207.739 +    /**
 207.740 +     * Returns all of the values comprising K.
 207.741 +     * The result is uncloned, cached, and shared by all callers.
 207.742 +     */
 207.743 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.fld_$VALUES;")
 207.744 +    private static native <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType);
 207.745 +
 207.746 +    private static final long serialVersionUID = 458661240069192865L;
 207.747 +
 207.748 +    /**
 207.749 +     * Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
 207.750 +     * serialize it).
 207.751 +     *
 207.752 +     * @serialData The <i>size</i> of the enum map (the number of key-value
 207.753 +     *             mappings) is emitted (int), followed by the key (Object)
 207.754 +     *             and value (Object) for each key-value mapping represented
 207.755 +     *             by the enum map.
 207.756 +     */
 207.757 +    private void writeObject(java.io.ObjectOutputStream s)
 207.758 +        throws java.io.IOException
 207.759 +    {
 207.760 +        // Write out the key type and any hidden stuff
 207.761 +        s.defaultWriteObject();
 207.762 +
 207.763 +        // Write out size (number of Mappings)
 207.764 +        s.writeInt(size);
 207.765 +
 207.766 +        // Write out keys and values (alternating)
 207.767 +        int entriesToBeWritten = size;
 207.768 +        for (int i = 0; entriesToBeWritten > 0; i++) {
 207.769 +            if (null != vals[i]) {
 207.770 +                s.writeObject(keyUniverse[i]);
 207.771 +                s.writeObject(unmaskNull(vals[i]));
 207.772 +                entriesToBeWritten--;
 207.773 +            }
 207.774 +        }
 207.775 +    }
 207.776 +
 207.777 +    /**
 207.778 +     * Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
 207.779 +     * deserialize it).
 207.780 +     */
 207.781 +    private void readObject(java.io.ObjectInputStream s)
 207.782 +        throws java.io.IOException, ClassNotFoundException
 207.783 +    {
 207.784 +        // Read in the key type and any hidden stuff
 207.785 +        s.defaultReadObject();
 207.786 +
 207.787 +        keyUniverse = getKeyUniverse(keyType);
 207.788 +        vals = new Object[keyUniverse.length];
 207.789 +
 207.790 +        // Read in size (number of Mappings)
 207.791 +        int size = s.readInt();
 207.792 +
 207.793 +        // Read the keys and values, and put the mappings in the HashMap
 207.794 +        for (int i = 0; i < size; i++) {
 207.795 +            K key = (K) s.readObject();
 207.796 +            V value = (V) s.readObject();
 207.797 +            put(key, value);
 207.798 +        }
 207.799 +    }
 207.800 +}
   208.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   208.2 +++ b/rt/emul/compact/src/main/java/java/util/EnumSet.java	Wed Apr 30 15:04:10 2014 +0200
   208.3 @@ -0,0 +1,441 @@
   208.4 +/*
   208.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   208.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   208.7 + *
   208.8 + * This code is free software; you can redistribute it and/or modify it
   208.9 + * under the terms of the GNU General Public License version 2 only, as
  208.10 + * published by the Free Software Foundation.  Oracle designates this
  208.11 + * particular file as subject to the "Classpath" exception as provided
  208.12 + * by Oracle in the LICENSE file that accompanied this code.
  208.13 + *
  208.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  208.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  208.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  208.17 + * version 2 for more details (a copy is included in the LICENSE file that
  208.18 + * accompanied this code).
  208.19 + *
  208.20 + * You should have received a copy of the GNU General Public License version
  208.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  208.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  208.23 + *
  208.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  208.25 + * or visit www.oracle.com if you need additional information or have any
  208.26 + * questions.
  208.27 + */
  208.28 +
  208.29 +package java.util;
  208.30 +
  208.31 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  208.32 +
  208.33 +/**
  208.34 + * A specialized {@link Set} implementation for use with enum types.  All of
  208.35 + * the elements in an enum set must come from a single enum type that is
  208.36 + * specified, explicitly or implicitly, when the set is created.  Enum sets
  208.37 + * are represented internally as bit vectors.  This representation is
  208.38 + * extremely compact and efficient. The space and time performance of this
  208.39 + * class should be good enough to allow its use as a high-quality, typesafe
  208.40 + * alternative to traditional <tt>int</tt>-based "bit flags."  Even bulk
  208.41 + * operations (such as <tt>containsAll</tt> and <tt>retainAll</tt>) should
  208.42 + * run very quickly if their argument is also an enum set.
  208.43 + *
  208.44 + * <p>The iterator returned by the <tt>iterator</tt> method traverses the
  208.45 + * elements in their <i>natural order</i> (the order in which the enum
  208.46 + * constants are declared).  The returned iterator is <i>weakly
  208.47 + * consistent</i>: it will never throw {@link ConcurrentModificationException}
  208.48 + * and it may or may not show the effects of any modifications to the set that
  208.49 + * occur while the iteration is in progress.
  208.50 + *
  208.51 + * <p>Null elements are not permitted.  Attempts to insert a null element
  208.52 + * will throw {@link NullPointerException}.  Attempts to test for the
  208.53 + * presence of a null element or to remove one will, however, function
  208.54 + * properly.
  208.55 + *
  208.56 + * <P>Like most collection implementations, <tt>EnumSet</tt> is not
  208.57 + * synchronized.  If multiple threads access an enum set concurrently, and at
  208.58 + * least one of the threads modifies the set, it should be synchronized
  208.59 + * externally.  This is typically accomplished by synchronizing on some
  208.60 + * object that naturally encapsulates the enum set.  If no such object exists,
  208.61 + * the set should be "wrapped" using the {@link Collections#synchronizedSet}
  208.62 + * method.  This is best done at creation time, to prevent accidental
  208.63 + * unsynchronized access:
  208.64 + *
  208.65 + * <pre>
  208.66 + * Set&lt;MyEnum&gt; s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
  208.67 + * </pre>
  208.68 + *
  208.69 + * <p>Implementation note: All basic operations execute in constant time.
  208.70 + * They are likely (though not guaranteed) to be much faster than their
  208.71 + * {@link HashSet} counterparts.  Even bulk operations execute in
  208.72 + * constant time if their argument is also an enum set.
  208.73 + *
  208.74 + * <p>This class is a member of the
  208.75 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  208.76 + * Java Collections Framework</a>.
  208.77 + *
  208.78 + * @author Josh Bloch
  208.79 + * @since 1.5
  208.80 + * @see EnumMap
  208.81 + * @serial exclude
  208.82 + */
  208.83 +public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
  208.84 +    implements Cloneable, java.io.Serializable
  208.85 +{
  208.86 +    /**
  208.87 +     * The class of all the elements of this set.
  208.88 +     */
  208.89 +    final Class<E> elementType;
  208.90 +
  208.91 +    /**
  208.92 +     * All of the values comprising T.  (Cached for performance.)
  208.93 +     */
  208.94 +    final Enum[] universe;
  208.95 +
  208.96 +    private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
  208.97 +
  208.98 +    EnumSet(Class<E>elementType, Enum[] universe) {
  208.99 +        this.elementType = elementType;
 208.100 +        this.universe    = universe;
 208.101 +    }
 208.102 +
 208.103 +    /**
 208.104 +     * Creates an empty enum set with the specified element type.
 208.105 +     *
 208.106 +     * @param elementType the class object of the element type for this enum
 208.107 +     *     set
 208.108 +     * @throws NullPointerException if <tt>elementType</tt> is null
 208.109 +     */
 208.110 +    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
 208.111 +        Enum[] universe = getUniverse(elementType);
 208.112 +        if (universe == null)
 208.113 +            throw new ClassCastException(elementType + " not an enum");
 208.114 +
 208.115 +        if (universe.length <= 64)
 208.116 +            return new RegularEnumSet<>(elementType, universe);
 208.117 +        else
 208.118 +            return new JumboEnumSet<>(elementType, universe);
 208.119 +    }
 208.120 +
 208.121 +    /**
 208.122 +     * Creates an enum set containing all of the elements in the specified
 208.123 +     * element type.
 208.124 +     *
 208.125 +     * @param elementType the class object of the element type for this enum
 208.126 +     *     set
 208.127 +     * @throws NullPointerException if <tt>elementType</tt> is null
 208.128 +     */
 208.129 +    public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
 208.130 +        EnumSet<E> result = noneOf(elementType);
 208.131 +        result.addAll();
 208.132 +        return result;
 208.133 +    }
 208.134 +
 208.135 +    /**
 208.136 +     * Adds all of the elements from the appropriate enum type to this enum
 208.137 +     * set, which is empty prior to the call.
 208.138 +     */
 208.139 +    abstract void addAll();
 208.140 +
 208.141 +    /**
 208.142 +     * Creates an enum set with the same element type as the specified enum
 208.143 +     * set, initially containing the same elements (if any).
 208.144 +     *
 208.145 +     * @param s the enum set from which to initialize this enum set
 208.146 +     * @throws NullPointerException if <tt>s</tt> is null
 208.147 +     */
 208.148 +    public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
 208.149 +        return s.clone();
 208.150 +    }
 208.151 +
 208.152 +    /**
 208.153 +     * Creates an enum set initialized from the specified collection.  If
 208.154 +     * the specified collection is an <tt>EnumSet</tt> instance, this static
 208.155 +     * factory method behaves identically to {@link #copyOf(EnumSet)}.
 208.156 +     * Otherwise, the specified collection must contain at least one element
 208.157 +     * (in order to determine the new enum set's element type).
 208.158 +     *
 208.159 +     * @param c the collection from which to initialize this enum set
 208.160 +     * @throws IllegalArgumentException if <tt>c</tt> is not an
 208.161 +     *     <tt>EnumSet</tt> instance and contains no elements
 208.162 +     * @throws NullPointerException if <tt>c</tt> is null
 208.163 +     */
 208.164 +    public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
 208.165 +        if (c instanceof EnumSet) {
 208.166 +            return ((EnumSet<E>)c).clone();
 208.167 +        } else {
 208.168 +            if (c.isEmpty())
 208.169 +                throw new IllegalArgumentException("Collection is empty");
 208.170 +            Iterator<E> i = c.iterator();
 208.171 +            E first = i.next();
 208.172 +            EnumSet<E> result = EnumSet.of(first);
 208.173 +            while (i.hasNext())
 208.174 +                result.add(i.next());
 208.175 +            return result;
 208.176 +        }
 208.177 +    }
 208.178 +
 208.179 +    /**
 208.180 +     * Creates an enum set with the same element type as the specified enum
 208.181 +     * set, initially containing all the elements of this type that are
 208.182 +     * <i>not</i> contained in the specified set.
 208.183 +     *
 208.184 +     * @param s the enum set from whose complement to initialize this enum set
 208.185 +     * @throws NullPointerException if <tt>s</tt> is null
 208.186 +     */
 208.187 +    public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
 208.188 +        EnumSet<E> result = copyOf(s);
 208.189 +        result.complement();
 208.190 +        return result;
 208.191 +    }
 208.192 +
 208.193 +    /**
 208.194 +     * Creates an enum set initially containing the specified element.
 208.195 +     *
 208.196 +     * Overloadings of this method exist to initialize an enum set with
 208.197 +     * one through five elements.  A sixth overloading is provided that
 208.198 +     * uses the varargs feature.  This overloading may be used to create
 208.199 +     * an enum set initially containing an arbitrary number of elements, but
 208.200 +     * is likely to run slower than the overloadings that do not use varargs.
 208.201 +     *
 208.202 +     * @param e the element that this set is to contain initially
 208.203 +     * @throws NullPointerException if <tt>e</tt> is null
 208.204 +     * @return an enum set initially containing the specified element
 208.205 +     */
 208.206 +    public static <E extends Enum<E>> EnumSet<E> of(E e) {
 208.207 +        EnumSet<E> result = noneOf(e.getDeclaringClass());
 208.208 +        result.add(e);
 208.209 +        return result;
 208.210 +    }
 208.211 +
 208.212 +    /**
 208.213 +     * Creates an enum set initially containing the specified elements.
 208.214 +     *
 208.215 +     * Overloadings of this method exist to initialize an enum set with
 208.216 +     * one through five elements.  A sixth overloading is provided that
 208.217 +     * uses the varargs feature.  This overloading may be used to create
 208.218 +     * an enum set initially containing an arbitrary number of elements, but
 208.219 +     * is likely to run slower than the overloadings that do not use varargs.
 208.220 +     *
 208.221 +     * @param e1 an element that this set is to contain initially
 208.222 +     * @param e2 another element that this set is to contain initially
 208.223 +     * @throws NullPointerException if any parameters are null
 208.224 +     * @return an enum set initially containing the specified elements
 208.225 +     */
 208.226 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
 208.227 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 208.228 +        result.add(e1);
 208.229 +        result.add(e2);
 208.230 +        return result;
 208.231 +    }
 208.232 +
 208.233 +    /**
 208.234 +     * Creates an enum set initially containing the specified elements.
 208.235 +     *
 208.236 +     * Overloadings of this method exist to initialize an enum set with
 208.237 +     * one through five elements.  A sixth overloading is provided that
 208.238 +     * uses the varargs feature.  This overloading may be used to create
 208.239 +     * an enum set initially containing an arbitrary number of elements, but
 208.240 +     * is likely to run slower than the overloadings that do not use varargs.
 208.241 +     *
 208.242 +     * @param e1 an element that this set is to contain initially
 208.243 +     * @param e2 another element that this set is to contain initially
 208.244 +     * @param e3 another element that this set is to contain initially
 208.245 +     * @throws NullPointerException if any parameters are null
 208.246 +     * @return an enum set initially containing the specified elements
 208.247 +     */
 208.248 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
 208.249 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 208.250 +        result.add(e1);
 208.251 +        result.add(e2);
 208.252 +        result.add(e3);
 208.253 +        return result;
 208.254 +    }
 208.255 +
 208.256 +    /**
 208.257 +     * Creates an enum set initially containing the specified elements.
 208.258 +     *
 208.259 +     * Overloadings of this method exist to initialize an enum set with
 208.260 +     * one through five elements.  A sixth overloading is provided that
 208.261 +     * uses the varargs feature.  This overloading may be used to create
 208.262 +     * an enum set initially containing an arbitrary number of elements, but
 208.263 +     * is likely to run slower than the overloadings that do not use varargs.
 208.264 +     *
 208.265 +     * @param e1 an element that this set is to contain initially
 208.266 +     * @param e2 another element that this set is to contain initially
 208.267 +     * @param e3 another element that this set is to contain initially
 208.268 +     * @param e4 another element that this set is to contain initially
 208.269 +     * @throws NullPointerException if any parameters are null
 208.270 +     * @return an enum set initially containing the specified elements
 208.271 +     */
 208.272 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
 208.273 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 208.274 +        result.add(e1);
 208.275 +        result.add(e2);
 208.276 +        result.add(e3);
 208.277 +        result.add(e4);
 208.278 +        return result;
 208.279 +    }
 208.280 +
 208.281 +    /**
 208.282 +     * Creates an enum set initially containing the specified elements.
 208.283 +     *
 208.284 +     * Overloadings of this method exist to initialize an enum set with
 208.285 +     * one through five elements.  A sixth overloading is provided that
 208.286 +     * uses the varargs feature.  This overloading may be used to create
 208.287 +     * an enum set initially containing an arbitrary number of elements, but
 208.288 +     * is likely to run slower than the overloadings that do not use varargs.
 208.289 +     *
 208.290 +     * @param e1 an element that this set is to contain initially
 208.291 +     * @param e2 another element that this set is to contain initially
 208.292 +     * @param e3 another element that this set is to contain initially
 208.293 +     * @param e4 another element that this set is to contain initially
 208.294 +     * @param e5 another element that this set is to contain initially
 208.295 +     * @throws NullPointerException if any parameters are null
 208.296 +     * @return an enum set initially containing the specified elements
 208.297 +     */
 208.298 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4,
 208.299 +                                                    E e5)
 208.300 +    {
 208.301 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 208.302 +        result.add(e1);
 208.303 +        result.add(e2);
 208.304 +        result.add(e3);
 208.305 +        result.add(e4);
 208.306 +        result.add(e5);
 208.307 +        return result;
 208.308 +    }
 208.309 +
 208.310 +    /**
 208.311 +     * Creates an enum set initially containing the specified elements.
 208.312 +     * This factory, whose parameter list uses the varargs feature, may
 208.313 +     * be used to create an enum set initially containing an arbitrary
 208.314 +     * number of elements, but it is likely to run slower than the overloadings
 208.315 +     * that do not use varargs.
 208.316 +     *
 208.317 +     * @param first an element that the set is to contain initially
 208.318 +     * @param rest the remaining elements the set is to contain initially
 208.319 +     * @throws NullPointerException if any of the specified elements are null,
 208.320 +     *     or if <tt>rest</tt> is null
 208.321 +     * @return an enum set initially containing the specified elements
 208.322 +     */
 208.323 +    @SafeVarargs
 208.324 +    public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
 208.325 +        EnumSet<E> result = noneOf(first.getDeclaringClass());
 208.326 +        result.add(first);
 208.327 +        for (E e : rest)
 208.328 +            result.add(e);
 208.329 +        return result;
 208.330 +    }
 208.331 +
 208.332 +    /**
 208.333 +     * Creates an enum set initially containing all of the elements in the
 208.334 +     * range defined by the two specified endpoints.  The returned set will
 208.335 +     * contain the endpoints themselves, which may be identical but must not
 208.336 +     * be out of order.
 208.337 +     *
 208.338 +     * @param from the first element in the range
 208.339 +     * @param to the last element in the range
 208.340 +     * @throws NullPointerException if {@code from} or {@code to} are null
 208.341 +     * @throws IllegalArgumentException if {@code from.compareTo(to) > 0}
 208.342 +     * @return an enum set initially containing all of the elements in the
 208.343 +     *         range defined by the two specified endpoints
 208.344 +     */
 208.345 +    public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
 208.346 +        if (from.compareTo(to) > 0)
 208.347 +            throw new IllegalArgumentException(from + " > " + to);
 208.348 +        EnumSet<E> result = noneOf(from.getDeclaringClass());
 208.349 +        result.addRange(from, to);
 208.350 +        return result;
 208.351 +    }
 208.352 +
 208.353 +    /**
 208.354 +     * Adds the specified range to this enum set, which is empty prior
 208.355 +     * to the call.
 208.356 +     */
 208.357 +    abstract void addRange(E from, E to);
 208.358 +
 208.359 +    /**
 208.360 +     * Returns a copy of this set.
 208.361 +     *
 208.362 +     * @return a copy of this set
 208.363 +     */
 208.364 +    public EnumSet<E> clone() {
 208.365 +        try {
 208.366 +            return (EnumSet<E>) super.clone();
 208.367 +        } catch(CloneNotSupportedException e) {
 208.368 +            throw new AssertionError(e);
 208.369 +        }
 208.370 +    }
 208.371 +
 208.372 +    /**
 208.373 +     * Complements the contents of this enum set.
 208.374 +     */
 208.375 +    abstract void complement();
 208.376 +
 208.377 +    /**
 208.378 +     * Throws an exception if e is not of the correct type for this enum set.
 208.379 +     */
 208.380 +    final void typeCheck(E e) {
 208.381 +        Class eClass = e.getClass();
 208.382 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 208.383 +            throw new ClassCastException(eClass + " != " + elementType);
 208.384 +    }
 208.385 +
 208.386 +    /**
 208.387 +     * Returns all of the values comprising E.
 208.388 +     * The result is uncloned, cached, and shared by all callers.
 208.389 +     */
 208.390 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.fld_$VALUES;")
 208.391 +    private static native <E extends Enum<E>> E[] getUniverse(Class<E> elementType);
 208.392 +
 208.393 +    /**
 208.394 +     * This class is used to serialize all EnumSet instances, regardless of
 208.395 +     * implementation type.  It captures their "logical contents" and they
 208.396 +     * are reconstructed using public static factories.  This is necessary
 208.397 +     * to ensure that the existence of a particular implementation type is
 208.398 +     * an implementation detail.
 208.399 +     *
 208.400 +     * @serial include
 208.401 +     */
 208.402 +    private static class SerializationProxy <E extends Enum<E>>
 208.403 +        implements java.io.Serializable
 208.404 +    {
 208.405 +        /**
 208.406 +         * The element type of this enum set.
 208.407 +         *
 208.408 +         * @serial
 208.409 +         */
 208.410 +        private final Class<E> elementType;
 208.411 +
 208.412 +        /**
 208.413 +         * The elements contained in this enum set.
 208.414 +         *
 208.415 +         * @serial
 208.416 +         */
 208.417 +        private final Enum[] elements;
 208.418 +
 208.419 +        SerializationProxy(EnumSet<E> set) {
 208.420 +            elementType = set.elementType;
 208.421 +            elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
 208.422 +        }
 208.423 +
 208.424 +        private Object readResolve() {
 208.425 +            EnumSet<E> result = EnumSet.noneOf(elementType);
 208.426 +            for (Enum e : elements)
 208.427 +                result.add((E)e);
 208.428 +            return result;
 208.429 +        }
 208.430 +
 208.431 +        private static final long serialVersionUID = 362491234563181265L;
 208.432 +    }
 208.433 +
 208.434 +    Object writeReplace() {
 208.435 +        return new SerializationProxy<>(this);
 208.436 +    }
 208.437 +
 208.438 +    // readObject method for the serialization proxy pattern
 208.439 +    // See Effective Java, Second Ed., Item 78.
 208.440 +    private void readObject(java.io.ObjectInputStream stream)
 208.441 +        throws java.io.InvalidObjectException {
 208.442 +        throw new java.io.InvalidObjectException("Proxy required");
 208.443 +    }
 208.444 +}
   209.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   209.2 +++ b/rt/emul/compact/src/main/java/java/util/IdentityHashMap.java	Wed Apr 30 15:04:10 2014 +0200
   209.3 @@ -0,0 +1,1243 @@
   209.4 +/*
   209.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   209.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   209.7 + *
   209.8 + * This code is free software; you can redistribute it and/or modify it
   209.9 + * under the terms of the GNU General Public License version 2 only, as
  209.10 + * published by the Free Software Foundation.  Oracle designates this
  209.11 + * particular file as subject to the "Classpath" exception as provided
  209.12 + * by Oracle in the LICENSE file that accompanied this code.
  209.13 + *
  209.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  209.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  209.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  209.17 + * version 2 for more details (a copy is included in the LICENSE file that
  209.18 + * accompanied this code).
  209.19 + *
  209.20 + * You should have received a copy of the GNU General Public License version
  209.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  209.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  209.23 + *
  209.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  209.25 + * or visit www.oracle.com if you need additional information or have any
  209.26 + * questions.
  209.27 + */
  209.28 +
  209.29 +package java.util;
  209.30 +import java.io.*;
  209.31 +
  209.32 +/**
  209.33 + * This class implements the <tt>Map</tt> interface with a hash table, using
  209.34 + * reference-equality in place of object-equality when comparing keys (and
  209.35 + * values).  In other words, in an <tt>IdentityHashMap</tt>, two keys
  209.36 + * <tt>k1</tt> and <tt>k2</tt> are considered equal if and only if
  209.37 + * <tt>(k1==k2)</tt>.  (In normal <tt>Map</tt> implementations (like
  209.38 + * <tt>HashMap</tt>) two keys <tt>k1</tt> and <tt>k2</tt> are considered equal
  209.39 + * if and only if <tt>(k1==null ? k2==null : k1.equals(k2))</tt>.)
  209.40 + *
  209.41 + * <p><b>This class is <i>not</i> a general-purpose <tt>Map</tt>
  209.42 + * implementation!  While this class implements the <tt>Map</tt> interface, it
  209.43 + * intentionally violates <tt>Map's</tt> general contract, which mandates the
  209.44 + * use of the <tt>equals</tt> method when comparing objects.  This class is
  209.45 + * designed for use only in the rare cases wherein reference-equality
  209.46 + * semantics are required.</b>
  209.47 + *
  209.48 + * <p>A typical use of this class is <i>topology-preserving object graph
  209.49 + * transformations</i>, such as serialization or deep-copying.  To perform such
  209.50 + * a transformation, a program must maintain a "node table" that keeps track
  209.51 + * of all the object references that have already been processed.  The node
  209.52 + * table must not equate distinct objects even if they happen to be equal.
  209.53 + * Another typical use of this class is to maintain <i>proxy objects</i>.  For
  209.54 + * example, a debugging facility might wish to maintain a proxy object for
  209.55 + * each object in the program being debugged.
  209.56 + *
  209.57 + * <p>This class provides all of the optional map operations, and permits
  209.58 + * <tt>null</tt> values and the <tt>null</tt> key.  This class makes no
  209.59 + * guarantees as to the order of the map; in particular, it does not guarantee
  209.60 + * that the order will remain constant over time.
  209.61 + *
  209.62 + * <p>This class provides constant-time performance for the basic
  209.63 + * operations (<tt>get</tt> and <tt>put</tt>), assuming the system
  209.64 + * identity hash function ({@link System#identityHashCode(Object)})
  209.65 + * disperses elements properly among the buckets.
  209.66 + *
  209.67 + * <p>This class has one tuning parameter (which affects performance but not
  209.68 + * semantics): <i>expected maximum size</i>.  This parameter is the maximum
  209.69 + * number of key-value mappings that the map is expected to hold.  Internally,
  209.70 + * this parameter is used to determine the number of buckets initially
  209.71 + * comprising the hash table.  The precise relationship between the expected
  209.72 + * maximum size and the number of buckets is unspecified.
  209.73 + *
  209.74 + * <p>If the size of the map (the number of key-value mappings) sufficiently
  209.75 + * exceeds the expected maximum size, the number of buckets is increased
  209.76 + * Increasing the number of buckets ("rehashing") may be fairly expensive, so
  209.77 + * it pays to create identity hash maps with a sufficiently large expected
  209.78 + * maximum size.  On the other hand, iteration over collection views requires
  209.79 + * time proportional to the number of buckets in the hash table, so it
  209.80 + * pays not to set the expected maximum size too high if you are especially
  209.81 + * concerned with iteration performance or memory usage.
  209.82 + *
  209.83 + * <p><strong>Note that this implementation is not synchronized.</strong>
  209.84 + * If multiple threads access an identity hash map concurrently, and at
  209.85 + * least one of the threads modifies the map structurally, it <i>must</i>
  209.86 + * be synchronized externally.  (A structural modification is any operation
  209.87 + * that adds or deletes one or more mappings; merely changing the value
  209.88 + * associated with a key that an instance already contains is not a
  209.89 + * structural modification.)  This is typically accomplished by
  209.90 + * synchronizing on some object that naturally encapsulates the map.
  209.91 + *
  209.92 + * If no such object exists, the map should be "wrapped" using the
  209.93 + * {@link Collections#synchronizedMap Collections.synchronizedMap}
  209.94 + * method.  This is best done at creation time, to prevent accidental
  209.95 + * unsynchronized access to the map:<pre>
  209.96 + *   Map m = Collections.synchronizedMap(new IdentityHashMap(...));</pre>
  209.97 + *
  209.98 + * <p>The iterators returned by the <tt>iterator</tt> method of the
  209.99 + * collections returned by all of this class's "collection view
 209.100 + * methods" are <i>fail-fast</i>: if the map is structurally modified
 209.101 + * at any time after the iterator is created, in any way except
 209.102 + * through the iterator's own <tt>remove</tt> method, the iterator
 209.103 + * will throw a {@link ConcurrentModificationException}.  Thus, in the
 209.104 + * face of concurrent modification, the iterator fails quickly and
 209.105 + * cleanly, rather than risking arbitrary, non-deterministic behavior
 209.106 + * at an undetermined time in the future.
 209.107 + *
 209.108 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 209.109 + * as it is, generally speaking, impossible to make any hard guarantees in the
 209.110 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 209.111 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 209.112 + * Therefore, it would be wrong to write a program that depended on this
 209.113 + * exception for its correctness: <i>fail-fast iterators should be used only
 209.114 + * to detect bugs.</i>
 209.115 + *
 209.116 + * <p>Implementation note: This is a simple <i>linear-probe</i> hash table,
 209.117 + * as described for example in texts by Sedgewick and Knuth.  The array
 209.118 + * alternates holding keys and values.  (This has better locality for large
 209.119 + * tables than does using separate arrays.)  For many JRE implementations
 209.120 + * and operation mixes, this class will yield better performance than
 209.121 + * {@link HashMap} (which uses <i>chaining</i> rather than linear-probing).
 209.122 + *
 209.123 + * <p>This class is a member of the
 209.124 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 209.125 + * Java Collections Framework</a>.
 209.126 + *
 209.127 + * @see     System#identityHashCode(Object)
 209.128 + * @see     Object#hashCode()
 209.129 + * @see     Collection
 209.130 + * @see     Map
 209.131 + * @see     HashMap
 209.132 + * @see     TreeMap
 209.133 + * @author  Doug Lea and Josh Bloch
 209.134 + * @since   1.4
 209.135 + */
 209.136 +
 209.137 +public class IdentityHashMap<K,V>
 209.138 +    extends AbstractMap<K,V>
 209.139 +    implements Map<K,V>, java.io.Serializable, Cloneable
 209.140 +{
 209.141 +    /**
 209.142 +     * The initial capacity used by the no-args constructor.
 209.143 +     * MUST be a power of two.  The value 32 corresponds to the
 209.144 +     * (specified) expected maximum size of 21, given a load factor
 209.145 +     * of 2/3.
 209.146 +     */
 209.147 +    private static final int DEFAULT_CAPACITY = 32;
 209.148 +
 209.149 +    /**
 209.150 +     * The minimum capacity, used if a lower value is implicitly specified
 209.151 +     * by either of the constructors with arguments.  The value 4 corresponds
 209.152 +     * to an expected maximum size of 2, given a load factor of 2/3.
 209.153 +     * MUST be a power of two.
 209.154 +     */
 209.155 +    private static final int MINIMUM_CAPACITY = 4;
 209.156 +
 209.157 +    /**
 209.158 +     * The maximum capacity, used if a higher value is implicitly specified
 209.159 +     * by either of the constructors with arguments.
 209.160 +     * MUST be a power of two <= 1<<29.
 209.161 +     */
 209.162 +    private static final int MAXIMUM_CAPACITY = 1 << 29;
 209.163 +
 209.164 +    /**
 209.165 +     * The table, resized as necessary. Length MUST always be a power of two.
 209.166 +     */
 209.167 +    private transient Object[] table;
 209.168 +
 209.169 +    /**
 209.170 +     * The number of key-value mappings contained in this identity hash map.
 209.171 +     *
 209.172 +     * @serial
 209.173 +     */
 209.174 +    private int size;
 209.175 +
 209.176 +    /**
 209.177 +     * The number of modifications, to support fast-fail iterators
 209.178 +     */
 209.179 +    private transient int modCount;
 209.180 +
 209.181 +    /**
 209.182 +     * The next size value at which to resize (capacity * load factor).
 209.183 +     */
 209.184 +    private transient int threshold;
 209.185 +
 209.186 +    /**
 209.187 +     * Value representing null keys inside tables.
 209.188 +     */
 209.189 +    private static final Object NULL_KEY = new Object();
 209.190 +
 209.191 +    /**
 209.192 +     * Use NULL_KEY for key if it is null.
 209.193 +     */
 209.194 +    private static Object maskNull(Object key) {
 209.195 +        return (key == null ? NULL_KEY : key);
 209.196 +    }
 209.197 +
 209.198 +    /**
 209.199 +     * Returns internal representation of null key back to caller as null.
 209.200 +     */
 209.201 +    private static Object unmaskNull(Object key) {
 209.202 +        return (key == NULL_KEY ? null : key);
 209.203 +    }
 209.204 +
 209.205 +    /**
 209.206 +     * Constructs a new, empty identity hash map with a default expected
 209.207 +     * maximum size (21).
 209.208 +     */
 209.209 +    public IdentityHashMap() {
 209.210 +        init(DEFAULT_CAPACITY);
 209.211 +    }
 209.212 +
 209.213 +    /**
 209.214 +     * Constructs a new, empty map with the specified expected maximum size.
 209.215 +     * Putting more than the expected number of key-value mappings into
 209.216 +     * the map may cause the internal data structure to grow, which may be
 209.217 +     * somewhat time-consuming.
 209.218 +     *
 209.219 +     * @param expectedMaxSize the expected maximum size of the map
 209.220 +     * @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
 209.221 +     */
 209.222 +    public IdentityHashMap(int expectedMaxSize) {
 209.223 +        if (expectedMaxSize < 0)
 209.224 +            throw new IllegalArgumentException("expectedMaxSize is negative: "
 209.225 +                                               + expectedMaxSize);
 209.226 +        init(capacity(expectedMaxSize));
 209.227 +    }
 209.228 +
 209.229 +    /**
 209.230 +     * Returns the appropriate capacity for the specified expected maximum
 209.231 +     * size.  Returns the smallest power of two between MINIMUM_CAPACITY
 209.232 +     * and MAXIMUM_CAPACITY, inclusive, that is greater than
 209.233 +     * (3 * expectedMaxSize)/2, if such a number exists.  Otherwise
 209.234 +     * returns MAXIMUM_CAPACITY.  If (3 * expectedMaxSize)/2 is negative, it
 209.235 +     * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
 209.236 +     */
 209.237 +    private int capacity(int expectedMaxSize) {
 209.238 +        // Compute min capacity for expectedMaxSize given a load factor of 2/3
 209.239 +        int minCapacity = (3 * expectedMaxSize)/2;
 209.240 +
 209.241 +        // Compute the appropriate capacity
 209.242 +        int result;
 209.243 +        if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
 209.244 +            result = MAXIMUM_CAPACITY;
 209.245 +        } else {
 209.246 +            result = MINIMUM_CAPACITY;
 209.247 +            while (result < minCapacity)
 209.248 +                result <<= 1;
 209.249 +        }
 209.250 +        return result;
 209.251 +    }
 209.252 +
 209.253 +    /**
 209.254 +     * Initializes object to be an empty map with the specified initial
 209.255 +     * capacity, which is assumed to be a power of two between
 209.256 +     * MINIMUM_CAPACITY and MAXIMUM_CAPACITY inclusive.
 209.257 +     */
 209.258 +    private void init(int initCapacity) {
 209.259 +        // assert (initCapacity & -initCapacity) == initCapacity; // power of 2
 209.260 +        // assert initCapacity >= MINIMUM_CAPACITY;
 209.261 +        // assert initCapacity <= MAXIMUM_CAPACITY;
 209.262 +
 209.263 +        threshold = (initCapacity * 2)/3;
 209.264 +        table = new Object[2 * initCapacity];
 209.265 +    }
 209.266 +
 209.267 +    /**
 209.268 +     * Constructs a new identity hash map containing the keys-value mappings
 209.269 +     * in the specified map.
 209.270 +     *
 209.271 +     * @param m the map whose mappings are to be placed into this map
 209.272 +     * @throws NullPointerException if the specified map is null
 209.273 +     */
 209.274 +    public IdentityHashMap(Map<? extends K, ? extends V> m) {
 209.275 +        // Allow for a bit of growth
 209.276 +        this((int) ((1 + m.size()) * 1.1));
 209.277 +        putAll(m);
 209.278 +    }
 209.279 +
 209.280 +    /**
 209.281 +     * Returns the number of key-value mappings in this identity hash map.
 209.282 +     *
 209.283 +     * @return the number of key-value mappings in this map
 209.284 +     */
 209.285 +    public int size() {
 209.286 +        return size;
 209.287 +    }
 209.288 +
 209.289 +    /**
 209.290 +     * Returns <tt>true</tt> if this identity hash map contains no key-value
 209.291 +     * mappings.
 209.292 +     *
 209.293 +     * @return <tt>true</tt> if this identity hash map contains no key-value
 209.294 +     *         mappings
 209.295 +     */
 209.296 +    public boolean isEmpty() {
 209.297 +        return size == 0;
 209.298 +    }
 209.299 +
 209.300 +    /**
 209.301 +     * Returns index for Object x.
 209.302 +     */
 209.303 +    private static int hash(Object x, int length) {
 209.304 +        int h = System.identityHashCode(x);
 209.305 +        // Multiply by -127, and left-shift to use least bit as part of hash
 209.306 +        return ((h << 1) - (h << 8)) & (length - 1);
 209.307 +    }
 209.308 +
 209.309 +    /**
 209.310 +     * Circularly traverses table of size len.
 209.311 +     */
 209.312 +    private static int nextKeyIndex(int i, int len) {
 209.313 +        return (i + 2 < len ? i + 2 : 0);
 209.314 +    }
 209.315 +
 209.316 +    /**
 209.317 +     * Returns the value to which the specified key is mapped,
 209.318 +     * or {@code null} if this map contains no mapping for the key.
 209.319 +     *
 209.320 +     * <p>More formally, if this map contains a mapping from a key
 209.321 +     * {@code k} to a value {@code v} such that {@code (key == k)},
 209.322 +     * then this method returns {@code v}; otherwise it returns
 209.323 +     * {@code null}.  (There can be at most one such mapping.)
 209.324 +     *
 209.325 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 209.326 +     * indicate that the map contains no mapping for the key; it's also
 209.327 +     * possible that the map explicitly maps the key to {@code null}.
 209.328 +     * The {@link #containsKey containsKey} operation may be used to
 209.329 +     * distinguish these two cases.
 209.330 +     *
 209.331 +     * @see #put(Object, Object)
 209.332 +     */
 209.333 +    public V get(Object key) {
 209.334 +        Object k = maskNull(key);
 209.335 +        Object[] tab = table;
 209.336 +        int len = tab.length;
 209.337 +        int i = hash(k, len);
 209.338 +        while (true) {
 209.339 +            Object item = tab[i];
 209.340 +            if (item == k)
 209.341 +                return (V) tab[i + 1];
 209.342 +            if (item == null)
 209.343 +                return null;
 209.344 +            i = nextKeyIndex(i, len);
 209.345 +        }
 209.346 +    }
 209.347 +
 209.348 +    /**
 209.349 +     * Tests whether the specified object reference is a key in this identity
 209.350 +     * hash map.
 209.351 +     *
 209.352 +     * @param   key   possible key
 209.353 +     * @return  <code>true</code> if the specified object reference is a key
 209.354 +     *          in this map
 209.355 +     * @see     #containsValue(Object)
 209.356 +     */
 209.357 +    public boolean containsKey(Object key) {
 209.358 +        Object k = maskNull(key);
 209.359 +        Object[] tab = table;
 209.360 +        int len = tab.length;
 209.361 +        int i = hash(k, len);
 209.362 +        while (true) {
 209.363 +            Object item = tab[i];
 209.364 +            if (item == k)
 209.365 +                return true;
 209.366 +            if (item == null)
 209.367 +                return false;
 209.368 +            i = nextKeyIndex(i, len);
 209.369 +        }
 209.370 +    }
 209.371 +
 209.372 +    /**
 209.373 +     * Tests whether the specified object reference is a value in this identity
 209.374 +     * hash map.
 209.375 +     *
 209.376 +     * @param value value whose presence in this map is to be tested
 209.377 +     * @return <tt>true</tt> if this map maps one or more keys to the
 209.378 +     *         specified object reference
 209.379 +     * @see     #containsKey(Object)
 209.380 +     */
 209.381 +    public boolean containsValue(Object value) {
 209.382 +        Object[] tab = table;
 209.383 +        for (int i = 1; i < tab.length; i += 2)
 209.384 +            if (tab[i] == value && tab[i - 1] != null)
 209.385 +                return true;
 209.386 +
 209.387 +        return false;
 209.388 +    }
 209.389 +
 209.390 +    /**
 209.391 +     * Tests if the specified key-value mapping is in the map.
 209.392 +     *
 209.393 +     * @param   key   possible key
 209.394 +     * @param   value possible value
 209.395 +     * @return  <code>true</code> if and only if the specified key-value
 209.396 +     *          mapping is in the map
 209.397 +     */
 209.398 +    private boolean containsMapping(Object key, Object value) {
 209.399 +        Object k = maskNull(key);
 209.400 +        Object[] tab = table;
 209.401 +        int len = tab.length;
 209.402 +        int i = hash(k, len);
 209.403 +        while (true) {
 209.404 +            Object item = tab[i];
 209.405 +            if (item == k)
 209.406 +                return tab[i + 1] == value;
 209.407 +            if (item == null)
 209.408 +                return false;
 209.409 +            i = nextKeyIndex(i, len);
 209.410 +        }
 209.411 +    }
 209.412 +
 209.413 +    /**
 209.414 +     * Associates the specified value with the specified key in this identity
 209.415 +     * hash map.  If the map previously contained a mapping for the key, the
 209.416 +     * old value is replaced.
 209.417 +     *
 209.418 +     * @param key the key with which the specified value is to be associated
 209.419 +     * @param value the value to be associated with the specified key
 209.420 +     * @return the previous value associated with <tt>key</tt>, or
 209.421 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 209.422 +     *         (A <tt>null</tt> return can also indicate that the map
 209.423 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 209.424 +     * @see     Object#equals(Object)
 209.425 +     * @see     #get(Object)
 209.426 +     * @see     #containsKey(Object)
 209.427 +     */
 209.428 +    public V put(K key, V value) {
 209.429 +        Object k = maskNull(key);
 209.430 +        Object[] tab = table;
 209.431 +        int len = tab.length;
 209.432 +        int i = hash(k, len);
 209.433 +
 209.434 +        Object item;
 209.435 +        while ( (item = tab[i]) != null) {
 209.436 +            if (item == k) {
 209.437 +                V oldValue = (V) tab[i + 1];
 209.438 +                tab[i + 1] = value;
 209.439 +                return oldValue;
 209.440 +            }
 209.441 +            i = nextKeyIndex(i, len);
 209.442 +        }
 209.443 +
 209.444 +        modCount++;
 209.445 +        tab[i] = k;
 209.446 +        tab[i + 1] = value;
 209.447 +        if (++size >= threshold)
 209.448 +            resize(len); // len == 2 * current capacity.
 209.449 +        return null;
 209.450 +    }
 209.451 +
 209.452 +    /**
 209.453 +     * Resize the table to hold given capacity.
 209.454 +     *
 209.455 +     * @param newCapacity the new capacity, must be a power of two.
 209.456 +     */
 209.457 +    private void resize(int newCapacity) {
 209.458 +        // assert (newCapacity & -newCapacity) == newCapacity; // power of 2
 209.459 +        int newLength = newCapacity * 2;
 209.460 +
 209.461 +        Object[] oldTable = table;
 209.462 +        int oldLength = oldTable.length;
 209.463 +        if (oldLength == 2*MAXIMUM_CAPACITY) { // can't expand any further
 209.464 +            if (threshold == MAXIMUM_CAPACITY-1)
 209.465 +                throw new IllegalStateException("Capacity exhausted.");
 209.466 +            threshold = MAXIMUM_CAPACITY-1;  // Gigantic map!
 209.467 +            return;
 209.468 +        }
 209.469 +        if (oldLength >= newLength)
 209.470 +            return;
 209.471 +
 209.472 +        Object[] newTable = new Object[newLength];
 209.473 +        threshold = newLength / 3;
 209.474 +
 209.475 +        for (int j = 0; j < oldLength; j += 2) {
 209.476 +            Object key = oldTable[j];
 209.477 +            if (key != null) {
 209.478 +                Object value = oldTable[j+1];
 209.479 +                oldTable[j] = null;
 209.480 +                oldTable[j+1] = null;
 209.481 +                int i = hash(key, newLength);
 209.482 +                while (newTable[i] != null)
 209.483 +                    i = nextKeyIndex(i, newLength);
 209.484 +                newTable[i] = key;
 209.485 +                newTable[i + 1] = value;
 209.486 +            }
 209.487 +        }
 209.488 +        table = newTable;
 209.489 +    }
 209.490 +
 209.491 +    /**
 209.492 +     * Copies all of the mappings from the specified map to this map.
 209.493 +     * These mappings will replace any mappings that this map had for
 209.494 +     * any of the keys currently in the specified map.
 209.495 +     *
 209.496 +     * @param m mappings to be stored in this map
 209.497 +     * @throws NullPointerException if the specified map is null
 209.498 +     */
 209.499 +    public void putAll(Map<? extends K, ? extends V> m) {
 209.500 +        int n = m.size();
 209.501 +        if (n == 0)
 209.502 +            return;
 209.503 +        if (n > threshold) // conservatively pre-expand
 209.504 +            resize(capacity(n));
 209.505 +
 209.506 +        for (Entry<? extends K, ? extends V> e : m.entrySet())
 209.507 +            put(e.getKey(), e.getValue());
 209.508 +    }
 209.509 +
 209.510 +    /**
 209.511 +     * Removes the mapping for this key from this map if present.
 209.512 +     *
 209.513 +     * @param key key whose mapping is to be removed from the map
 209.514 +     * @return the previous value associated with <tt>key</tt>, or
 209.515 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 209.516 +     *         (A <tt>null</tt> return can also indicate that the map
 209.517 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 209.518 +     */
 209.519 +    public V remove(Object key) {
 209.520 +        Object k = maskNull(key);
 209.521 +        Object[] tab = table;
 209.522 +        int len = tab.length;
 209.523 +        int i = hash(k, len);
 209.524 +
 209.525 +        while (true) {
 209.526 +            Object item = tab[i];
 209.527 +            if (item == k) {
 209.528 +                modCount++;
 209.529 +                size--;
 209.530 +                V oldValue = (V) tab[i + 1];
 209.531 +                tab[i + 1] = null;
 209.532 +                tab[i] = null;
 209.533 +                closeDeletion(i);
 209.534 +                return oldValue;
 209.535 +            }
 209.536 +            if (item == null)
 209.537 +                return null;
 209.538 +            i = nextKeyIndex(i, len);
 209.539 +        }
 209.540 +
 209.541 +    }
 209.542 +
 209.543 +    /**
 209.544 +     * Removes the specified key-value mapping from the map if it is present.
 209.545 +     *
 209.546 +     * @param   key   possible key
 209.547 +     * @param   value possible value
 209.548 +     * @return  <code>true</code> if and only if the specified key-value
 209.549 +     *          mapping was in the map
 209.550 +     */
 209.551 +    private boolean removeMapping(Object key, Object value) {
 209.552 +        Object k = maskNull(key);
 209.553 +        Object[] tab = table;
 209.554 +        int len = tab.length;
 209.555 +        int i = hash(k, len);
 209.556 +
 209.557 +        while (true) {
 209.558 +            Object item = tab[i];
 209.559 +            if (item == k) {
 209.560 +                if (tab[i + 1] != value)
 209.561 +                    return false;
 209.562 +                modCount++;
 209.563 +                size--;
 209.564 +                tab[i] = null;
 209.565 +                tab[i + 1] = null;
 209.566 +                closeDeletion(i);
 209.567 +                return true;
 209.568 +            }
 209.569 +            if (item == null)
 209.570 +                return false;
 209.571 +            i = nextKeyIndex(i, len);
 209.572 +        }
 209.573 +    }
 209.574 +
 209.575 +    /**
 209.576 +     * Rehash all possibly-colliding entries following a
 209.577 +     * deletion. This preserves the linear-probe
 209.578 +     * collision properties required by get, put, etc.
 209.579 +     *
 209.580 +     * @param d the index of a newly empty deleted slot
 209.581 +     */
 209.582 +    private void closeDeletion(int d) {
 209.583 +        // Adapted from Knuth Section 6.4 Algorithm R
 209.584 +        Object[] tab = table;
 209.585 +        int len = tab.length;
 209.586 +
 209.587 +        // Look for items to swap into newly vacated slot
 209.588 +        // starting at index immediately following deletion,
 209.589 +        // and continuing until a null slot is seen, indicating
 209.590 +        // the end of a run of possibly-colliding keys.
 209.591 +        Object item;
 209.592 +        for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
 209.593 +             i = nextKeyIndex(i, len) ) {
 209.594 +            // The following test triggers if the item at slot i (which
 209.595 +            // hashes to be at slot r) should take the spot vacated by d.
 209.596 +            // If so, we swap it in, and then continue with d now at the
 209.597 +            // newly vacated i.  This process will terminate when we hit
 209.598 +            // the null slot at the end of this run.
 209.599 +            // The test is messy because we are using a circular table.
 209.600 +            int r = hash(item, len);
 209.601 +            if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) {
 209.602 +                tab[d] = item;
 209.603 +                tab[d + 1] = tab[i + 1];
 209.604 +                tab[i] = null;
 209.605 +                tab[i + 1] = null;
 209.606 +                d = i;
 209.607 +            }
 209.608 +        }
 209.609 +    }
 209.610 +
 209.611 +    /**
 209.612 +     * Removes all of the mappings from this map.
 209.613 +     * The map will be empty after this call returns.
 209.614 +     */
 209.615 +    public void clear() {
 209.616 +        modCount++;
 209.617 +        Object[] tab = table;
 209.618 +        for (int i = 0; i < tab.length; i++)
 209.619 +            tab[i] = null;
 209.620 +        size = 0;
 209.621 +    }
 209.622 +
 209.623 +    /**
 209.624 +     * Compares the specified object with this map for equality.  Returns
 209.625 +     * <tt>true</tt> if the given object is also a map and the two maps
 209.626 +     * represent identical object-reference mappings.  More formally, this
 209.627 +     * map is equal to another map <tt>m</tt> if and only if
 209.628 +     * <tt>this.entrySet().equals(m.entrySet())</tt>.
 209.629 +     *
 209.630 +     * <p><b>Owing to the reference-equality-based semantics of this map it is
 209.631 +     * possible that the symmetry and transitivity requirements of the
 209.632 +     * <tt>Object.equals</tt> contract may be violated if this map is compared
 209.633 +     * to a normal map.  However, the <tt>Object.equals</tt> contract is
 209.634 +     * guaranteed to hold among <tt>IdentityHashMap</tt> instances.</b>
 209.635 +     *
 209.636 +     * @param  o object to be compared for equality with this map
 209.637 +     * @return <tt>true</tt> if the specified object is equal to this map
 209.638 +     * @see Object#equals(Object)
 209.639 +     */
 209.640 +    public boolean equals(Object o) {
 209.641 +        if (o == this) {
 209.642 +            return true;
 209.643 +        } else if (o instanceof IdentityHashMap) {
 209.644 +            IdentityHashMap m = (IdentityHashMap) o;
 209.645 +            if (m.size() != size)
 209.646 +                return false;
 209.647 +
 209.648 +            Object[] tab = m.table;
 209.649 +            for (int i = 0; i < tab.length; i+=2) {
 209.650 +                Object k = tab[i];
 209.651 +                if (k != null && !containsMapping(k, tab[i + 1]))
 209.652 +                    return false;
 209.653 +            }
 209.654 +            return true;
 209.655 +        } else if (o instanceof Map) {
 209.656 +            Map m = (Map)o;
 209.657 +            return entrySet().equals(m.entrySet());
 209.658 +        } else {
 209.659 +            return false;  // o is not a Map
 209.660 +        }
 209.661 +    }
 209.662 +
 209.663 +    /**
 209.664 +     * Returns the hash code value for this map.  The hash code of a map is
 209.665 +     * defined to be the sum of the hash codes of each entry in the map's
 209.666 +     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
 209.667 +     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two
 209.668 +     * <tt>IdentityHashMap</tt> instances <tt>m1</tt> and <tt>m2</tt>, as
 209.669 +     * required by the general contract of {@link Object#hashCode}.
 209.670 +     *
 209.671 +     * <p><b>Owing to the reference-equality-based semantics of the
 209.672 +     * <tt>Map.Entry</tt> instances in the set returned by this map's
 209.673 +     * <tt>entrySet</tt> method, it is possible that the contractual
 209.674 +     * requirement of <tt>Object.hashCode</tt> mentioned in the previous
 209.675 +     * paragraph will be violated if one of the two objects being compared is
 209.676 +     * an <tt>IdentityHashMap</tt> instance and the other is a normal map.</b>
 209.677 +     *
 209.678 +     * @return the hash code value for this map
 209.679 +     * @see Object#equals(Object)
 209.680 +     * @see #equals(Object)
 209.681 +     */
 209.682 +    public int hashCode() {
 209.683 +        int result = 0;
 209.684 +        Object[] tab = table;
 209.685 +        for (int i = 0; i < tab.length; i +=2) {
 209.686 +            Object key = tab[i];
 209.687 +            if (key != null) {
 209.688 +                Object k = unmaskNull(key);
 209.689 +                result += System.identityHashCode(k) ^
 209.690 +                          System.identityHashCode(tab[i + 1]);
 209.691 +            }
 209.692 +        }
 209.693 +        return result;
 209.694 +    }
 209.695 +
 209.696 +    /**
 209.697 +     * Returns a shallow copy of this identity hash map: the keys and values
 209.698 +     * themselves are not cloned.
 209.699 +     *
 209.700 +     * @return a shallow copy of this map
 209.701 +     */
 209.702 +    public Object clone() {
 209.703 +        try {
 209.704 +            IdentityHashMap<K,V> m = (IdentityHashMap<K,V>) super.clone();
 209.705 +            m.entrySet = null;
 209.706 +            m.table = table.clone();
 209.707 +            return m;
 209.708 +        } catch (CloneNotSupportedException e) {
 209.709 +            throw new InternalError();
 209.710 +        }
 209.711 +    }
 209.712 +
 209.713 +    private abstract class IdentityHashMapIterator<T> implements Iterator<T> {
 209.714 +        int index = (size != 0 ? 0 : table.length); // current slot.
 209.715 +        int expectedModCount = modCount; // to support fast-fail
 209.716 +        int lastReturnedIndex = -1;      // to allow remove()
 209.717 +        boolean indexValid; // To avoid unnecessary next computation
 209.718 +        Object[] traversalTable = table; // reference to main table or copy
 209.719 +
 209.720 +        public boolean hasNext() {
 209.721 +            Object[] tab = traversalTable;
 209.722 +            for (int i = index; i < tab.length; i+=2) {
 209.723 +                Object key = tab[i];
 209.724 +                if (key != null) {
 209.725 +                    index = i;
 209.726 +                    return indexValid = true;
 209.727 +                }
 209.728 +            }
 209.729 +            index = tab.length;
 209.730 +            return false;
 209.731 +        }
 209.732 +
 209.733 +        protected int nextIndex() {
 209.734 +            if (modCount != expectedModCount)
 209.735 +                throw new ConcurrentModificationException();
 209.736 +            if (!indexValid && !hasNext())
 209.737 +                throw new NoSuchElementException();
 209.738 +
 209.739 +            indexValid = false;
 209.740 +            lastReturnedIndex = index;
 209.741 +            index += 2;
 209.742 +            return lastReturnedIndex;
 209.743 +        }
 209.744 +
 209.745 +        public void remove() {
 209.746 +            if (lastReturnedIndex == -1)
 209.747 +                throw new IllegalStateException();
 209.748 +            if (modCount != expectedModCount)
 209.749 +                throw new ConcurrentModificationException();
 209.750 +
 209.751 +            expectedModCount = ++modCount;
 209.752 +            int deletedSlot = lastReturnedIndex;
 209.753 +            lastReturnedIndex = -1;
 209.754 +            // back up index to revisit new contents after deletion
 209.755 +            index = deletedSlot;
 209.756 +            indexValid = false;
 209.757 +
 209.758 +            // Removal code proceeds as in closeDeletion except that
 209.759 +            // it must catch the rare case where an element already
 209.760 +            // seen is swapped into a vacant slot that will be later
 209.761 +            // traversed by this iterator. We cannot allow future
 209.762 +            // next() calls to return it again.  The likelihood of
 209.763 +            // this occurring under 2/3 load factor is very slim, but
 209.764 +            // when it does happen, we must make a copy of the rest of
 209.765 +            // the table to use for the rest of the traversal. Since
 209.766 +            // this can only happen when we are near the end of the table,
 209.767 +            // even in these rare cases, this is not very expensive in
 209.768 +            // time or space.
 209.769 +
 209.770 +            Object[] tab = traversalTable;
 209.771 +            int len = tab.length;
 209.772 +
 209.773 +            int d = deletedSlot;
 209.774 +            K key = (K) tab[d];
 209.775 +            tab[d] = null;        // vacate the slot
 209.776 +            tab[d + 1] = null;
 209.777 +
 209.778 +            // If traversing a copy, remove in real table.
 209.779 +            // We can skip gap-closure on copy.
 209.780 +            if (tab != IdentityHashMap.this.table) {
 209.781 +                IdentityHashMap.this.remove(key);
 209.782 +                expectedModCount = modCount;
 209.783 +                return;
 209.784 +            }
 209.785 +
 209.786 +            size--;
 209.787 +
 209.788 +            Object item;
 209.789 +            for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
 209.790 +                 i = nextKeyIndex(i, len)) {
 209.791 +                int r = hash(item, len);
 209.792 +                // See closeDeletion for explanation of this conditional
 209.793 +                if ((i < r && (r <= d || d <= i)) ||
 209.794 +                    (r <= d && d <= i)) {
 209.795 +
 209.796 +                    // If we are about to swap an already-seen element
 209.797 +                    // into a slot that may later be returned by next(),
 209.798 +                    // then clone the rest of table for use in future
 209.799 +                    // next() calls. It is OK that our copy will have
 209.800 +                    // a gap in the "wrong" place, since it will never
 209.801 +                    // be used for searching anyway.
 209.802 +
 209.803 +                    if (i < deletedSlot && d >= deletedSlot &&
 209.804 +                        traversalTable == IdentityHashMap.this.table) {
 209.805 +                        int remaining = len - deletedSlot;
 209.806 +                        Object[] newTable = new Object[remaining];
 209.807 +                        System.arraycopy(tab, deletedSlot,
 209.808 +                                         newTable, 0, remaining);
 209.809 +                        traversalTable = newTable;
 209.810 +                        index = 0;
 209.811 +                    }
 209.812 +
 209.813 +                    tab[d] = item;
 209.814 +                    tab[d + 1] = tab[i + 1];
 209.815 +                    tab[i] = null;
 209.816 +                    tab[i + 1] = null;
 209.817 +                    d = i;
 209.818 +                }
 209.819 +            }
 209.820 +        }
 209.821 +    }
 209.822 +
 209.823 +    private class KeyIterator extends IdentityHashMapIterator<K> {
 209.824 +        public K next() {
 209.825 +            return (K) unmaskNull(traversalTable[nextIndex()]);
 209.826 +        }
 209.827 +    }
 209.828 +
 209.829 +    private class ValueIterator extends IdentityHashMapIterator<V> {
 209.830 +        public V next() {
 209.831 +            return (V) traversalTable[nextIndex() + 1];
 209.832 +        }
 209.833 +    }
 209.834 +
 209.835 +    private class EntryIterator
 209.836 +        extends IdentityHashMapIterator<Map.Entry<K,V>>
 209.837 +    {
 209.838 +        private Entry lastReturnedEntry = null;
 209.839 +
 209.840 +        public Map.Entry<K,V> next() {
 209.841 +            lastReturnedEntry = new Entry(nextIndex());
 209.842 +            return lastReturnedEntry;
 209.843 +        }
 209.844 +
 209.845 +        public void remove() {
 209.846 +            lastReturnedIndex =
 209.847 +                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
 209.848 +            super.remove();
 209.849 +            lastReturnedEntry.index = lastReturnedIndex;
 209.850 +            lastReturnedEntry = null;
 209.851 +        }
 209.852 +
 209.853 +        private class Entry implements Map.Entry<K,V> {
 209.854 +            private int index;
 209.855 +
 209.856 +            private Entry(int index) {
 209.857 +                this.index = index;
 209.858 +            }
 209.859 +
 209.860 +            public K getKey() {
 209.861 +                checkIndexForEntryUse();
 209.862 +                return (K) unmaskNull(traversalTable[index]);
 209.863 +            }
 209.864 +
 209.865 +            public V getValue() {
 209.866 +                checkIndexForEntryUse();
 209.867 +                return (V) traversalTable[index+1];
 209.868 +            }
 209.869 +
 209.870 +            public V setValue(V value) {
 209.871 +                checkIndexForEntryUse();
 209.872 +                V oldValue = (V) traversalTable[index+1];
 209.873 +                traversalTable[index+1] = value;
 209.874 +                // if shadowing, force into main table
 209.875 +                if (traversalTable != IdentityHashMap.this.table)
 209.876 +                    put((K) traversalTable[index], value);
 209.877 +                return oldValue;
 209.878 +            }
 209.879 +
 209.880 +            public boolean equals(Object o) {
 209.881 +                if (index < 0)
 209.882 +                    return super.equals(o);
 209.883 +
 209.884 +                if (!(o instanceof Map.Entry))
 209.885 +                    return false;
 209.886 +                Map.Entry e = (Map.Entry)o;
 209.887 +                return (e.getKey() == unmaskNull(traversalTable[index]) &&
 209.888 +                       e.getValue() == traversalTable[index+1]);
 209.889 +            }
 209.890 +
 209.891 +            public int hashCode() {
 209.892 +                if (lastReturnedIndex < 0)
 209.893 +                    return super.hashCode();
 209.894 +
 209.895 +                return (System.identityHashCode(unmaskNull(traversalTable[index])) ^
 209.896 +                       System.identityHashCode(traversalTable[index+1]));
 209.897 +            }
 209.898 +
 209.899 +            public String toString() {
 209.900 +                if (index < 0)
 209.901 +                    return super.toString();
 209.902 +
 209.903 +                return (unmaskNull(traversalTable[index]) + "="
 209.904 +                        + traversalTable[index+1]);
 209.905 +            }
 209.906 +
 209.907 +            private void checkIndexForEntryUse() {
 209.908 +                if (index < 0)
 209.909 +                    throw new IllegalStateException("Entry was removed");
 209.910 +            }
 209.911 +        }
 209.912 +    }
 209.913 +
 209.914 +    // Views
 209.915 +
 209.916 +    /**
 209.917 +     * This field is initialized to contain an instance of the entry set
 209.918 +     * view the first time this view is requested.  The view is stateless,
 209.919 +     * so there's no reason to create more than one.
 209.920 +     */
 209.921 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 209.922 +
 209.923 +    /**
 209.924 +     * Returns an identity-based set view of the keys contained in this map.
 209.925 +     * The set is backed by the map, so changes to the map are reflected in
 209.926 +     * the set, and vice-versa.  If the map is modified while an iteration
 209.927 +     * over the set is in progress, the results of the iteration are
 209.928 +     * undefined.  The set supports element removal, which removes the
 209.929 +     * corresponding mapping from the map, via the <tt>Iterator.remove</tt>,
 209.930 +     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
 209.931 +     * <tt>clear</tt> methods.  It does not support the <tt>add</tt> or
 209.932 +     * <tt>addAll</tt> methods.
 209.933 +     *
 209.934 +     * <p><b>While the object returned by this method implements the
 209.935 +     * <tt>Set</tt> interface, it does <i>not</i> obey <tt>Set's</tt> general
 209.936 +     * contract.  Like its backing map, the set returned by this method
 209.937 +     * defines element equality as reference-equality rather than
 209.938 +     * object-equality.  This affects the behavior of its <tt>contains</tt>,
 209.939 +     * <tt>remove</tt>, <tt>containsAll</tt>, <tt>equals</tt>, and
 209.940 +     * <tt>hashCode</tt> methods.</b>
 209.941 +     *
 209.942 +     * <p><b>The <tt>equals</tt> method of the returned set returns <tt>true</tt>
 209.943 +     * only if the specified object is a set containing exactly the same
 209.944 +     * object references as the returned set.  The symmetry and transitivity
 209.945 +     * requirements of the <tt>Object.equals</tt> contract may be violated if
 209.946 +     * the set returned by this method is compared to a normal set.  However,
 209.947 +     * the <tt>Object.equals</tt> contract is guaranteed to hold among sets
 209.948 +     * returned by this method.</b>
 209.949 +     *
 209.950 +     * <p>The <tt>hashCode</tt> method of the returned set returns the sum of
 209.951 +     * the <i>identity hashcodes</i> of the elements in the set, rather than
 209.952 +     * the sum of their hashcodes.  This is mandated by the change in the
 209.953 +     * semantics of the <tt>equals</tt> method, in order to enforce the
 209.954 +     * general contract of the <tt>Object.hashCode</tt> method among sets
 209.955 +     * returned by this method.
 209.956 +     *
 209.957 +     * @return an identity-based set view of the keys contained in this map
 209.958 +     * @see Object#equals(Object)
 209.959 +     * @see System#identityHashCode(Object)
 209.960 +     */
 209.961 +    public Set<K> keySet() {
 209.962 +        Set<K> ks = keySet;
 209.963 +        if (ks != null)
 209.964 +            return ks;
 209.965 +        else
 209.966 +            return keySet = new KeySet();
 209.967 +    }
 209.968 +
 209.969 +    private class KeySet extends AbstractSet<K> {
 209.970 +        public Iterator<K> iterator() {
 209.971 +            return new KeyIterator();
 209.972 +        }
 209.973 +        public int size() {
 209.974 +            return size;
 209.975 +        }
 209.976 +        public boolean contains(Object o) {
 209.977 +            return containsKey(o);
 209.978 +        }
 209.979 +        public boolean remove(Object o) {
 209.980 +            int oldSize = size;
 209.981 +            IdentityHashMap.this.remove(o);
 209.982 +            return size != oldSize;
 209.983 +        }
 209.984 +        /*
 209.985 +         * Must revert from AbstractSet's impl to AbstractCollection's, as
 209.986 +         * the former contains an optimization that results in incorrect
 209.987 +         * behavior when c is a smaller "normal" (non-identity-based) Set.
 209.988 +         */
 209.989 +        public boolean removeAll(Collection<?> c) {
 209.990 +            boolean modified = false;
 209.991 +            for (Iterator<K> i = iterator(); i.hasNext(); ) {
 209.992 +                if (c.contains(i.next())) {
 209.993 +                    i.remove();
 209.994 +                    modified = true;
 209.995 +                }
 209.996 +            }
 209.997 +            return modified;
 209.998 +        }
 209.999 +        public void clear() {
209.1000 +            IdentityHashMap.this.clear();
209.1001 +        }
209.1002 +        public int hashCode() {
209.1003 +            int result = 0;
209.1004 +            for (K key : this)
209.1005 +                result += System.identityHashCode(key);
209.1006 +            return result;
209.1007 +        }
209.1008 +    }
209.1009 +
209.1010 +    /**
209.1011 +     * Returns a {@link Collection} view of the values contained in this map.
209.1012 +     * The collection is backed by the map, so changes to the map are
209.1013 +     * reflected in the collection, and vice-versa.  If the map is
209.1014 +     * modified while an iteration over the collection is in progress,
209.1015 +     * the results of the iteration are undefined.  The collection
209.1016 +     * supports element removal, which removes the corresponding
209.1017 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
209.1018 +     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
209.1019 +     * <tt>retainAll</tt> and <tt>clear</tt> methods.  It does not
209.1020 +     * support the <tt>add</tt> or <tt>addAll</tt> methods.
209.1021 +     *
209.1022 +     * <p><b>While the object returned by this method implements the
209.1023 +     * <tt>Collection</tt> interface, it does <i>not</i> obey
209.1024 +     * <tt>Collection's</tt> general contract.  Like its backing map,
209.1025 +     * the collection returned by this method defines element equality as
209.1026 +     * reference-equality rather than object-equality.  This affects the
209.1027 +     * behavior of its <tt>contains</tt>, <tt>remove</tt> and
209.1028 +     * <tt>containsAll</tt> methods.</b>
209.1029 +     */
209.1030 +    public Collection<V> values() {
209.1031 +        Collection<V> vs = values;
209.1032 +        if (vs != null)
209.1033 +            return vs;
209.1034 +        else
209.1035 +            return values = new Values();
209.1036 +    }
209.1037 +
209.1038 +    private class Values extends AbstractCollection<V> {
209.1039 +        public Iterator<V> iterator() {
209.1040 +            return new ValueIterator();
209.1041 +        }
209.1042 +        public int size() {
209.1043 +            return size;
209.1044 +        }
209.1045 +        public boolean contains(Object o) {
209.1046 +            return containsValue(o);
209.1047 +        }
209.1048 +        public boolean remove(Object o) {
209.1049 +            for (Iterator<V> i = iterator(); i.hasNext(); ) {
209.1050 +                if (i.next() == o) {
209.1051 +                    i.remove();
209.1052 +                    return true;
209.1053 +                }
209.1054 +            }
209.1055 +            return false;
209.1056 +        }
209.1057 +        public void clear() {
209.1058 +            IdentityHashMap.this.clear();
209.1059 +        }
209.1060 +    }
209.1061 +
209.1062 +    /**
209.1063 +     * Returns a {@link Set} view of the mappings contained in this map.
209.1064 +     * Each element in the returned set is a reference-equality-based
209.1065 +     * <tt>Map.Entry</tt>.  The set is backed by the map, so changes
209.1066 +     * to the map are reflected in the set, and vice-versa.  If the
209.1067 +     * map is modified while an iteration over the set is in progress,
209.1068 +     * the results of the iteration are undefined.  The set supports
209.1069 +     * element removal, which removes the corresponding mapping from
209.1070 +     * the map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
209.1071 +     * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
209.1072 +     * methods.  It does not support the <tt>add</tt> or
209.1073 +     * <tt>addAll</tt> methods.
209.1074 +     *
209.1075 +     * <p>Like the backing map, the <tt>Map.Entry</tt> objects in the set
209.1076 +     * returned by this method define key and value equality as
209.1077 +     * reference-equality rather than object-equality.  This affects the
209.1078 +     * behavior of the <tt>equals</tt> and <tt>hashCode</tt> methods of these
209.1079 +     * <tt>Map.Entry</tt> objects.  A reference-equality based <tt>Map.Entry
209.1080 +     * e</tt> is equal to an object <tt>o</tt> if and only if <tt>o</tt> is a
209.1081 +     * <tt>Map.Entry</tt> and <tt>e.getKey()==o.getKey() &amp;&amp;
209.1082 +     * e.getValue()==o.getValue()</tt>.  To accommodate these equals
209.1083 +     * semantics, the <tt>hashCode</tt> method returns
209.1084 +     * <tt>System.identityHashCode(e.getKey()) ^
209.1085 +     * System.identityHashCode(e.getValue())</tt>.
209.1086 +     *
209.1087 +     * <p><b>Owing to the reference-equality-based semantics of the
209.1088 +     * <tt>Map.Entry</tt> instances in the set returned by this method,
209.1089 +     * it is possible that the symmetry and transitivity requirements of
209.1090 +     * the {@link Object#equals(Object)} contract may be violated if any of
209.1091 +     * the entries in the set is compared to a normal map entry, or if
209.1092 +     * the set returned by this method is compared to a set of normal map
209.1093 +     * entries (such as would be returned by a call to this method on a normal
209.1094 +     * map).  However, the <tt>Object.equals</tt> contract is guaranteed to
209.1095 +     * hold among identity-based map entries, and among sets of such entries.
209.1096 +     * </b>
209.1097 +     *
209.1098 +     * @return a set view of the identity-mappings contained in this map
209.1099 +     */
209.1100 +    public Set<Map.Entry<K,V>> entrySet() {
209.1101 +        Set<Map.Entry<K,V>> es = entrySet;
209.1102 +        if (es != null)
209.1103 +            return es;
209.1104 +        else
209.1105 +            return entrySet = new EntrySet();
209.1106 +    }
209.1107 +
209.1108 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
209.1109 +        public Iterator<Map.Entry<K,V>> iterator() {
209.1110 +            return new EntryIterator();
209.1111 +        }
209.1112 +        public boolean contains(Object o) {
209.1113 +            if (!(o instanceof Map.Entry))
209.1114 +                return false;
209.1115 +            Map.Entry entry = (Map.Entry)o;
209.1116 +            return containsMapping(entry.getKey(), entry.getValue());
209.1117 +        }
209.1118 +        public boolean remove(Object o) {
209.1119 +            if (!(o instanceof Map.Entry))
209.1120 +                return false;
209.1121 +            Map.Entry entry = (Map.Entry)o;
209.1122 +            return removeMapping(entry.getKey(), entry.getValue());
209.1123 +        }
209.1124 +        public int size() {
209.1125 +            return size;
209.1126 +        }
209.1127 +        public void clear() {
209.1128 +            IdentityHashMap.this.clear();
209.1129 +        }
209.1130 +        /*
209.1131 +         * Must revert from AbstractSet's impl to AbstractCollection's, as
209.1132 +         * the former contains an optimization that results in incorrect
209.1133 +         * behavior when c is a smaller "normal" (non-identity-based) Set.
209.1134 +         */
209.1135 +        public boolean removeAll(Collection<?> c) {
209.1136 +            boolean modified = false;
209.1137 +            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
209.1138 +                if (c.contains(i.next())) {
209.1139 +                    i.remove();
209.1140 +                    modified = true;
209.1141 +                }
209.1142 +            }
209.1143 +            return modified;
209.1144 +        }
209.1145 +
209.1146 +        public Object[] toArray() {
209.1147 +            int size = size();
209.1148 +            Object[] result = new Object[size];
209.1149 +            Iterator<Map.Entry<K,V>> it = iterator();
209.1150 +            for (int i = 0; i < size; i++)
209.1151 +                result[i] = new AbstractMap.SimpleEntry<>(it.next());
209.1152 +            return result;
209.1153 +        }
209.1154 +
209.1155 +        @SuppressWarnings("unchecked")
209.1156 +        public <T> T[] toArray(T[] a) {
209.1157 +            int size = size();
209.1158 +            if (a.length < size)
209.1159 +                a = (T[])java.lang.reflect.Array
209.1160 +                    .newInstance(a.getClass().getComponentType(), size);
209.1161 +            Iterator<Map.Entry<K,V>> it = iterator();
209.1162 +            for (int i = 0; i < size; i++)
209.1163 +                a[i] = (T) new AbstractMap.SimpleEntry<>(it.next());
209.1164 +            if (a.length > size)
209.1165 +                a[size] = null;
209.1166 +            return a;
209.1167 +        }
209.1168 +    }
209.1169 +
209.1170 +
209.1171 +    private static final long serialVersionUID = 8188218128353913216L;
209.1172 +
209.1173 +    /**
209.1174 +     * Save the state of the <tt>IdentityHashMap</tt> instance to a stream
209.1175 +     * (i.e., serialize it).
209.1176 +     *
209.1177 +     * @serialData The <i>size</i> of the HashMap (the number of key-value
209.1178 +     *          mappings) (<tt>int</tt>), followed by the key (Object) and
209.1179 +     *          value (Object) for each key-value mapping represented by the
209.1180 +     *          IdentityHashMap.  The key-value mappings are emitted in no
209.1181 +     *          particular order.
209.1182 +     */
209.1183 +    private void writeObject(java.io.ObjectOutputStream s)
209.1184 +        throws java.io.IOException  {
209.1185 +        // Write out and any hidden stuff
209.1186 +        s.defaultWriteObject();
209.1187 +
209.1188 +        // Write out size (number of Mappings)
209.1189 +        s.writeInt(size);
209.1190 +
209.1191 +        // Write out keys and values (alternating)
209.1192 +        Object[] tab = table;
209.1193 +        for (int i = 0; i < tab.length; i += 2) {
209.1194 +            Object key = tab[i];
209.1195 +            if (key != null) {
209.1196 +                s.writeObject(unmaskNull(key));
209.1197 +                s.writeObject(tab[i + 1]);
209.1198 +            }
209.1199 +        }
209.1200 +    }
209.1201 +
209.1202 +    /**
209.1203 +     * Reconstitute the <tt>IdentityHashMap</tt> instance from a stream (i.e.,
209.1204 +     * deserialize it).
209.1205 +     */
209.1206 +    private void readObject(java.io.ObjectInputStream s)
209.1207 +        throws java.io.IOException, ClassNotFoundException  {
209.1208 +        // Read in any hidden stuff
209.1209 +        s.defaultReadObject();
209.1210 +
209.1211 +        // Read in size (number of Mappings)
209.1212 +        int size = s.readInt();
209.1213 +
209.1214 +        // Allow for 33% growth (i.e., capacity is >= 2* size()).
209.1215 +        init(capacity((size*4)/3));
209.1216 +
209.1217 +        // Read the keys and values, and put the mappings in the table
209.1218 +        for (int i=0; i<size; i++) {
209.1219 +            K key = (K) s.readObject();
209.1220 +            V value = (V) s.readObject();
209.1221 +            putForCreate(key, value);
209.1222 +        }
209.1223 +    }
209.1224 +
209.1225 +    /**
209.1226 +     * The put method for readObject.  It does not resize the table,
209.1227 +     * update modCount, etc.
209.1228 +     */
209.1229 +    private void putForCreate(K key, V value)
209.1230 +        throws IOException
209.1231 +    {
209.1232 +        K k = (K)maskNull(key);
209.1233 +        Object[] tab = table;
209.1234 +        int len = tab.length;
209.1235 +        int i = hash(k, len);
209.1236 +
209.1237 +        Object item;
209.1238 +        while ( (item = tab[i]) != null) {
209.1239 +            if (item == k)
209.1240 +                throw new java.io.StreamCorruptedException();
209.1241 +            i = nextKeyIndex(i, len);
209.1242 +        }
209.1243 +        tab[i] = k;
209.1244 +        tab[i + 1] = value;
209.1245 +    }
209.1246 +}
   210.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   210.2 +++ b/rt/emul/compact/src/main/java/java/util/JumboEnumSet.java	Wed Apr 30 15:04:10 2014 +0200
   210.3 @@ -0,0 +1,375 @@
   210.4 +/*
   210.5 + * Copyright (c) 2003, 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.util;
  210.30 +
  210.31 +/**
  210.32 + * Private implementation class for EnumSet, for "jumbo" enum types
  210.33 + * (i.e., those with more than 64 elements).
  210.34 + *
  210.35 + * @author Josh Bloch
  210.36 + * @since 1.5
  210.37 + * @serial exclude
  210.38 + */
  210.39 +class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
  210.40 +    private static final long serialVersionUID = 334349849919042784L;
  210.41 +
  210.42 +    /**
  210.43 +     * Bit vector representation of this set.  The ith bit of the jth
  210.44 +     * element of this array represents the  presence of universe[64*j +i]
  210.45 +     * in this set.
  210.46 +     */
  210.47 +    private long elements[];
  210.48 +
  210.49 +    // Redundant - maintained for performance
  210.50 +    private int size = 0;
  210.51 +
  210.52 +    JumboEnumSet(Class<E>elementType, Enum[] universe) {
  210.53 +        super(elementType, universe);
  210.54 +        elements = new long[(universe.length + 63) >>> 6];
  210.55 +    }
  210.56 +
  210.57 +    void addRange(E from, E to) {
  210.58 +        int fromIndex = from.ordinal() >>> 6;
  210.59 +        int toIndex = to.ordinal() >>> 6;
  210.60 +
  210.61 +        if (fromIndex == toIndex) {
  210.62 +            elements[fromIndex] = (-1L >>>  (from.ordinal() - to.ordinal() - 1))
  210.63 +                            << from.ordinal();
  210.64 +        } else {
  210.65 +            elements[fromIndex] = (-1L << from.ordinal());
  210.66 +            for (int i = fromIndex + 1; i < toIndex; i++)
  210.67 +                elements[i] = -1;
  210.68 +            elements[toIndex] = -1L >>> (63 - to.ordinal());
  210.69 +        }
  210.70 +        size = to.ordinal() - from.ordinal() + 1;
  210.71 +    }
  210.72 +
  210.73 +    void addAll() {
  210.74 +        for (int i = 0; i < elements.length; i++)
  210.75 +            elements[i] = -1;
  210.76 +        elements[elements.length - 1] >>>= -universe.length;
  210.77 +        size = universe.length;
  210.78 +    }
  210.79 +
  210.80 +    void complement() {
  210.81 +        for (int i = 0; i < elements.length; i++)
  210.82 +            elements[i] = ~elements[i];
  210.83 +        elements[elements.length - 1] &= (-1L >>> -universe.length);
  210.84 +        size = universe.length - size;
  210.85 +    }
  210.86 +
  210.87 +    /**
  210.88 +     * Returns an iterator over the elements contained in this set.  The
  210.89 +     * iterator traverses the elements in their <i>natural order</i> (which is
  210.90 +     * the order in which the enum constants are declared). The returned
  210.91 +     * Iterator is a "weakly consistent" iterator that will never throw {@link
  210.92 +     * ConcurrentModificationException}.
  210.93 +     *
  210.94 +     * @return an iterator over the elements contained in this set
  210.95 +     */
  210.96 +    public Iterator<E> iterator() {
  210.97 +        return new EnumSetIterator<>();
  210.98 +    }
  210.99 +
 210.100 +    private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
 210.101 +        /**
 210.102 +         * A bit vector representing the elements in the current "word"
 210.103 +         * of the set not yet returned by this iterator.
 210.104 +         */
 210.105 +        long unseen;
 210.106 +
 210.107 +        /**
 210.108 +         * The index corresponding to unseen in the elements array.
 210.109 +         */
 210.110 +        int unseenIndex = 0;
 210.111 +
 210.112 +        /**
 210.113 +         * The bit representing the last element returned by this iterator
 210.114 +         * but not removed, or zero if no such element exists.
 210.115 +         */
 210.116 +        long lastReturned = 0;
 210.117 +
 210.118 +        /**
 210.119 +         * The index corresponding to lastReturned in the elements array.
 210.120 +         */
 210.121 +        int lastReturnedIndex = 0;
 210.122 +
 210.123 +        EnumSetIterator() {
 210.124 +            unseen = elements[0];
 210.125 +        }
 210.126 +
 210.127 +        public boolean hasNext() {
 210.128 +            while (unseen == 0 && unseenIndex < elements.length - 1)
 210.129 +                unseen = elements[++unseenIndex];
 210.130 +            return unseen != 0;
 210.131 +        }
 210.132 +
 210.133 +        public E next() {
 210.134 +            if (!hasNext())
 210.135 +                throw new NoSuchElementException();
 210.136 +            lastReturned = unseen & -unseen;
 210.137 +            lastReturnedIndex = unseenIndex;
 210.138 +            unseen -= lastReturned;
 210.139 +            return (E) universe[(lastReturnedIndex << 6)
 210.140 +                                + Long.numberOfTrailingZeros(lastReturned)];
 210.141 +        }
 210.142 +
 210.143 +        public void remove() {
 210.144 +            if (lastReturned == 0)
 210.145 +                throw new IllegalStateException();
 210.146 +            final long oldElements = elements[lastReturnedIndex];
 210.147 +            elements[lastReturnedIndex] &= ~lastReturned;
 210.148 +            if (oldElements != elements[lastReturnedIndex]) {
 210.149 +                size--;
 210.150 +            }
 210.151 +            lastReturned = 0;
 210.152 +        }
 210.153 +    }
 210.154 +
 210.155 +    /**
 210.156 +     * Returns the number of elements in this set.
 210.157 +     *
 210.158 +     * @return the number of elements in this set
 210.159 +     */
 210.160 +    public int size() {
 210.161 +        return size;
 210.162 +    }
 210.163 +
 210.164 +    /**
 210.165 +     * Returns <tt>true</tt> if this set contains no elements.
 210.166 +     *
 210.167 +     * @return <tt>true</tt> if this set contains no elements
 210.168 +     */
 210.169 +    public boolean isEmpty() {
 210.170 +        return size == 0;
 210.171 +    }
 210.172 +
 210.173 +    /**
 210.174 +     * Returns <tt>true</tt> if this set contains the specified element.
 210.175 +     *
 210.176 +     * @param e element to be checked for containment in this collection
 210.177 +     * @return <tt>true</tt> if this set contains the specified element
 210.178 +     */
 210.179 +    public boolean contains(Object e) {
 210.180 +        if (e == null)
 210.181 +            return false;
 210.182 +        Class eClass = e.getClass();
 210.183 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 210.184 +            return false;
 210.185 +
 210.186 +        int eOrdinal = ((Enum)e).ordinal();
 210.187 +        return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0;
 210.188 +    }
 210.189 +
 210.190 +    // Modification Operations
 210.191 +
 210.192 +    /**
 210.193 +     * Adds the specified element to this set if it is not already present.
 210.194 +     *
 210.195 +     * @param e element to be added to this set
 210.196 +     * @return <tt>true</tt> if the set changed as a result of the call
 210.197 +     *
 210.198 +     * @throws NullPointerException if <tt>e</tt> is null
 210.199 +     */
 210.200 +    public boolean add(E e) {
 210.201 +        typeCheck(e);
 210.202 +
 210.203 +        int eOrdinal = e.ordinal();
 210.204 +        int eWordNum = eOrdinal >>> 6;
 210.205 +
 210.206 +        long oldElements = elements[eWordNum];
 210.207 +        elements[eWordNum] |= (1L << eOrdinal);
 210.208 +        boolean result = (elements[eWordNum] != oldElements);
 210.209 +        if (result)
 210.210 +            size++;
 210.211 +        return result;
 210.212 +    }
 210.213 +
 210.214 +    /**
 210.215 +     * Removes the specified element from this set if it is present.
 210.216 +     *
 210.217 +     * @param e element to be removed from this set, if present
 210.218 +     * @return <tt>true</tt> if the set contained the specified element
 210.219 +     */
 210.220 +    public boolean remove(Object e) {
 210.221 +        if (e == null)
 210.222 +            return false;
 210.223 +        Class eClass = e.getClass();
 210.224 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 210.225 +            return false;
 210.226 +        int eOrdinal = ((Enum)e).ordinal();
 210.227 +        int eWordNum = eOrdinal >>> 6;
 210.228 +
 210.229 +        long oldElements = elements[eWordNum];
 210.230 +        elements[eWordNum] &= ~(1L << eOrdinal);
 210.231 +        boolean result = (elements[eWordNum] != oldElements);
 210.232 +        if (result)
 210.233 +            size--;
 210.234 +        return result;
 210.235 +    }
 210.236 +
 210.237 +    // Bulk Operations
 210.238 +
 210.239 +    /**
 210.240 +     * Returns <tt>true</tt> if this set contains all of the elements
 210.241 +     * in the specified collection.
 210.242 +     *
 210.243 +     * @param c collection to be checked for containment in this set
 210.244 +     * @return <tt>true</tt> if this set contains all of the elements
 210.245 +     *        in the specified collection
 210.246 +     * @throws NullPointerException if the specified collection is null
 210.247 +     */
 210.248 +    public boolean containsAll(Collection<?> c) {
 210.249 +        if (!(c instanceof JumboEnumSet))
 210.250 +            return super.containsAll(c);
 210.251 +
 210.252 +        JumboEnumSet es = (JumboEnumSet)c;
 210.253 +        if (es.elementType != elementType)
 210.254 +            return es.isEmpty();
 210.255 +
 210.256 +        for (int i = 0; i < elements.length; i++)
 210.257 +            if ((es.elements[i] & ~elements[i]) != 0)
 210.258 +                return false;
 210.259 +        return true;
 210.260 +    }
 210.261 +
 210.262 +    /**
 210.263 +     * Adds all of the elements in the specified collection to this set.
 210.264 +     *
 210.265 +     * @param c collection whose elements are to be added to this set
 210.266 +     * @return <tt>true</tt> if this set changed as a result of the call
 210.267 +     * @throws NullPointerException if the specified collection or any of
 210.268 +     *     its elements are null
 210.269 +     */
 210.270 +    public boolean addAll(Collection<? extends E> c) {
 210.271 +        if (!(c instanceof JumboEnumSet))
 210.272 +            return super.addAll(c);
 210.273 +
 210.274 +        JumboEnumSet es = (JumboEnumSet)c;
 210.275 +        if (es.elementType != elementType) {
 210.276 +            if (es.isEmpty())
 210.277 +                return false;
 210.278 +            else
 210.279 +                throw new ClassCastException(
 210.280 +                    es.elementType + " != " + elementType);
 210.281 +        }
 210.282 +
 210.283 +        for (int i = 0; i < elements.length; i++)
 210.284 +            elements[i] |= es.elements[i];
 210.285 +        return recalculateSize();
 210.286 +    }
 210.287 +
 210.288 +    /**
 210.289 +     * Removes from this set all of its elements that are contained in
 210.290 +     * the specified collection.
 210.291 +     *
 210.292 +     * @param c elements to be removed from this set
 210.293 +     * @return <tt>true</tt> if this set changed as a result of the call
 210.294 +     * @throws NullPointerException if the specified collection is null
 210.295 +     */
 210.296 +    public boolean removeAll(Collection<?> c) {
 210.297 +        if (!(c instanceof JumboEnumSet))
 210.298 +            return super.removeAll(c);
 210.299 +
 210.300 +        JumboEnumSet es = (JumboEnumSet)c;
 210.301 +        if (es.elementType != elementType)
 210.302 +            return false;
 210.303 +
 210.304 +        for (int i = 0; i < elements.length; i++)
 210.305 +            elements[i] &= ~es.elements[i];
 210.306 +        return recalculateSize();
 210.307 +    }
 210.308 +
 210.309 +    /**
 210.310 +     * Retains only the elements in this set that are contained in the
 210.311 +     * specified collection.
 210.312 +     *
 210.313 +     * @param c elements to be retained in this set
 210.314 +     * @return <tt>true</tt> if this set changed as a result of the call
 210.315 +     * @throws NullPointerException if the specified collection is null
 210.316 +     */
 210.317 +    public boolean retainAll(Collection<?> c) {
 210.318 +        if (!(c instanceof JumboEnumSet))
 210.319 +            return super.retainAll(c);
 210.320 +
 210.321 +        JumboEnumSet<?> es = (JumboEnumSet<?>)c;
 210.322 +        if (es.elementType != elementType) {
 210.323 +            boolean changed = (size != 0);
 210.324 +            clear();
 210.325 +            return changed;
 210.326 +        }
 210.327 +
 210.328 +        for (int i = 0; i < elements.length; i++)
 210.329 +            elements[i] &= es.elements[i];
 210.330 +        return recalculateSize();
 210.331 +    }
 210.332 +
 210.333 +    /**
 210.334 +     * Removes all of the elements from this set.
 210.335 +     */
 210.336 +    public void clear() {
 210.337 +        Arrays.fill(elements, 0);
 210.338 +        size = 0;
 210.339 +    }
 210.340 +
 210.341 +    /**
 210.342 +     * Compares the specified object with this set for equality.  Returns
 210.343 +     * <tt>true</tt> if the given object is also a set, the two sets have
 210.344 +     * the same size, and every member of the given set is contained in
 210.345 +     * this set.
 210.346 +     *
 210.347 +     * @param e object to be compared for equality with this set
 210.348 +     * @return <tt>true</tt> if the specified object is equal to this set
 210.349 +     */
 210.350 +    public boolean equals(Object o) {
 210.351 +        if (!(o instanceof JumboEnumSet))
 210.352 +            return super.equals(o);
 210.353 +
 210.354 +        JumboEnumSet es = (JumboEnumSet)o;
 210.355 +        if (es.elementType != elementType)
 210.356 +            return size == 0 && es.size == 0;
 210.357 +
 210.358 +        return Arrays.equals(es.elements, elements);
 210.359 +    }
 210.360 +
 210.361 +    /**
 210.362 +     * Recalculates the size of the set.  Returns true if it's changed.
 210.363 +     */
 210.364 +    private boolean recalculateSize() {
 210.365 +        int oldSize = size;
 210.366 +        size = 0;
 210.367 +        for (long elt : elements)
 210.368 +            size += Long.bitCount(elt);
 210.369 +
 210.370 +        return size != oldSize;
 210.371 +    }
 210.372 +
 210.373 +    public EnumSet<E> clone() {
 210.374 +        JumboEnumSet<E> result = (JumboEnumSet<E>) super.clone();
 210.375 +        result.elements = result.elements.clone();
 210.376 +        return result;
 210.377 +    }
 210.378 +}
   211.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   211.2 +++ b/rt/emul/compact/src/main/java/java/util/LinkedHashSet.java	Wed Apr 30 15:04:10 2014 +0200
   211.3 @@ -0,0 +1,171 @@
   211.4 +/*
   211.5 + * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
   211.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   211.7 + *
   211.8 + * This code is free software; you can redistribute it and/or modify it
   211.9 + * under the terms of the GNU General Public License version 2 only, as
  211.10 + * published by the Free Software Foundation.  Oracle designates this
  211.11 + * particular file as subject to the "Classpath" exception as provided
  211.12 + * by Oracle in the LICENSE file that accompanied this code.
  211.13 + *
  211.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  211.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  211.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  211.17 + * version 2 for more details (a copy is included in the LICENSE file that
  211.18 + * accompanied this code).
  211.19 + *
  211.20 + * You should have received a copy of the GNU General Public License version
  211.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  211.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  211.23 + *
  211.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  211.25 + * or visit www.oracle.com if you need additional information or have any
  211.26 + * questions.
  211.27 + */
  211.28 +
  211.29 +package java.util;
  211.30 +
  211.31 +/**
  211.32 + * <p>Hash table and linked list implementation of the <tt>Set</tt> interface,
  211.33 + * with predictable iteration order.  This implementation differs from
  211.34 + * <tt>HashSet</tt> in that it maintains a doubly-linked list running through
  211.35 + * all of its entries.  This linked list defines the iteration ordering,
  211.36 + * which is the order in which elements were inserted into the set
  211.37 + * (<i>insertion-order</i>).  Note that insertion order is <i>not</i> affected
  211.38 + * if an element is <i>re-inserted</i> into the set.  (An element <tt>e</tt>
  211.39 + * is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
  211.40 + * <tt>s.contains(e)</tt> would return <tt>true</tt> immediately prior to
  211.41 + * the invocation.)
  211.42 + *
  211.43 + * <p>This implementation spares its clients from the unspecified, generally
  211.44 + * chaotic ordering provided by {@link HashSet}, without incurring the
  211.45 + * increased cost associated with {@link TreeSet}.  It can be used to
  211.46 + * produce a copy of a set that has the same order as the original, regardless
  211.47 + * of the original set's implementation:
  211.48 + * <pre>
  211.49 + *     void foo(Set s) {
  211.50 + *         Set copy = new LinkedHashSet(s);
  211.51 + *         ...
  211.52 + *     }
  211.53 + * </pre>
  211.54 + * This technique is particularly useful if a module takes a set on input,
  211.55 + * copies it, and later returns results whose order is determined by that of
  211.56 + * the copy.  (Clients generally appreciate having things returned in the same
  211.57 + * order they were presented.)
  211.58 + *
  211.59 + * <p>This class provides all of the optional <tt>Set</tt> operations, and
  211.60 + * permits null elements.  Like <tt>HashSet</tt>, it provides constant-time
  211.61 + * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
  211.62 + * <tt>remove</tt>), assuming the hash function disperses elements
  211.63 + * properly among the buckets.  Performance is likely to be just slightly
  211.64 + * below that of <tt>HashSet</tt>, due to the added expense of maintaining the
  211.65 + * linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
  211.66 + * requires time proportional to the <i>size</i> of the set, regardless of
  211.67 + * its capacity.  Iteration over a <tt>HashSet</tt> is likely to be more
  211.68 + * expensive, requiring time proportional to its <i>capacity</i>.
  211.69 + *
  211.70 + * <p>A linked hash set has two parameters that affect its performance:
  211.71 + * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
  211.72 + * as for <tt>HashSet</tt>.  Note, however, that the penalty for choosing an
  211.73 + * excessively high value for initial capacity is less severe for this class
  211.74 + * than for <tt>HashSet</tt>, as iteration times for this class are unaffected
  211.75 + * by capacity.
  211.76 + *
  211.77 + * <p><strong>Note that this implementation is not synchronized.</strong>
  211.78 + * If multiple threads access a linked hash set concurrently, and at least
  211.79 + * one of the threads modifies the set, it <em>must</em> be synchronized
  211.80 + * externally.  This is typically accomplished by synchronizing on some
  211.81 + * object that naturally encapsulates the set.
  211.82 + *
  211.83 + * If no such object exists, the set should be "wrapped" using the
  211.84 + * {@link Collections#synchronizedSet Collections.synchronizedSet}
  211.85 + * method.  This is best done at creation time, to prevent accidental
  211.86 + * unsynchronized access to the set: <pre>
  211.87 + *   Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
  211.88 + *
  211.89 + * <p>The iterators returned by this class's <tt>iterator</tt> method are
  211.90 + * <em>fail-fast</em>: if the set is modified at any time after the iterator
  211.91 + * is created, in any way except through the iterator's own <tt>remove</tt>
  211.92 + * method, the iterator will throw a {@link ConcurrentModificationException}.
  211.93 + * Thus, in the face of concurrent modification, the iterator fails quickly
  211.94 + * and cleanly, rather than risking arbitrary, non-deterministic behavior at
  211.95 + * an undetermined time in the future.
  211.96 + *
  211.97 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  211.98 + * as it is, generally speaking, impossible to make any hard guarantees in the
  211.99 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 211.100 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 211.101 + * Therefore, it would be wrong to write a program that depended on this
 211.102 + * exception for its correctness:   <i>the fail-fast behavior of iterators
 211.103 + * should be used only to detect bugs.</i>
 211.104 + *
 211.105 + * <p>This class is a member of the
 211.106 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 211.107 + * Java Collections Framework</a>.
 211.108 + *
 211.109 + * @param <E> the type of elements maintained by this set
 211.110 + *
 211.111 + * @author  Josh Bloch
 211.112 + * @see     Object#hashCode()
 211.113 + * @see     Collection
 211.114 + * @see     Set
 211.115 + * @see     HashSet
 211.116 + * @see     TreeSet
 211.117 + * @see     Hashtable
 211.118 + * @since   1.4
 211.119 + */
 211.120 +
 211.121 +public class LinkedHashSet<E>
 211.122 +    extends HashSet<E>
 211.123 +    implements Set<E>, Cloneable, java.io.Serializable {
 211.124 +
 211.125 +    private static final long serialVersionUID = -2851667679971038690L;
 211.126 +
 211.127 +    /**
 211.128 +     * Constructs a new, empty linked hash set with the specified initial
 211.129 +     * capacity and load factor.
 211.130 +     *
 211.131 +     * @param      initialCapacity the initial capacity of the linked hash set
 211.132 +     * @param      loadFactor      the load factor of the linked hash set
 211.133 +     * @throws     IllegalArgumentException  if the initial capacity is less
 211.134 +     *               than zero, or if the load factor is nonpositive
 211.135 +     */
 211.136 +    public LinkedHashSet(int initialCapacity, float loadFactor) {
 211.137 +        super(initialCapacity, loadFactor, true);
 211.138 +    }
 211.139 +
 211.140 +    /**
 211.141 +     * Constructs a new, empty linked hash set with the specified initial
 211.142 +     * capacity and the default load factor (0.75).
 211.143 +     *
 211.144 +     * @param   initialCapacity   the initial capacity of the LinkedHashSet
 211.145 +     * @throws  IllegalArgumentException if the initial capacity is less
 211.146 +     *              than zero
 211.147 +     */
 211.148 +    public LinkedHashSet(int initialCapacity) {
 211.149 +        super(initialCapacity, .75f, true);
 211.150 +    }
 211.151 +
 211.152 +    /**
 211.153 +     * Constructs a new, empty linked hash set with the default initial
 211.154 +     * capacity (16) and load factor (0.75).
 211.155 +     */
 211.156 +    public LinkedHashSet() {
 211.157 +        super(16, .75f, true);
 211.158 +    }
 211.159 +
 211.160 +    /**
 211.161 +     * Constructs a new linked hash set with the same elements as the
 211.162 +     * specified collection.  The linked hash set is created with an initial
 211.163 +     * capacity sufficient to hold the elements in the specified collection
 211.164 +     * and the default load factor (0.75).
 211.165 +     *
 211.166 +     * @param c  the collection whose elements are to be placed into
 211.167 +     *           this set
 211.168 +     * @throws NullPointerException if the specified collection is null
 211.169 +     */
 211.170 +    public LinkedHashSet(Collection<? extends E> c) {
 211.171 +        super(Math.max(2*c.size(), 11), .75f, true);
 211.172 +        addAll(c);
 211.173 +    }
 211.174 +}
   212.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   212.2 +++ b/rt/emul/compact/src/main/java/java/util/Locale.java	Wed Apr 30 15:04:10 2014 +0200
   212.3 @@ -0,0 +1,1012 @@
   212.4 +/*
   212.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   212.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   212.7 + *
   212.8 + * This code is free software; you can redistribute it and/or modify it
   212.9 + * under the terms of the GNU General Public License version 2 only, as
  212.10 + * published by the Free Software Foundation.  Oracle designates this
  212.11 + * particular file as subject to the "Classpath" exception as provided
  212.12 + * by Oracle in the LICENSE file that accompanied this code.
  212.13 + *
  212.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  212.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  212.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  212.17 + * version 2 for more details (a copy is included in the LICENSE file that
  212.18 + * accompanied this code).
  212.19 + *
  212.20 + * You should have received a copy of the GNU General Public License version
  212.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  212.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  212.23 + *
  212.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  212.25 + * or visit www.oracle.com if you need additional information or have any
  212.26 + * questions.
  212.27 + */
  212.28 +
  212.29 +/*
  212.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  212.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  212.32 + *
  212.33 + * The original version of this source code and documentation
  212.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
  212.35 + * subsidiary of IBM. These materials are provided under terms
  212.36 + * of a License Agreement between Taligent and Sun. This technology
  212.37 + * is protected by multiple US and International patents.
  212.38 + *
  212.39 + * This notice and attribution to Taligent may not be removed.
  212.40 + * Taligent is a registered trademark of Taligent, Inc.
  212.41 + *
  212.42 + */
  212.43 +
  212.44 +package java.util;
  212.45 +
  212.46 +import java.io.IOException;
  212.47 +import java.io.ObjectInputStream;
  212.48 +import java.io.ObjectOutputStream;
  212.49 +import java.io.ObjectStreamField;
  212.50 +import java.io.Serializable;
  212.51 +
  212.52 +/**
  212.53 + * A <code>Locale</code> object represents a specific geographical, political,
  212.54 + * or cultural region. An operation that requires a <code>Locale</code> to perform
  212.55 + * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
  212.56 + * to tailor information for the user. For example, displaying a number
  212.57 + * is a locale-sensitive operation&mdash; the number should be formatted
  212.58 + * according to the customs and conventions of the user's native country,
  212.59 + * region, or culture.
  212.60 + *
  212.61 + * <p> The <code>Locale</code> class implements identifiers
  212.62 + * interchangeable with BCP 47 (IETF BCP 47, "Tags for Identifying
  212.63 + * Languages"), with support for the LDML (UTS#35, "Unicode Locale
  212.64 + * Data Markup Language") BCP 47-compatible extensions for locale data
  212.65 + * exchange.
  212.66 + *
  212.67 + * <p> A <code>Locale</code> object logically consists of the fields
  212.68 + * described below.
  212.69 + *
  212.70 + * <dl>
  212.71 + *   <dt><a name="def_language"/><b>language</b></dt>
  212.72 + *
  212.73 + *   <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
  212.74 + *   language subtags up to 8 alpha letters (for future enhancements).
  212.75 + *   When a language has both an alpha-2 code and an alpha-3 code, the
  212.76 + *   alpha-2 code must be used.  You can find a full list of valid
  212.77 + *   language codes in the IANA Language Subtag Registry (search for
  212.78 + *   "Type: language").  The language field is case insensitive, but
  212.79 + *   <code>Locale</code> always canonicalizes to lower case.</dd><br>
  212.80 + *
  212.81 + *   <dd>Well-formed language values have the form
  212.82 + *   <code>[a-zA-Z]{2,8}</code>.  Note that this is not the the full
  212.83 + *   BCP47 language production, since it excludes extlang.  They are
  212.84 + *   not needed since modern three-letter language codes replace
  212.85 + *   them.</dd><br>
  212.86 + *
  212.87 + *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
  212.88 + *
  212.89 + *   <dt><a name="def_script"/><b>script</b></dt>
  212.90 + *
  212.91 + *   <dd>ISO 15924 alpha-4 script code.  You can find a full list of
  212.92 + *   valid script codes in the IANA Language Subtag Registry (search
  212.93 + *   for "Type: script").  The script field is case insensitive, but
  212.94 + *   <code>Locale</code> always canonicalizes to title case (the first
  212.95 + *   letter is upper case and the rest of the letters are lower
  212.96 + *   case).</dd><br>
  212.97 + *
  212.98 + *   <dd>Well-formed script values have the form
  212.99 + *   <code>[a-zA-Z]{4}</code></dd><br>
 212.100 + *
 212.101 + *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
 212.102 + *
 212.103 + *   <dt><a name="def_region"/><b>country (region)</b></dt>
 212.104 + *
 212.105 + *   <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
 212.106 + *   You can find a full list of valid country and region codes in the
 212.107 + *   IANA Language Subtag Registry (search for "Type: region").  The
 212.108 + *   country (region) field is case insensitive, but
 212.109 + *   <code>Locale</code> always canonicalizes to upper case.</dd><br>
 212.110 + *
 212.111 + *   <dd>Well-formed country/region values have
 212.112 + *   the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
 212.113 + *
 212.114 + *   <dd>Example: "US" (United States), "FR" (France), "029"
 212.115 + *   (Caribbean)</dd><br>
 212.116 + *
 212.117 + *   <dt><a name="def_variant"/><b>variant</b></dt>
 212.118 + *
 212.119 + *   <dd>Any arbitrary value used to indicate a variation of a
 212.120 + *   <code>Locale</code>.  Where there are two or more variant values
 212.121 + *   each indicating its own semantics, these values should be ordered
 212.122 + *   by importance, with most important first, separated by
 212.123 + *   underscore('_').  The variant field is case sensitive.</dd><br>
 212.124 + *
 212.125 + *   <dd>Note: IETF BCP 47 places syntactic restrictions on variant
 212.126 + *   subtags.  Also BCP 47 subtags are strictly used to indicate
 212.127 + *   additional variations that define a language or its dialects that
 212.128 + *   are not covered by any combinations of language, script and
 212.129 + *   region subtags.  You can find a full list of valid variant codes
 212.130 + *   in the IANA Language Subtag Registry (search for "Type: variant").
 212.131 + *
 212.132 + *   <p>However, the variant field in <code>Locale</code> has
 212.133 + *   historically been used for any kind of variation, not just
 212.134 + *   language variations.  For example, some supported variants
 212.135 + *   available in Java SE Runtime Environments indicate alternative
 212.136 + *   cultural behaviors such as calendar type or number script.  In
 212.137 + *   BCP 47 this kind of information, which does not identify the
 212.138 + *   language, is supported by extension subtags or private use
 212.139 + *   subtags.</dd><br>
 212.140 + *
 212.141 + *   <dd>Well-formed variant values have the form <code>SUBTAG
 212.142 + *   (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
 212.143 + *   [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
 212.144 + *   uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
 212.145 + *
 212.146 + *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
 212.147 + *
 212.148 + *   <dt><a name="def_extensions"/><b>extensions</b></dt>
 212.149 + *
 212.150 + *   <dd>A map from single character keys to string values, indicating
 212.151 + *   extensions apart from language identification.  The extensions in
 212.152 + *   <code>Locale</code> implement the semantics and syntax of BCP 47
 212.153 + *   extension subtags and private use subtags. The extensions are
 212.154 + *   case insensitive, but <code>Locale</code> canonicalizes all
 212.155 + *   extension keys and values to lower case. Note that extensions
 212.156 + *   cannot have empty values.</dd><br>
 212.157 + *
 212.158 + *   <dd>Well-formed keys are single characters from the set
 212.159 + *   <code>[0-9a-zA-Z]</code>.  Well-formed values have the form
 212.160 + *   <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
 212.161 + *   <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
 212.162 + *   <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
 212.163 + *   single-character subtags).</dd><br>
 212.164 + *
 212.165 + *   <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
 212.166 + *   key="x"/value="java-1-7"</dd>
 212.167 + * </dl>
 212.168 + *
 212.169 + * <b>Note:</b> Although BCP 47 requires field values to be registered
 212.170 + * in the IANA Language Subtag Registry, the <code>Locale</code> class
 212.171 + * does not provide any validation features.  The <code>Builder</code>
 212.172 + * only checks if an individual field satisfies the syntactic
 212.173 + * requirement (is well-formed), but does not validate the value
 212.174 + * itself.  See {@link Builder} for details.
 212.175 + *
 212.176 + * <h4><a name="def_locale_extension">Unicode locale/language extension</h4>
 212.177 + *
 212.178 + * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
 212.179 + * attributes and keywords to override or refine the default behavior
 212.180 + * associated with a locale.  A keyword is represented by a pair of
 212.181 + * key and type.  For example, "nu-thai" indicates that Thai local
 212.182 + * digits (value:"thai") should be used for formatting numbers
 212.183 + * (key:"nu").
 212.184 + *
 212.185 + * <p>The keywords are mapped to a BCP 47 extension value using the
 212.186 + * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}).  The above
 212.187 + * example, "nu-thai", becomes the extension "u-nu-thai".code
 212.188 + *
 212.189 + * <p>Thus, when a <code>Locale</code> object contains Unicode locale
 212.190 + * attributes and keywords,
 212.191 + * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a
 212.192 + * String representing this information, for example, "nu-thai".  The
 212.193 + * <code>Locale</code> class also provides {@link
 212.194 + * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
 212.195 + * {@link #getUnicodeLocaleType} which allow you to access Unicode
 212.196 + * locale attributes and key/type pairs directly.  When represented as
 212.197 + * a string, the Unicode Locale Extension lists attributes
 212.198 + * alphabetically, followed by key/type sequences with keys listed
 212.199 + * alphabetically (the order of subtags comprising a key's type is
 212.200 + * fixed when the type is defined)
 212.201 + *
 212.202 + * <p>A well-formed locale key has the form
 212.203 + * <code>[0-9a-zA-Z]{2}</code>.  A well-formed locale type has the
 212.204 + * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it
 212.205 + * can be empty, or a series of subtags 3-8 alphanums in length).  A
 212.206 + * well-formed locale attribute has the form
 212.207 + * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same
 212.208 + * form as a locale type subtag).
 212.209 + *
 212.210 + * <p>The Unicode locale extension specifies optional behavior in
 212.211 + * locale-sensitive services.  Although the LDML specification defines
 212.212 + * various keys and values, actual locale-sensitive service
 212.213 + * implementations in a Java Runtime Environment might not support any
 212.214 + * particular Unicode locale attributes or key/type pairs.
 212.215 + *
 212.216 + * <h4>Creating a Locale</h4>
 212.217 + *
 212.218 + * <p>There are several different ways to create a <code>Locale</code>
 212.219 + * object.
 212.220 + *
 212.221 + * <h5>Builder</h5>
 212.222 + *
 212.223 + * <p>Using {@link Builder} you can construct a <code>Locale</code> object
 212.224 + * that conforms to BCP 47 syntax.
 212.225 + *
 212.226 + * <h5>Constructors</h5>
 212.227 + *
 212.228 + * <p>The <code>Locale</code> class provides three constructors:
 212.229 + * <blockquote>
 212.230 + * <pre>
 212.231 + *     {@link #Locale(String language)}
 212.232 + *     {@link #Locale(String language, String country)}
 212.233 + *     {@link #Locale(String language, String country, String variant)}
 212.234 + * </pre>
 212.235 + * </blockquote>
 212.236 + * These constructors allow you to create a <code>Locale</code> object
 212.237 + * with language, country and variant, but you cannot specify
 212.238 + * script or extensions.
 212.239 + *
 212.240 + * <h5>Factory Methods</h5>
 212.241 + *
 212.242 + * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
 212.243 + * object for a well-formed BCP 47 language tag.
 212.244 + *
 212.245 + * <h5>Locale Constants</h5>
 212.246 + *
 212.247 + * <p>The <code>Locale</code> class provides a number of convenient constants
 212.248 + * that you can use to create <code>Locale</code> objects for commonly used
 212.249 + * locales. For example, the following creates a <code>Locale</code> object
 212.250 + * for the United States:
 212.251 + * <blockquote>
 212.252 + * <pre>
 212.253 + *     Locale.US
 212.254 + * </pre>
 212.255 + * </blockquote>
 212.256 + *
 212.257 + * <h4>Use of Locale</h4>
 212.258 + *
 212.259 + * <p>Once you've created a <code>Locale</code> you can query it for information
 212.260 + * about itself. Use <code>getCountry</code> to get the country (or region)
 212.261 + * code and <code>getLanguage</code> to get the language code.
 212.262 + * You can use <code>getDisplayCountry</code> to get the
 212.263 + * name of the country suitable for displaying to the user. Similarly,
 212.264 + * you can use <code>getDisplayLanguage</code> to get the name of
 212.265 + * the language suitable for displaying to the user. Interestingly,
 212.266 + * the <code>getDisplayXXX</code> methods are themselves locale-sensitive
 212.267 + * and have two versions: one that uses the default locale and one
 212.268 + * that uses the locale specified as an argument.
 212.269 + *
 212.270 + * <p>The Java Platform provides a number of classes that perform locale-sensitive
 212.271 + * operations. For example, the <code>NumberFormat</code> class formats
 212.272 + * numbers, currency, and percentages in a locale-sensitive manner. Classes
 212.273 + * such as <code>NumberFormat</code> have several convenience methods
 212.274 + * for creating a default object of that type. For example, the
 212.275 + * <code>NumberFormat</code> class provides these three convenience methods
 212.276 + * for creating a default <code>NumberFormat</code> object:
 212.277 + * <blockquote>
 212.278 + * <pre>
 212.279 + *     NumberFormat.getInstance()
 212.280 + *     NumberFormat.getCurrencyInstance()
 212.281 + *     NumberFormat.getPercentInstance()
 212.282 + * </pre>
 212.283 + * </blockquote>
 212.284 + * Each of these methods has two variants; one with an explicit locale
 212.285 + * and one without; the latter uses the default locale:
 212.286 + * <blockquote>
 212.287 + * <pre>
 212.288 + *     NumberFormat.getInstance(myLocale)
 212.289 + *     NumberFormat.getCurrencyInstance(myLocale)
 212.290 + *     NumberFormat.getPercentInstance(myLocale)
 212.291 + * </pre>
 212.292 + * </blockquote>
 212.293 + * A <code>Locale</code> is the mechanism for identifying the kind of object
 212.294 + * (<code>NumberFormat</code>) that you would like to get. The locale is
 212.295 + * <STRONG>just</STRONG> a mechanism for identifying objects,
 212.296 + * <STRONG>not</STRONG> a container for the objects themselves.
 212.297 + *
 212.298 + * <h4>Compatibility</h4>
 212.299 + *
 212.300 + * <p>In order to maintain compatibility with existing usage, Locale's
 212.301 + * constructors retain their behavior prior to the Java Runtime
 212.302 + * Environment version 1.7.  The same is largely true for the
 212.303 + * <code>toString</code> method. Thus Locale objects can continue to
 212.304 + * be used as they were. In particular, clients who parse the output
 212.305 + * of toString into language, country, and variant fields can continue
 212.306 + * to do so (although this is strongly discouraged), although the
 212.307 + * variant field will have additional information in it if script or
 212.308 + * extensions are present.
 212.309 + *
 212.310 + * <p>In addition, BCP 47 imposes syntax restrictions that are not
 212.311 + * imposed by Locale's constructors. This means that conversions
 212.312 + * between some Locales and BCP 47 language tags cannot be made without
 212.313 + * losing information. Thus <code>toLanguageTag</code> cannot
 212.314 + * represent the state of locales whose language, country, or variant
 212.315 + * do not conform to BCP 47.
 212.316 + *
 212.317 + * <p>Because of these issues, it is recommended that clients migrate
 212.318 + * away from constructing non-conforming locales and use the
 212.319 + * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead.
 212.320 + * Clients desiring a string representation of the complete locale can
 212.321 + * then always rely on <code>toLanguageTag</code> for this purpose.
 212.322 + *
 212.323 + * <h5><a name="special_cases_constructor"/>Special cases</h5>
 212.324 + *
 212.325 + * <p>For compatibility reasons, two
 212.326 + * non-conforming locales are treated as special cases.  These are
 212.327 + * <b><tt>ja_JP_JP</tt></b> and <b><tt>th_TH_TH</tt></b>. These are ill-formed
 212.328 + * in BCP 47 since the variants are too short. To ease migration to BCP 47,
 212.329 + * these are treated specially during construction.  These two cases (and only
 212.330 + * these) cause a constructor to generate an extension, all other values behave
 212.331 + * exactly as they did prior to Java 7.
 212.332 + *
 212.333 + * <p>Java has used <tt>ja_JP_JP</tt> to represent Japanese as used in
 212.334 + * Japan together with the Japanese Imperial calendar. This is now
 212.335 + * representable using a Unicode locale extension, by specifying the
 212.336 + * Unicode locale key <tt>ca</tt> (for "calendar") and type
 212.337 + * <tt>japanese</tt>. When the Locale constructor is called with the
 212.338 + * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
 212.339 + * automatically added.
 212.340 + *
 212.341 + * <p>Java has used <tt>th_TH_TH</tt> to represent Thai as used in
 212.342 + * Thailand together with Thai digits. This is also now representable using
 212.343 + * a Unicode locale extension, by specifying the Unicode locale key
 212.344 + * <tt>nu</tt> (for "number") and value <tt>thai</tt>. When the Locale
 212.345 + * constructor is called with the arguments "th", "TH", "TH", the
 212.346 + * extension "u-nu-thai" is automatically added.
 212.347 + *
 212.348 + * <h5>Serialization</h5>
 212.349 + *
 212.350 + * <p>During serialization, writeObject writes all fields to the output
 212.351 + * stream, including extensions.
 212.352 + *
 212.353 + * <p>During deserialization, readResolve adds extensions as described
 212.354 + * in <a href="#special_cases_constructor">Special Cases</a>, only
 212.355 + * for the two cases th_TH_TH and ja_JP_JP.
 212.356 + *
 212.357 + * <h5>Legacy language codes</h5>
 212.358 + *
 212.359 + * <p>Locale's constructor has always converted three language codes to
 212.360 + * their earlier, obsoleted forms: <tt>he</tt> maps to <tt>iw</tt>,
 212.361 + * <tt>yi</tt> maps to <tt>ji</tt>, and <tt>id</tt> maps to
 212.362 + * <tt>in</tt>.  This continues to be the case, in order to not break
 212.363 + * backwards compatibility.
 212.364 + *
 212.365 + * <p>The APIs added in 1.7 map between the old and new language codes,
 212.366 + * maintaining the old codes internal to Locale (so that
 212.367 + * <code>getLanguage</code> and <code>toString</code> reflect the old
 212.368 + * code), but using the new codes in the BCP 47 language tag APIs (so
 212.369 + * that <code>toLanguageTag</code> reflects the new one). This
 212.370 + * preserves the equivalence between Locales no matter which code or
 212.371 + * API is used to construct them. Java's default resource bundle
 212.372 + * lookup mechanism also implements this mapping, so that resources
 212.373 + * can be named using either convention, see {@link ResourceBundle.Control}.
 212.374 + *
 212.375 + * <h5>Three-letter language/country(region) codes</h5>
 212.376 + *
 212.377 + * <p>The Locale constructors have always specified that the language
 212.378 + * and the country param be two characters in length, although in
 212.379 + * practice they have accepted any length.  The specification has now
 212.380 + * been relaxed to allow language codes of two to eight characters and
 212.381 + * country (region) codes of two to three characters, and in
 212.382 + * particular, three-letter language codes and three-digit region
 212.383 + * codes as specified in the IANA Language Subtag Registry.  For
 212.384 + * compatibility, the implementation still does not impose a length
 212.385 + * constraint.
 212.386 + *
 212.387 + * @see Builder
 212.388 + * @see ResourceBundle
 212.389 + * @see java.text.Format
 212.390 + * @see java.text.NumberFormat
 212.391 + * @see java.text.Collator
 212.392 + * @author Mark Davis
 212.393 + * @since 1.1
 212.394 + */
 212.395 +public final class Locale implements Cloneable, Serializable {
 212.396 +
 212.397 +    /** Useful constant for language.
 212.398 +     */
 212.399 +    static public final Locale ENGLISH = createConstant("en", "");
 212.400 +
 212.401 +    /** Useful constant for language.
 212.402 +     */
 212.403 +    static public final Locale FRENCH = createConstant("fr", "");
 212.404 +
 212.405 +    /** Useful constant for language.
 212.406 +     */
 212.407 +    static public final Locale GERMAN = createConstant("de", "");
 212.408 +
 212.409 +    /** Useful constant for language.
 212.410 +     */
 212.411 +    static public final Locale ITALIAN = createConstant("it", "");
 212.412 +
 212.413 +    /** Useful constant for language.
 212.414 +     */
 212.415 +    static public final Locale JAPANESE = createConstant("ja", "");
 212.416 +
 212.417 +    /** Useful constant for language.
 212.418 +     */
 212.419 +    static public final Locale KOREAN = createConstant("ko", "");
 212.420 +
 212.421 +    /** Useful constant for language.
 212.422 +     */
 212.423 +    static public final Locale CHINESE = createConstant("zh", "");
 212.424 +
 212.425 +    /** Useful constant for language.
 212.426 +     */
 212.427 +    static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
 212.428 +
 212.429 +    /** Useful constant for language.
 212.430 +     */
 212.431 +    static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
 212.432 +
 212.433 +    /** Useful constant for country.
 212.434 +     */
 212.435 +    static public final Locale FRANCE = createConstant("fr", "FR");
 212.436 +
 212.437 +    /** Useful constant for country.
 212.438 +     */
 212.439 +    static public final Locale GERMANY = createConstant("de", "DE");
 212.440 +
 212.441 +    /** Useful constant for country.
 212.442 +     */
 212.443 +    static public final Locale ITALY = createConstant("it", "IT");
 212.444 +
 212.445 +    /** Useful constant for country.
 212.446 +     */
 212.447 +    static public final Locale JAPAN = createConstant("ja", "JP");
 212.448 +
 212.449 +    /** Useful constant for country.
 212.450 +     */
 212.451 +    static public final Locale KOREA = createConstant("ko", "KR");
 212.452 +
 212.453 +    /** Useful constant for country.
 212.454 +     */
 212.455 +    static public final Locale CHINA = SIMPLIFIED_CHINESE;
 212.456 +
 212.457 +    /** Useful constant for country.
 212.458 +     */
 212.459 +    static public final Locale PRC = SIMPLIFIED_CHINESE;
 212.460 +
 212.461 +    /** Useful constant for country.
 212.462 +     */
 212.463 +    static public final Locale TAIWAN = TRADITIONAL_CHINESE;
 212.464 +
 212.465 +    /** Useful constant for country.
 212.466 +     */
 212.467 +    static public final Locale UK = createConstant("en", "GB");
 212.468 +
 212.469 +    /** Useful constant for country.
 212.470 +     */
 212.471 +    static public final Locale US = createConstant("en", "US");
 212.472 +
 212.473 +    /** Useful constant for country.
 212.474 +     */
 212.475 +    static public final Locale CANADA = createConstant("en", "CA");
 212.476 +
 212.477 +    /** Useful constant for country.
 212.478 +     */
 212.479 +    static public final Locale CANADA_FRENCH = createConstant("fr", "CA");
 212.480 +
 212.481 +    /**
 212.482 +     * Useful constant for the root locale.  The root locale is the locale whose
 212.483 +     * language, country, and variant are empty ("") strings.  This is regarded
 212.484 +     * as the base locale of all locales, and is used as the language/country
 212.485 +     * neutral locale for the locale sensitive operations.
 212.486 +     *
 212.487 +     * @since 1.6
 212.488 +     */
 212.489 +    static public final Locale ROOT = createConstant("", "");
 212.490 +
 212.491 +    /**
 212.492 +     * The key for the private use extension ('x').
 212.493 +     *
 212.494 +     * @see #getExtension(char)
 212.495 +     * @see Builder#setExtension(char, String)
 212.496 +     * @since 1.7
 212.497 +     */
 212.498 +    static public final char PRIVATE_USE_EXTENSION = 'x';
 212.499 +
 212.500 +    /**
 212.501 +     * The key for Unicode locale extension ('u').
 212.502 +     *
 212.503 +     * @see #getExtension(char)
 212.504 +     * @see Builder#setExtension(char, String)
 212.505 +     * @since 1.7
 212.506 +     */
 212.507 +    static public final char UNICODE_LOCALE_EXTENSION = 'u';
 212.508 +
 212.509 +    /** serialization ID
 212.510 +     */
 212.511 +    static final long serialVersionUID = 9149081749638150636L;
 212.512 +
 212.513 +    /**
 212.514 +     * Display types for retrieving localized names from the name providers.
 212.515 +     */
 212.516 +    private static final int DISPLAY_LANGUAGE = 0;
 212.517 +    private static final int DISPLAY_COUNTRY  = 1;
 212.518 +    private static final int DISPLAY_VARIANT  = 2;
 212.519 +    private static final int DISPLAY_SCRIPT   = 3;
 212.520 +
 212.521 +    static Locale getInstance(String language, String script, String region, String v, Object object) {
 212.522 +        return new Locale(language, script, region);
 212.523 +    }
 212.524 +
 212.525 +    static Locale getInstance(String no, String no0, String ny) {
 212.526 +        return new Locale(no, no0, ny);
 212.527 +    }
 212.528 +    
 212.529 +    private String language;
 212.530 +    private String country;
 212.531 +    private String variant;
 212.532 +
 212.533 +
 212.534 +    /**
 212.535 +     * Construct a locale from language, country and variant.
 212.536 +     * This constructor normalizes the language value to lowercase and
 212.537 +     * the country value to uppercase.
 212.538 +     * <p>
 212.539 +     * <b>Note:</b>
 212.540 +     * <ul>
 212.541 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 212.542 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 212.543 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 212.544 +     * API on Locale will return only the OLD codes.
 212.545 +     * <li>For backward compatibility reasons, this constructor does not make
 212.546 +     * any syntactic checks on the input.
 212.547 +     * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
 212.548 +     * see <a href="#special_cases_constructor">Special Cases</a> for more information.
 212.549 +     * </ul>
 212.550 +     *
 212.551 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 212.552 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 212.553 +     * valid language values.
 212.554 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
 212.555 +     * See the <code>Locale</code> class description about valid country values.
 212.556 +     * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
 212.557 +     * See the <code>Locale</code> class description for the details.
 212.558 +     * @exception NullPointerException thrown if any argument is null.
 212.559 +     */
 212.560 +    public Locale(String language, String country, String variant) {
 212.561 +        if (language== null || country == null || variant == null) {
 212.562 +            throw new NullPointerException();
 212.563 +        }
 212.564 +        this.language = language;
 212.565 +        this.country = country;
 212.566 +        this.variant = variant;
 212.567 +    }
 212.568 +
 212.569 +    /**
 212.570 +     * Construct a locale from language and country.
 212.571 +     * This constructor normalizes the language value to lowercase and
 212.572 +     * the country value to uppercase.
 212.573 +     * <p>
 212.574 +     * <b>Note:</b>
 212.575 +     * <ul>
 212.576 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 212.577 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 212.578 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 212.579 +     * API on Locale will return only the OLD codes.
 212.580 +     * <li>For backward compatibility reasons, this constructor does not make
 212.581 +     * any syntactic checks on the input.
 212.582 +     * </ul>
 212.583 +     *
 212.584 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 212.585 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 212.586 +     * valid language values.
 212.587 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
 212.588 +     * See the <code>Locale</code> class description about valid country values.
 212.589 +     * @exception NullPointerException thrown if either argument is null.
 212.590 +     */
 212.591 +    public Locale(String language, String country) {
 212.592 +        this(language, country, "");
 212.593 +    }
 212.594 +
 212.595 +    /**
 212.596 +     * Construct a locale from a language code.
 212.597 +     * This constructor normalizes the language value to lowercase.
 212.598 +     * <p>
 212.599 +     * <b>Note:</b>
 212.600 +     * <ul>
 212.601 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 212.602 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 212.603 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 212.604 +     * API on Locale will return only the OLD codes.
 212.605 +     * <li>For backward compatibility reasons, this constructor does not make
 212.606 +     * any syntactic checks on the input.
 212.607 +     * </ul>
 212.608 +     *
 212.609 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 212.610 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 212.611 +     * valid language values.
 212.612 +     * @exception NullPointerException thrown if argument is null.
 212.613 +     * @since 1.4
 212.614 +     */
 212.615 +    public Locale(String language) {
 212.616 +        this(language, "", "");
 212.617 +    }
 212.618 +
 212.619 +    /**
 212.620 +     * This method must be called only for creating the Locale.*
 212.621 +     * constants due to making shortcuts.
 212.622 +     */
 212.623 +    private static Locale createConstant(String lang, String country) {
 212.624 +        return new Locale(lang, country);
 212.625 +    }
 212.626 +
 212.627 +    /**
 212.628 +     * Gets the current value of the default locale for this instance
 212.629 +     * of the Java Virtual Machine.
 212.630 +     * <p>
 212.631 +     * The Java Virtual Machine sets the default locale during startup
 212.632 +     * based on the host environment. It is used by many locale-sensitive
 212.633 +     * methods if no locale is explicitly specified.
 212.634 +     * It can be changed using the
 212.635 +     * {@link #setDefault(java.util.Locale) setDefault} method.
 212.636 +     *
 212.637 +     * @return the default locale for this instance of the Java Virtual Machine
 212.638 +     */
 212.639 +    public static Locale getDefault() {
 212.640 +        return Locale.US;
 212.641 +    }
 212.642 +
 212.643 +    /**
 212.644 +     * Gets the current value of the default locale for the specified Category
 212.645 +     * for this instance of the Java Virtual Machine.
 212.646 +     * <p>
 212.647 +     * The Java Virtual Machine sets the default locale during startup based
 212.648 +     * on the host environment. It is used by many locale-sensitive methods
 212.649 +     * if no locale is explicitly specified. It can be changed using the
 212.650 +     * setDefault(Locale.Category, Locale) method.
 212.651 +     *
 212.652 +     * @param category - the specified category to get the default locale
 212.653 +     * @throws NullPointerException - if category is null
 212.654 +     * @return the default locale for the specified Category for this instance
 212.655 +     *     of the Java Virtual Machine
 212.656 +     * @see #setDefault(Locale.Category, Locale)
 212.657 +     * @since 1.7
 212.658 +     */
 212.659 +    public static Locale getDefault(Locale.Category category) {
 212.660 +        return Locale.US;
 212.661 +    }
 212.662 +    
 212.663 +    /**
 212.664 +     * Sets the default locale for this instance of the Java Virtual Machine.
 212.665 +     * This does not affect the host locale.
 212.666 +     * <p>
 212.667 +     * If there is a security manager, its <code>checkPermission</code>
 212.668 +     * method is called with a <code>PropertyPermission("user.language", "write")</code>
 212.669 +     * permission before the default locale is changed.
 212.670 +     * <p>
 212.671 +     * The Java Virtual Machine sets the default locale during startup
 212.672 +     * based on the host environment. It is used by many locale-sensitive
 212.673 +     * methods if no locale is explicitly specified.
 212.674 +     * <p>
 212.675 +     * Since changing the default locale may affect many different areas
 212.676 +     * of functionality, this method should only be used if the caller
 212.677 +     * is prepared to reinitialize locale-sensitive code running
 212.678 +     * within the same Java Virtual Machine.
 212.679 +     * <p>
 212.680 +     * By setting the default locale with this method, all of the default
 212.681 +     * locales for each Category are also set to the specified default locale.
 212.682 +     *
 212.683 +     * @throws SecurityException
 212.684 +     *        if a security manager exists and its
 212.685 +     *        <code>checkPermission</code> method doesn't allow the operation.
 212.686 +     * @throws NullPointerException if <code>newLocale</code> is null
 212.687 +     * @param newLocale the new default locale
 212.688 +     * @see SecurityManager#checkPermission
 212.689 +     * @see java.util.PropertyPermission
 212.690 +     */
 212.691 +    public static void setDefault(Locale newLocale) {
 212.692 +        throw new SecurityException();
 212.693 +    }
 212.694 +
 212.695 +    /**
 212.696 +     * Returns an array of all installed locales.
 212.697 +     * The returned array represents the union of locales supported
 212.698 +     * by the Java runtime environment and by installed
 212.699 +     * {@link java.util.spi.LocaleServiceProvider LocaleServiceProvider}
 212.700 +     * implementations.  It must contain at least a <code>Locale</code>
 212.701 +     * instance equal to {@link java.util.Locale#US Locale.US}.
 212.702 +     *
 212.703 +     * @return An array of installed locales.
 212.704 +     */
 212.705 +    public static Locale[] getAvailableLocales() {
 212.706 +        return new Locale[] { Locale.US };
 212.707 +    }
 212.708 +
 212.709 +    /**
 212.710 +     * Returns the language code of this Locale.
 212.711 +     *
 212.712 +     * <p><b>Note:</b> ISO 639 is not a stable standard&mdash; some languages' codes have changed.
 212.713 +     * Locale's constructor recognizes both the new and the old codes for the languages
 212.714 +     * whose codes have changed, but this function always returns the old code.  If you
 212.715 +     * want to check for a specific language whose code has changed, don't do
 212.716 +     * <pre>
 212.717 +     * if (locale.getLanguage().equals("he")) // BAD!
 212.718 +     *    ...
 212.719 +     * </pre>
 212.720 +     * Instead, do
 212.721 +     * <pre>
 212.722 +     * if (locale.getLanguage().equals(new Locale("he").getLanguage()))
 212.723 +     *    ...
 212.724 +     * </pre>
 212.725 +     * @return The language code, or the empty string if none is defined.
 212.726 +     * @see #getDisplayLanguage
 212.727 +     */
 212.728 +    public String getLanguage() {
 212.729 +        return language;
 212.730 +    }
 212.731 +
 212.732 +    /**
 212.733 +     * Returns the script for this locale, which should
 212.734 +     * either be the empty string or an ISO 15924 4-letter script
 212.735 +     * code. The first letter is uppercase and the rest are
 212.736 +     * lowercase, for example, 'Latn', 'Cyrl'.
 212.737 +     *
 212.738 +     * @return The script code, or the empty string if none is defined.
 212.739 +     * @see #getDisplayScript
 212.740 +     * @since 1.7
 212.741 +     */
 212.742 +    public String getScript() {
 212.743 +        return "";
 212.744 +    }
 212.745 +
 212.746 +    /**
 212.747 +     * Returns the country/region code for this locale, which should
 212.748 +     * either be the empty string, an uppercase ISO 3166 2-letter code,
 212.749 +     * or a UN M.49 3-digit code.
 212.750 +     *
 212.751 +     * @return The country/region code, or the empty string if none is defined.
 212.752 +     * @see #getDisplayCountry
 212.753 +     */
 212.754 +    public String getCountry() {
 212.755 +        return country;
 212.756 +    }
 212.757 +
 212.758 +    /**
 212.759 +     * Returns the variant code for this locale.
 212.760 +     *
 212.761 +     * @return The variant code, or the empty string if none is defined.
 212.762 +     * @see #getDisplayVariant
 212.763 +     */
 212.764 +    public String getVariant() {
 212.765 +        return variant;
 212.766 +    }
 212.767 +    
 212.768 +    String getRegion() {
 212.769 +        return getCountry();
 212.770 +    }
 212.771 +
 212.772 +    /**
 212.773 +     * Returns the extension (or private use) value associated with
 212.774 +     * the specified key, or null if there is no extension
 212.775 +     * associated with the key. To be well-formed, the key must be one
 212.776 +     * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
 212.777 +     * for example 'z' and 'Z' represent the same extension.
 212.778 +     *
 212.779 +     * @param key the extension key
 212.780 +     * @return The extension, or null if this locale defines no
 212.781 +     * extension for the specified key.
 212.782 +     * @throws IllegalArgumentException if key is not well-formed
 212.783 +     * @see #PRIVATE_USE_EXTENSION
 212.784 +     * @see #UNICODE_LOCALE_EXTENSION
 212.785 +     * @since 1.7
 212.786 +     */
 212.787 +    public String getExtension(char key) {
 212.788 +        return null;
 212.789 +    }
 212.790 +
 212.791 +    /**
 212.792 +     * Returns the set of extension keys associated with this locale, or the
 212.793 +     * empty set if it has no extensions. The returned set is unmodifiable.
 212.794 +     * The keys will all be lower-case.
 212.795 +     *
 212.796 +     * @return The set of extension keys, or the empty set if this locale has
 212.797 +     * no extensions.
 212.798 +     * @since 1.7
 212.799 +     */
 212.800 +    public Set<Character> getExtensionKeys() {
 212.801 +        return Collections.emptySet();
 212.802 +    }
 212.803 +
 212.804 +    /**
 212.805 +     * Returns the set of unicode locale attributes associated with
 212.806 +     * this locale, or the empty set if it has no attributes. The
 212.807 +     * returned set is unmodifiable.
 212.808 +     *
 212.809 +     * @return The set of attributes.
 212.810 +     * @since 1.7
 212.811 +     */
 212.812 +    public Set<String> getUnicodeLocaleAttributes() {
 212.813 +        return Collections.emptySet();
 212.814 +    }
 212.815 +
 212.816 +    /**
 212.817 +     * Returns the Unicode locale type associated with the specified Unicode locale key
 212.818 +     * for this locale. Returns the empty string for keys that are defined with no type.
 212.819 +     * Returns null if the key is not defined. Keys are case-insensitive. The key must
 212.820 +     * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
 212.821 +     * thrown.
 212.822 +     *
 212.823 +     * @param key the Unicode locale key
 212.824 +     * @return The Unicode locale type associated with the key, or null if the
 212.825 +     * locale does not define the key.
 212.826 +     * @throws IllegalArgumentException if the key is not well-formed
 212.827 +     * @throws NullPointerException if <code>key</code> is null
 212.828 +     * @since 1.7
 212.829 +     */
 212.830 +    public String getUnicodeLocaleType(String key) {
 212.831 +        return null;
 212.832 +    }
 212.833 +
 212.834 +    /**
 212.835 +     * Returns the set of Unicode locale keys defined by this locale, or the empty set if
 212.836 +     * this locale has none.  The returned set is immutable.  Keys are all lower case.
 212.837 +     *
 212.838 +     * @return The set of Unicode locale keys, or the empty set if this locale has
 212.839 +     * no Unicode locale keywords.
 212.840 +     * @since 1.7
 212.841 +     */
 212.842 +    public Set<String> getUnicodeLocaleKeys() {
 212.843 +        return Collections.emptySet();
 212.844 +    }
 212.845 +
 212.846 +    /**
 212.847 +     * Returns a string representation of this <code>Locale</code>
 212.848 +     * object, consisting of language, country, variant, script,
 212.849 +     * and extensions as below:
 212.850 +     * <p><blockquote>
 212.851 +     * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
 212.852 +     * </blockquote>
 212.853 +     *
 212.854 +     * Language is always lower case, country is always upper case, script is always title
 212.855 +     * case, and extensions are always lower case.  Extensions and private use subtags
 212.856 +     * will be in canonical order as explained in {@link #toLanguageTag}.
 212.857 +     *
 212.858 +     * <p>When the locale has neither script nor extensions, the result is the same as in
 212.859 +     * Java 6 and prior.
 212.860 +     *
 212.861 +     * <p>If both the language and country fields are missing, this function will return
 212.862 +     * the empty string, even if the variant, script, or extensions field is present (you
 212.863 +     * can't have a locale with just a variant, the variant must accompany a well-formed
 212.864 +     * language or country code).
 212.865 +     *
 212.866 +     * <p>If script or extensions are present and variant is missing, no underscore is
 212.867 +     * added before the "#".
 212.868 +     *
 212.869 +     * <p>This behavior is designed to support debugging and to be compatible with
 212.870 +     * previous uses of <code>toString</code> that expected language, country, and variant
 212.871 +     * fields only.  To represent a Locale as a String for interchange purposes, use
 212.872 +     * {@link #toLanguageTag}.
 212.873 +     *
 212.874 +     * <p>Examples: <ul><tt>
 212.875 +     * <li>en
 212.876 +     * <li>de_DE
 212.877 +     * <li>_GB
 212.878 +     * <li>en_US_WIN
 212.879 +     * <li>de__POSIX
 212.880 +     * <li>zh_CN_#Hans
 212.881 +     * <li>zh_TW_#Hant-x-java
 212.882 +     * <li>th_TH_TH_#u-nu-thai</tt></ul>
 212.883 +     *
 212.884 +     * @return A string representation of the Locale, for debugging.
 212.885 +     * @see #getDisplayName
 212.886 +     * @see #toLanguageTag
 212.887 +     */
 212.888 +    @Override
 212.889 +    public final String toString() {
 212.890 +        Locale baseLocale = this;
 212.891 +        boolean l = (baseLocale.getLanguage().length() != 0);
 212.892 +        boolean s = (baseLocale.getScript().length() != 0);
 212.893 +        boolean r = (baseLocale.getRegion().length() != 0);
 212.894 +        boolean v = (baseLocale.getVariant().length() != 0);
 212.895 +        boolean e = false; //(localeExtensions != null && localeExtensions.getID().length() != 0);
 212.896 +
 212.897 +        StringBuilder result = new StringBuilder(baseLocale.getLanguage());
 212.898 +        if (r || (l && (v || s || e))) {
 212.899 +            result.append('_')
 212.900 +                .append(baseLocale.getRegion()); // This may just append '_'
 212.901 +        }
 212.902 +        if (v && (l || r)) {
 212.903 +            result.append('_')
 212.904 +                .append(baseLocale.getVariant());
 212.905 +        }
 212.906 +
 212.907 +        if (s && (l || r)) {
 212.908 +            result.append("_#")
 212.909 +                .append(baseLocale.getScript());
 212.910 +        }
 212.911 +
 212.912 +        if (e && (l || r)) {
 212.913 +            result.append('_');
 212.914 +            if (!s) {
 212.915 +                result.append('#');
 212.916 +            }
 212.917 +//            result.append(localeExtensions.getID());
 212.918 +        }
 212.919 +
 212.920 +        return result.toString();
 212.921 +    }
 212.922 +
 212.923 +    
 212.924 +    /**
 212.925 +     * Overrides Cloneable.
 212.926 +     */
 212.927 +    public Object clone()
 212.928 +    {
 212.929 +        try {
 212.930 +            Locale that = (Locale)super.clone();
 212.931 +            return that;
 212.932 +        } catch (CloneNotSupportedException e) {
 212.933 +            throw new InternalError();
 212.934 +        }
 212.935 +    }
 212.936 +
 212.937 +    /**
 212.938 +     * Override hashCode.
 212.939 +     * Since Locales are often used in hashtables, caches the value
 212.940 +     * for speed.
 212.941 +     */
 212.942 +    @Override
 212.943 +    public int hashCode() {
 212.944 +        int hash = 3;
 212.945 +        hash = 43 * hash + Objects.hashCode(this.language);
 212.946 +        hash = 43 * hash + Objects.hashCode(this.country);
 212.947 +        hash = 43 * hash + Objects.hashCode(this.variant);
 212.948 +        return hash;
 212.949 +    }
 212.950 +
 212.951 +    // Overrides
 212.952 +    @Override
 212.953 +    public boolean equals(Object obj) {
 212.954 +        if (obj == null) {
 212.955 +            return false;
 212.956 +        }
 212.957 +        if (getClass() != obj.getClass()) {
 212.958 +            return false;
 212.959 +        }
 212.960 +        final Locale other = (Locale) obj;
 212.961 +        if (!Objects.equals(this.language, other.language)) {
 212.962 +            return false;
 212.963 +        }
 212.964 +        if (!Objects.equals(this.country, other.country)) {
 212.965 +            return false;
 212.966 +        }
 212.967 +        if (!Objects.equals(this.variant, other.variant)) {
 212.968 +            return false;
 212.969 +        }
 212.970 +        return true;
 212.971 +    }
 212.972 +
 212.973 +    /**
 212.974 +     * Enum for locale categories.  These locale categories are used to get/set
 212.975 +     * the default locale for the specific functionality represented by the
 212.976 +     * category.
 212.977 +     *
 212.978 +     * @see #getDefault(Locale.Category)
 212.979 +     * @see #setDefault(Locale.Category, Locale)
 212.980 +     * @since 1.7
 212.981 +     */
 212.982 +    public enum Category {
 212.983 +
 212.984 +        /**
 212.985 +         * Category used to represent the default locale for
 212.986 +         * displaying user interfaces.
 212.987 +         */
 212.988 +        DISPLAY("user.language.display",
 212.989 +                "user.script.display",
 212.990 +                "user.country.display",
 212.991 +                "user.variant.display"),
 212.992 +
 212.993 +        /**
 212.994 +         * Category used to represent the default locale for
 212.995 +         * formatting dates, numbers, and/or currencies.
 212.996 +         */
 212.997 +        FORMAT("user.language.format",
 212.998 +               "user.script.format",
 212.999 +               "user.country.format",
212.1000 +               "user.variant.format");
212.1001 +
212.1002 +        Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
212.1003 +            this.languageKey = languageKey;
212.1004 +            this.scriptKey = scriptKey;
212.1005 +            this.countryKey = countryKey;
212.1006 +            this.variantKey = variantKey;
212.1007 +        }
212.1008 +
212.1009 +        final String languageKey;
212.1010 +        final String scriptKey;
212.1011 +        final String countryKey;
212.1012 +        final String variantKey;
212.1013 +    }
212.1014 +
212.1015 +}
   213.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   213.2 +++ b/rt/emul/compact/src/main/java/java/util/MissingResourceException.java	Wed Apr 30 15:04:10 2014 +0200
   213.3 @@ -0,0 +1,124 @@
   213.4 +/*
   213.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
   213.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   213.7 + *
   213.8 + * This code is free software; you can redistribute it and/or modify it
   213.9 + * under the terms of the GNU General Public License version 2 only, as
  213.10 + * published by the Free Software Foundation.  Oracle designates this
  213.11 + * particular file as subject to the "Classpath" exception as provided
  213.12 + * by Oracle in the LICENSE file that accompanied this code.
  213.13 + *
  213.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  213.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  213.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  213.17 + * version 2 for more details (a copy is included in the LICENSE file that
  213.18 + * accompanied this code).
  213.19 + *
  213.20 + * You should have received a copy of the GNU General Public License version
  213.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  213.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  213.23 + *
  213.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  213.25 + * or visit www.oracle.com if you need additional information or have any
  213.26 + * questions.
  213.27 + */
  213.28 +
  213.29 +/*
  213.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  213.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  213.32 + *
  213.33 + * The original version of this source code and documentation
  213.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
  213.35 + * subsidiary of IBM. These materials are provided under terms
  213.36 + * of a License Agreement between Taligent and Sun. This technology
  213.37 + * is protected by multiple US and International patents.
  213.38 + *
  213.39 + * This notice and attribution to Taligent may not be removed.
  213.40 + * Taligent is a registered trademark of Taligent, Inc.
  213.41 + *
  213.42 + */
  213.43 +
  213.44 +package java.util;
  213.45 +
  213.46 +/**
  213.47 + * Signals that a resource is missing.
  213.48 + * @see java.lang.Exception
  213.49 + * @see ResourceBundle
  213.50 + * @author      Mark Davis
  213.51 + * @since       JDK1.1
  213.52 + */
  213.53 +public
  213.54 +class MissingResourceException extends RuntimeException {
  213.55 +
  213.56 +    /**
  213.57 +     * Constructs a MissingResourceException with the specified information.
  213.58 +     * A detail message is a String that describes this particular exception.
  213.59 +     * @param s the detail message
  213.60 +     * @param className the name of the resource class
  213.61 +     * @param key the key for the missing resource.
  213.62 +     */
  213.63 +    public MissingResourceException(String s, String className, String key) {
  213.64 +        super(s);
  213.65 +        this.className = className;
  213.66 +        this.key = key;
  213.67 +    }
  213.68 +
  213.69 +    /**
  213.70 +     * Constructs a <code>MissingResourceException</code> with
  213.71 +     * <code>message</code>, <code>className</code>, <code>key</code>,
  213.72 +     * and <code>cause</code>. This constructor is package private for
  213.73 +     * use by <code>ResourceBundle.getBundle</code>.
  213.74 +     *
  213.75 +     * @param message
  213.76 +     *        the detail message
  213.77 +     * @param className
  213.78 +     *        the name of the resource class
  213.79 +     * @param key
  213.80 +     *        the key for the missing resource.
  213.81 +     * @param cause
  213.82 +     *        the cause (which is saved for later retrieval by the
  213.83 +     *        {@link Throwable.getCause()} method). (A null value is
  213.84 +     *        permitted, and indicates that the cause is nonexistent
  213.85 +     *        or unknown.)
  213.86 +     */
  213.87 +    MissingResourceException(String message, String className, String key, Throwable cause) {
  213.88 +        super(message, cause);
  213.89 +        this.className = className;
  213.90 +        this.key = key;
  213.91 +    }
  213.92 +
  213.93 +    /**
  213.94 +     * Gets parameter passed by constructor.
  213.95 +     *
  213.96 +     * @return the name of the resource class
  213.97 +     */
  213.98 +    public String getClassName() {
  213.99 +        return className;
 213.100 +    }
 213.101 +
 213.102 +    /**
 213.103 +     * Gets parameter passed by constructor.
 213.104 +     *
 213.105 +     * @return the key for the missing resource
 213.106 +     */
 213.107 +    public String getKey() {
 213.108 +        return key;
 213.109 +    }
 213.110 +
 213.111 +    //============ privates ============
 213.112 +
 213.113 +    // serialization compatibility with JDK1.1
 213.114 +    private static final long serialVersionUID = -4876345176062000401L;
 213.115 +
 213.116 +    /**
 213.117 +     * The class name of the resource bundle requested by the user.
 213.118 +     * @serial
 213.119 +     */
 213.120 +    private String className;
 213.121 +
 213.122 +    /**
 213.123 +     * The name of the specific resource requested by the user.
 213.124 +     * @serial
 213.125 +     */
 213.126 +    private String key;
 213.127 +}
   214.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   214.2 +++ b/rt/emul/compact/src/main/java/java/util/NavigableMap.java	Wed Apr 30 15:04:10 2014 +0200
   214.3 @@ -0,0 +1,424 @@
   214.4 +/*
   214.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   214.6 + *
   214.7 + * This code is free software; you can redistribute it and/or modify it
   214.8 + * under the terms of the GNU General Public License version 2 only, as
   214.9 + * published by the Free Software Foundation.  Oracle designates this
  214.10 + * particular file as subject to the "Classpath" exception as provided
  214.11 + * by Oracle in the LICENSE file that accompanied this code.
  214.12 + *
  214.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  214.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  214.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  214.16 + * version 2 for more details (a copy is included in the LICENSE file that
  214.17 + * accompanied this code).
  214.18 + *
  214.19 + * You should have received a copy of the GNU General Public License version
  214.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  214.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  214.22 + *
  214.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  214.24 + * or visit www.oracle.com if you need additional information or have any
  214.25 + * questions.
  214.26 + */
  214.27 +
  214.28 +/*
  214.29 + * This file is available under and governed by the GNU General Public
  214.30 + * License version 2 only, as published by the Free Software Foundation.
  214.31 + * However, the following notice accompanied the original version of this
  214.32 + * file:
  214.33 + *
  214.34 + * Written by Doug Lea and Josh Bloch with assistance from members of JCP
  214.35 + * JSR-166 Expert Group and released to the public domain, as explained at
  214.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  214.37 + */
  214.38 +
  214.39 +package java.util;
  214.40 +
  214.41 +/**
  214.42 + * A {@link SortedMap} extended with navigation methods returning the
  214.43 + * closest matches for given search targets. Methods
  214.44 + * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
  214.45 + * and {@code higherEntry} return {@code Map.Entry} objects
  214.46 + * associated with keys respectively less than, less than or equal,
  214.47 + * greater than or equal, and greater than a given key, returning
  214.48 + * {@code null} if there is no such key.  Similarly, methods
  214.49 + * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
  214.50 + * {@code higherKey} return only the associated keys. All of these
  214.51 + * methods are designed for locating, not traversing entries.
  214.52 + *
  214.53 + * <p>A {@code NavigableMap} may be accessed and traversed in either
  214.54 + * ascending or descending key order.  The {@code descendingMap}
  214.55 + * method returns a view of the map with the senses of all relational
  214.56 + * and directional methods inverted. The performance of ascending
  214.57 + * operations and views is likely to be faster than that of descending
  214.58 + * ones.  Methods {@code subMap}, {@code headMap},
  214.59 + * and {@code tailMap} differ from the like-named {@code
  214.60 + * SortedMap} methods in accepting additional arguments describing
  214.61 + * whether lower and upper bounds are inclusive versus exclusive.
  214.62 + * Submaps of any {@code NavigableMap} must implement the {@code
  214.63 + * NavigableMap} interface.
  214.64 + *
  214.65 + * <p>This interface additionally defines methods {@code firstEntry},
  214.66 + * {@code pollFirstEntry}, {@code lastEntry}, and
  214.67 + * {@code pollLastEntry} that return and/or remove the least and
  214.68 + * greatest mappings, if any exist, else returning {@code null}.
  214.69 + *
  214.70 + * <p>Implementations of entry-returning methods are expected to
  214.71 + * return {@code Map.Entry} pairs representing snapshots of mappings
  214.72 + * at the time they were produced, and thus generally do <em>not</em>
  214.73 + * support the optional {@code Entry.setValue} method. Note however
  214.74 + * that it is possible to change mappings in the associated map using
  214.75 + * method {@code put}.
  214.76 + *
  214.77 + * <p>Methods
  214.78 + * {@link #subMap(Object, Object) subMap(K, K)},
  214.79 + * {@link #headMap(Object) headMap(K)}, and
  214.80 + * {@link #tailMap(Object) tailMap(K)}
  214.81 + * are specified to return {@code SortedMap} to allow existing
  214.82 + * implementations of {@code SortedMap} to be compatibly retrofitted to
  214.83 + * implement {@code NavigableMap}, but extensions and implementations
  214.84 + * of this interface are encouraged to override these methods to return
  214.85 + * {@code NavigableMap}.  Similarly,
  214.86 + * {@link #keySet()} can be overriden to return {@code NavigableSet}.
  214.87 + *
  214.88 + * <p>This interface is a member of the
  214.89 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  214.90 + * Java Collections Framework</a>.
  214.91 + *
  214.92 + * @author Doug Lea
  214.93 + * @author Josh Bloch
  214.94 + * @param <K> the type of keys maintained by this map
  214.95 + * @param <V> the type of mapped values
  214.96 + * @since 1.6
  214.97 + */
  214.98 +public interface NavigableMap<K,V> extends SortedMap<K,V> {
  214.99 +    /**
 214.100 +     * Returns a key-value mapping associated with the greatest key
 214.101 +     * strictly less than the given key, or {@code null} if there is
 214.102 +     * no such key.
 214.103 +     *
 214.104 +     * @param key the key
 214.105 +     * @return an entry with the greatest key less than {@code key},
 214.106 +     *         or {@code null} if there is no such key
 214.107 +     * @throws ClassCastException if the specified key cannot be compared
 214.108 +     *         with the keys currently in the map
 214.109 +     * @throws NullPointerException if the specified key is null
 214.110 +     *         and this map does not permit null keys
 214.111 +     */
 214.112 +    Map.Entry<K,V> lowerEntry(K key);
 214.113 +
 214.114 +    /**
 214.115 +     * Returns the greatest key strictly less than the given key, or
 214.116 +     * {@code null} if there is no such key.
 214.117 +     *
 214.118 +     * @param key the key
 214.119 +     * @return the greatest key less than {@code key},
 214.120 +     *         or {@code null} if there is no such key
 214.121 +     * @throws ClassCastException if the specified key cannot be compared
 214.122 +     *         with the keys currently in the map
 214.123 +     * @throws NullPointerException if the specified key is null
 214.124 +     *         and this map does not permit null keys
 214.125 +     */
 214.126 +    K lowerKey(K key);
 214.127 +
 214.128 +    /**
 214.129 +     * Returns a key-value mapping associated with the greatest key
 214.130 +     * less than or equal to the given key, or {@code null} if there
 214.131 +     * is no such key.
 214.132 +     *
 214.133 +     * @param key the key
 214.134 +     * @return an entry with the greatest key less than or equal to
 214.135 +     *         {@code key}, or {@code null} if there is no such key
 214.136 +     * @throws ClassCastException if the specified key cannot be compared
 214.137 +     *         with the keys currently in the map
 214.138 +     * @throws NullPointerException if the specified key is null
 214.139 +     *         and this map does not permit null keys
 214.140 +     */
 214.141 +    Map.Entry<K,V> floorEntry(K key);
 214.142 +
 214.143 +    /**
 214.144 +     * Returns the greatest key less than or equal to the given key,
 214.145 +     * or {@code null} if there is no such key.
 214.146 +     *
 214.147 +     * @param key the key
 214.148 +     * @return the greatest key less than or equal to {@code key},
 214.149 +     *         or {@code null} if there is no such key
 214.150 +     * @throws ClassCastException if the specified key cannot be compared
 214.151 +     *         with the keys currently in the map
 214.152 +     * @throws NullPointerException if the specified key is null
 214.153 +     *         and this map does not permit null keys
 214.154 +     */
 214.155 +    K floorKey(K key);
 214.156 +
 214.157 +    /**
 214.158 +     * Returns a key-value mapping associated with the least key
 214.159 +     * greater than or equal to the given key, or {@code null} if
 214.160 +     * there is no such key.
 214.161 +     *
 214.162 +     * @param key the key
 214.163 +     * @return an entry with the least key greater than or equal to
 214.164 +     *         {@code key}, or {@code null} if there is no such key
 214.165 +     * @throws ClassCastException if the specified key cannot be compared
 214.166 +     *         with the keys currently in the map
 214.167 +     * @throws NullPointerException if the specified key is null
 214.168 +     *         and this map does not permit null keys
 214.169 +     */
 214.170 +    Map.Entry<K,V> ceilingEntry(K key);
 214.171 +
 214.172 +    /**
 214.173 +     * Returns the least key greater than or equal to the given key,
 214.174 +     * or {@code null} if there is no such key.
 214.175 +     *
 214.176 +     * @param key the key
 214.177 +     * @return the least key greater than or equal to {@code key},
 214.178 +     *         or {@code null} if there is no such key
 214.179 +     * @throws ClassCastException if the specified key cannot be compared
 214.180 +     *         with the keys currently in the map
 214.181 +     * @throws NullPointerException if the specified key is null
 214.182 +     *         and this map does not permit null keys
 214.183 +     */
 214.184 +    K ceilingKey(K key);
 214.185 +
 214.186 +    /**
 214.187 +     * Returns a key-value mapping associated with the least key
 214.188 +     * strictly greater than the given key, or {@code null} if there
 214.189 +     * is no such key.
 214.190 +     *
 214.191 +     * @param key the key
 214.192 +     * @return an entry with the least key greater than {@code key},
 214.193 +     *         or {@code null} if there is no such key
 214.194 +     * @throws ClassCastException if the specified key cannot be compared
 214.195 +     *         with the keys currently in the map
 214.196 +     * @throws NullPointerException if the specified key is null
 214.197 +     *         and this map does not permit null keys
 214.198 +     */
 214.199 +    Map.Entry<K,V> higherEntry(K key);
 214.200 +
 214.201 +    /**
 214.202 +     * Returns the least key strictly greater than the given key, or
 214.203 +     * {@code null} if there is no such key.
 214.204 +     *
 214.205 +     * @param key the key
 214.206 +     * @return the least key greater than {@code key},
 214.207 +     *         or {@code null} if there is no such key
 214.208 +     * @throws ClassCastException if the specified key cannot be compared
 214.209 +     *         with the keys currently in the map
 214.210 +     * @throws NullPointerException if the specified key is null
 214.211 +     *         and this map does not permit null keys
 214.212 +     */
 214.213 +    K higherKey(K key);
 214.214 +
 214.215 +    /**
 214.216 +     * Returns a key-value mapping associated with the least
 214.217 +     * key in this map, or {@code null} if the map is empty.
 214.218 +     *
 214.219 +     * @return an entry with the least key,
 214.220 +     *         or {@code null} if this map is empty
 214.221 +     */
 214.222 +    Map.Entry<K,V> firstEntry();
 214.223 +
 214.224 +    /**
 214.225 +     * Returns a key-value mapping associated with the greatest
 214.226 +     * key in this map, or {@code null} if the map is empty.
 214.227 +     *
 214.228 +     * @return an entry with the greatest key,
 214.229 +     *         or {@code null} if this map is empty
 214.230 +     */
 214.231 +    Map.Entry<K,V> lastEntry();
 214.232 +
 214.233 +    /**
 214.234 +     * Removes and returns a key-value mapping associated with
 214.235 +     * the least key in this map, or {@code null} if the map is empty.
 214.236 +     *
 214.237 +     * @return the removed first entry of this map,
 214.238 +     *         or {@code null} if this map is empty
 214.239 +     */
 214.240 +    Map.Entry<K,V> pollFirstEntry();
 214.241 +
 214.242 +    /**
 214.243 +     * Removes and returns a key-value mapping associated with
 214.244 +     * the greatest key in this map, or {@code null} if the map is empty.
 214.245 +     *
 214.246 +     * @return the removed last entry of this map,
 214.247 +     *         or {@code null} if this map is empty
 214.248 +     */
 214.249 +    Map.Entry<K,V> pollLastEntry();
 214.250 +
 214.251 +    /**
 214.252 +     * Returns a reverse order view of the mappings contained in this map.
 214.253 +     * The descending map is backed by this map, so changes to the map are
 214.254 +     * reflected in the descending map, and vice-versa.  If either map is
 214.255 +     * modified while an iteration over a collection view of either map
 214.256 +     * is in progress (except through the iterator's own {@code remove}
 214.257 +     * operation), the results of the iteration are undefined.
 214.258 +     *
 214.259 +     * <p>The returned map has an ordering equivalent to
 214.260 +     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
 214.261 +     * The expression {@code m.descendingMap().descendingMap()} returns a
 214.262 +     * view of {@code m} essentially equivalent to {@code m}.
 214.263 +     *
 214.264 +     * @return a reverse order view of this map
 214.265 +     */
 214.266 +    NavigableMap<K,V> descendingMap();
 214.267 +
 214.268 +    /**
 214.269 +     * Returns a {@link NavigableSet} view of the keys contained in this map.
 214.270 +     * The set's iterator returns the keys in ascending order.
 214.271 +     * The set is backed by the map, so changes to the map are reflected in
 214.272 +     * the set, and vice-versa.  If the map is modified while an iteration
 214.273 +     * over the set is in progress (except through the iterator's own {@code
 214.274 +     * remove} operation), the results of the iteration are undefined.  The
 214.275 +     * set supports element removal, which removes the corresponding mapping
 214.276 +     * from the map, via the {@code Iterator.remove}, {@code Set.remove},
 214.277 +     * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
 214.278 +     * It does not support the {@code add} or {@code addAll} operations.
 214.279 +     *
 214.280 +     * @return a navigable set view of the keys in this map
 214.281 +     */
 214.282 +    NavigableSet<K> navigableKeySet();
 214.283 +
 214.284 +    /**
 214.285 +     * Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
 214.286 +     * The set's iterator returns the keys in descending order.
 214.287 +     * The set is backed by the map, so changes to the map are reflected in
 214.288 +     * the set, and vice-versa.  If the map is modified while an iteration
 214.289 +     * over the set is in progress (except through the iterator's own {@code
 214.290 +     * remove} operation), the results of the iteration are undefined.  The
 214.291 +     * set supports element removal, which removes the corresponding mapping
 214.292 +     * from the map, via the {@code Iterator.remove}, {@code Set.remove},
 214.293 +     * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
 214.294 +     * It does not support the {@code add} or {@code addAll} operations.
 214.295 +     *
 214.296 +     * @return a reverse order navigable set view of the keys in this map
 214.297 +     */
 214.298 +    NavigableSet<K> descendingKeySet();
 214.299 +
 214.300 +    /**
 214.301 +     * Returns a view of the portion of this map whose keys range from
 214.302 +     * {@code fromKey} to {@code toKey}.  If {@code fromKey} and
 214.303 +     * {@code toKey} are equal, the returned map is empty unless
 214.304 +     * {@code fromInclusive} and {@code toInclusive} are both true.  The
 214.305 +     * returned map is backed by this map, so changes in the returned map are
 214.306 +     * reflected in this map, and vice-versa.  The returned map supports all
 214.307 +     * optional map operations that this map supports.
 214.308 +     *
 214.309 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 214.310 +     * on an attempt to insert a key outside of its range, or to construct a
 214.311 +     * submap either of whose endpoints lie outside its range.
 214.312 +     *
 214.313 +     * @param fromKey low endpoint of the keys in the returned map
 214.314 +     * @param fromInclusive {@code true} if the low endpoint
 214.315 +     *        is to be included in the returned view
 214.316 +     * @param toKey high endpoint of the keys in the returned map
 214.317 +     * @param toInclusive {@code true} if the high endpoint
 214.318 +     *        is to be included in the returned view
 214.319 +     * @return a view of the portion of this map whose keys range from
 214.320 +     *         {@code fromKey} to {@code toKey}
 214.321 +     * @throws ClassCastException if {@code fromKey} and {@code toKey}
 214.322 +     *         cannot be compared to one another using this map's comparator
 214.323 +     *         (or, if the map has no comparator, using natural ordering).
 214.324 +     *         Implementations may, but are not required to, throw this
 214.325 +     *         exception if {@code fromKey} or {@code toKey}
 214.326 +     *         cannot be compared to keys currently in the map.
 214.327 +     * @throws NullPointerException if {@code fromKey} or {@code toKey}
 214.328 +     *         is null and this map does not permit null keys
 214.329 +     * @throws IllegalArgumentException if {@code fromKey} is greater than
 214.330 +     *         {@code toKey}; or if this map itself has a restricted
 214.331 +     *         range, and {@code fromKey} or {@code toKey} lies
 214.332 +     *         outside the bounds of the range
 214.333 +     */
 214.334 +    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
 214.335 +                             K toKey,   boolean toInclusive);
 214.336 +
 214.337 +    /**
 214.338 +     * Returns a view of the portion of this map whose keys are less than (or
 214.339 +     * equal to, if {@code inclusive} is true) {@code toKey}.  The returned
 214.340 +     * map is backed by this map, so changes in the returned map are reflected
 214.341 +     * in this map, and vice-versa.  The returned map supports all optional
 214.342 +     * map operations that this map supports.
 214.343 +     *
 214.344 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 214.345 +     * on an attempt to insert a key outside its range.
 214.346 +     *
 214.347 +     * @param toKey high endpoint of the keys in the returned map
 214.348 +     * @param inclusive {@code true} if the high endpoint
 214.349 +     *        is to be included in the returned view
 214.350 +     * @return a view of the portion of this map whose keys are less than
 214.351 +     *         (or equal to, if {@code inclusive} is true) {@code toKey}
 214.352 +     * @throws ClassCastException if {@code toKey} is not compatible
 214.353 +     *         with this map's comparator (or, if the map has no comparator,
 214.354 +     *         if {@code toKey} does not implement {@link Comparable}).
 214.355 +     *         Implementations may, but are not required to, throw this
 214.356 +     *         exception if {@code toKey} cannot be compared to keys
 214.357 +     *         currently in the map.
 214.358 +     * @throws NullPointerException if {@code toKey} is null
 214.359 +     *         and this map does not permit null keys
 214.360 +     * @throws IllegalArgumentException if this map itself has a
 214.361 +     *         restricted range, and {@code toKey} lies outside the
 214.362 +     *         bounds of the range
 214.363 +     */
 214.364 +    NavigableMap<K,V> headMap(K toKey, boolean inclusive);
 214.365 +
 214.366 +    /**
 214.367 +     * Returns a view of the portion of this map whose keys are greater than (or
 214.368 +     * equal to, if {@code inclusive} is true) {@code fromKey}.  The returned
 214.369 +     * map is backed by this map, so changes in the returned map are reflected
 214.370 +     * in this map, and vice-versa.  The returned map supports all optional
 214.371 +     * map operations that this map supports.
 214.372 +     *
 214.373 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 214.374 +     * on an attempt to insert a key outside its range.
 214.375 +     *
 214.376 +     * @param fromKey low endpoint of the keys in the returned map
 214.377 +     * @param inclusive {@code true} if the low endpoint
 214.378 +     *        is to be included in the returned view
 214.379 +     * @return a view of the portion of this map whose keys are greater than
 214.380 +     *         (or equal to, if {@code inclusive} is true) {@code fromKey}
 214.381 +     * @throws ClassCastException if {@code fromKey} is not compatible
 214.382 +     *         with this map's comparator (or, if the map has no comparator,
 214.383 +     *         if {@code fromKey} does not implement {@link Comparable}).
 214.384 +     *         Implementations may, but are not required to, throw this
 214.385 +     *         exception if {@code fromKey} cannot be compared to keys
 214.386 +     *         currently in the map.
 214.387 +     * @throws NullPointerException if {@code fromKey} is null
 214.388 +     *         and this map does not permit null keys
 214.389 +     * @throws IllegalArgumentException if this map itself has a
 214.390 +     *         restricted range, and {@code fromKey} lies outside the
 214.391 +     *         bounds of the range
 214.392 +     */
 214.393 +    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
 214.394 +
 214.395 +    /**
 214.396 +     * {@inheritDoc}
 214.397 +     *
 214.398 +     * <p>Equivalent to {@code subMap(fromKey, true, toKey, false)}.
 214.399 +     *
 214.400 +     * @throws ClassCastException       {@inheritDoc}
 214.401 +     * @throws NullPointerException     {@inheritDoc}
 214.402 +     * @throws IllegalArgumentException {@inheritDoc}
 214.403 +     */
 214.404 +    SortedMap<K,V> subMap(K fromKey, K toKey);
 214.405 +
 214.406 +    /**
 214.407 +     * {@inheritDoc}
 214.408 +     *
 214.409 +     * <p>Equivalent to {@code headMap(toKey, false)}.
 214.410 +     *
 214.411 +     * @throws ClassCastException       {@inheritDoc}
 214.412 +     * @throws NullPointerException     {@inheritDoc}
 214.413 +     * @throws IllegalArgumentException {@inheritDoc}
 214.414 +     */
 214.415 +    SortedMap<K,V> headMap(K toKey);
 214.416 +
 214.417 +    /**
 214.418 +     * {@inheritDoc}
 214.419 +     *
 214.420 +     * <p>Equivalent to {@code tailMap(fromKey, true)}.
 214.421 +     *
 214.422 +     * @throws ClassCastException       {@inheritDoc}
 214.423 +     * @throws NullPointerException     {@inheritDoc}
 214.424 +     * @throws IllegalArgumentException {@inheritDoc}
 214.425 +     */
 214.426 +    SortedMap<K,V> tailMap(K fromKey);
 214.427 +}
   215.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   215.2 +++ b/rt/emul/compact/src/main/java/java/util/NavigableSet.java	Wed Apr 30 15:04:10 2014 +0200
   215.3 @@ -0,0 +1,319 @@
   215.4 +/*
   215.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   215.6 + *
   215.7 + * This code is free software; you can redistribute it and/or modify it
   215.8 + * under the terms of the GNU General Public License version 2 only, as
   215.9 + * published by the Free Software Foundation.  Oracle designates this
  215.10 + * particular file as subject to the "Classpath" exception as provided
  215.11 + * by Oracle in the LICENSE file that accompanied this code.
  215.12 + *
  215.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  215.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  215.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  215.16 + * version 2 for more details (a copy is included in the LICENSE file that
  215.17 + * accompanied this code).
  215.18 + *
  215.19 + * You should have received a copy of the GNU General Public License version
  215.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  215.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  215.22 + *
  215.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  215.24 + * or visit www.oracle.com if you need additional information or have any
  215.25 + * questions.
  215.26 + */
  215.27 +
  215.28 +/*
  215.29 + * This file is available under and governed by the GNU General Public
  215.30 + * License version 2 only, as published by the Free Software Foundation.
  215.31 + * However, the following notice accompanied the original version of this
  215.32 + * file:
  215.33 + *
  215.34 + * Written by Doug Lea and Josh Bloch with assistance from members of JCP
  215.35 + * JSR-166 Expert Group and released to the public domain, as explained at
  215.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  215.37 + */
  215.38 +
  215.39 +package java.util;
  215.40 +
  215.41 +/**
  215.42 + * A {@link SortedSet} extended with navigation methods reporting
  215.43 + * closest matches for given search targets. Methods {@code lower},
  215.44 + * {@code floor}, {@code ceiling}, and {@code higher} return elements
  215.45 + * respectively less than, less than or equal, greater than or equal,
  215.46 + * and greater than a given element, returning {@code null} if there
  215.47 + * is no such element.  A {@code NavigableSet} may be accessed and
  215.48 + * traversed in either ascending or descending order.  The {@code
  215.49 + * descendingSet} method returns a view of the set with the senses of
  215.50 + * all relational and directional methods inverted. The performance of
  215.51 + * ascending operations and views is likely to be faster than that of
  215.52 + * descending ones.  This interface additionally defines methods
  215.53 + * {@code pollFirst} and {@code pollLast} that return and remove the
  215.54 + * lowest and highest element, if one exists, else returning {@code
  215.55 + * null}.  Methods {@code subSet}, {@code headSet},
  215.56 + * and {@code tailSet} differ from the like-named {@code
  215.57 + * SortedSet} methods in accepting additional arguments describing
  215.58 + * whether lower and upper bounds are inclusive versus exclusive.
  215.59 + * Subsets of any {@code NavigableSet} must implement the {@code
  215.60 + * NavigableSet} interface.
  215.61 + *
  215.62 + * <p> The return values of navigation methods may be ambiguous in
  215.63 + * implementations that permit {@code null} elements. However, even
  215.64 + * in this case the result can be disambiguated by checking
  215.65 + * {@code contains(null)}. To avoid such issues, implementations of
  215.66 + * this interface are encouraged to <em>not</em> permit insertion of
  215.67 + * {@code null} elements. (Note that sorted sets of {@link
  215.68 + * Comparable} elements intrinsically do not permit {@code null}.)
  215.69 + *
  215.70 + * <p>Methods
  215.71 + * {@link #subSet(Object, Object) subSet(E, E)},
  215.72 + * {@link #headSet(Object) headSet(E)}, and
  215.73 + * {@link #tailSet(Object) tailSet(E)}
  215.74 + * are specified to return {@code SortedSet} to allow existing
  215.75 + * implementations of {@code SortedSet} to be compatibly retrofitted to
  215.76 + * implement {@code NavigableSet}, but extensions and implementations
  215.77 + * of this interface are encouraged to override these methods to return
  215.78 + * {@code NavigableSet}.
  215.79 + *
  215.80 + * <p>This interface is a member of the
  215.81 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  215.82 + * Java Collections Framework</a>.
  215.83 + *
  215.84 + * @author Doug Lea
  215.85 + * @author Josh Bloch
  215.86 + * @param <E> the type of elements maintained by this set
  215.87 + * @since 1.6
  215.88 + */
  215.89 +public interface NavigableSet<E> extends SortedSet<E> {
  215.90 +    /**
  215.91 +     * Returns the greatest element in this set strictly less than the
  215.92 +     * given element, or {@code null} if there is no such element.
  215.93 +     *
  215.94 +     * @param e the value to match
  215.95 +     * @return the greatest element less than {@code e},
  215.96 +     *         or {@code null} if there is no such element
  215.97 +     * @throws ClassCastException if the specified element cannot be
  215.98 +     *         compared with the elements currently in the set
  215.99 +     * @throws NullPointerException if the specified element is null
 215.100 +     *         and this set does not permit null elements
 215.101 +     */
 215.102 +    E lower(E e);
 215.103 +
 215.104 +    /**
 215.105 +     * Returns the greatest element in this set less than or equal to
 215.106 +     * the given element, or {@code null} if there is no such element.
 215.107 +     *
 215.108 +     * @param e the value to match
 215.109 +     * @return the greatest element less than or equal to {@code e},
 215.110 +     *         or {@code null} if there is no such element
 215.111 +     * @throws ClassCastException if the specified element cannot be
 215.112 +     *         compared with the elements currently in the set
 215.113 +     * @throws NullPointerException if the specified element is null
 215.114 +     *         and this set does not permit null elements
 215.115 +     */
 215.116 +    E floor(E e);
 215.117 +
 215.118 +    /**
 215.119 +     * Returns the least element in this set greater than or equal to
 215.120 +     * the given element, or {@code null} if there is no such element.
 215.121 +     *
 215.122 +     * @param e the value to match
 215.123 +     * @return the least element greater than or equal to {@code e},
 215.124 +     *         or {@code null} if there is no such element
 215.125 +     * @throws ClassCastException if the specified element cannot be
 215.126 +     *         compared with the elements currently in the set
 215.127 +     * @throws NullPointerException if the specified element is null
 215.128 +     *         and this set does not permit null elements
 215.129 +     */
 215.130 +    E ceiling(E e);
 215.131 +
 215.132 +    /**
 215.133 +     * Returns the least element in this set strictly greater than the
 215.134 +     * given element, or {@code null} if there is no such element.
 215.135 +     *
 215.136 +     * @param e the value to match
 215.137 +     * @return the least element greater than {@code e},
 215.138 +     *         or {@code null} if there is no such element
 215.139 +     * @throws ClassCastException if the specified element cannot be
 215.140 +     *         compared with the elements currently in the set
 215.141 +     * @throws NullPointerException if the specified element is null
 215.142 +     *         and this set does not permit null elements
 215.143 +     */
 215.144 +    E higher(E e);
 215.145 +
 215.146 +    /**
 215.147 +     * Retrieves and removes the first (lowest) element,
 215.148 +     * or returns {@code null} if this set is empty.
 215.149 +     *
 215.150 +     * @return the first element, or {@code null} if this set is empty
 215.151 +     */
 215.152 +    E pollFirst();
 215.153 +
 215.154 +    /**
 215.155 +     * Retrieves and removes the last (highest) element,
 215.156 +     * or returns {@code null} if this set is empty.
 215.157 +     *
 215.158 +     * @return the last element, or {@code null} if this set is empty
 215.159 +     */
 215.160 +    E pollLast();
 215.161 +
 215.162 +    /**
 215.163 +     * Returns an iterator over the elements in this set, in ascending order.
 215.164 +     *
 215.165 +     * @return an iterator over the elements in this set, in ascending order
 215.166 +     */
 215.167 +    Iterator<E> iterator();
 215.168 +
 215.169 +    /**
 215.170 +     * Returns a reverse order view of the elements contained in this set.
 215.171 +     * The descending set is backed by this set, so changes to the set are
 215.172 +     * reflected in the descending set, and vice-versa.  If either set is
 215.173 +     * modified while an iteration over either set is in progress (except
 215.174 +     * through the iterator's own {@code remove} operation), the results of
 215.175 +     * the iteration are undefined.
 215.176 +     *
 215.177 +     * <p>The returned set has an ordering equivalent to
 215.178 +     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
 215.179 +     * The expression {@code s.descendingSet().descendingSet()} returns a
 215.180 +     * view of {@code s} essentially equivalent to {@code s}.
 215.181 +     *
 215.182 +     * @return a reverse order view of this set
 215.183 +     */
 215.184 +    NavigableSet<E> descendingSet();
 215.185 +
 215.186 +    /**
 215.187 +     * Returns an iterator over the elements in this set, in descending order.
 215.188 +     * Equivalent in effect to {@code descendingSet().iterator()}.
 215.189 +     *
 215.190 +     * @return an iterator over the elements in this set, in descending order
 215.191 +     */
 215.192 +    Iterator<E> descendingIterator();
 215.193 +
 215.194 +    /**
 215.195 +     * Returns a view of the portion of this set whose elements range from
 215.196 +     * {@code fromElement} to {@code toElement}.  If {@code fromElement} and
 215.197 +     * {@code toElement} are equal, the returned set is empty unless {@code
 215.198 +     * fromInclusive} and {@code toInclusive} are both true.  The returned set
 215.199 +     * is backed by this set, so changes in the returned set are reflected in
 215.200 +     * this set, and vice-versa.  The returned set supports all optional set
 215.201 +     * operations that this set supports.
 215.202 +     *
 215.203 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 215.204 +     * on an attempt to insert an element outside its range.
 215.205 +     *
 215.206 +     * @param fromElement low endpoint of the returned set
 215.207 +     * @param fromInclusive {@code true} if the low endpoint
 215.208 +     *        is to be included in the returned view
 215.209 +     * @param toElement high endpoint of the returned set
 215.210 +     * @param toInclusive {@code true} if the high endpoint
 215.211 +     *        is to be included in the returned view
 215.212 +     * @return a view of the portion of this set whose elements range from
 215.213 +     *         {@code fromElement}, inclusive, to {@code toElement}, exclusive
 215.214 +     * @throws ClassCastException if {@code fromElement} and
 215.215 +     *         {@code toElement} cannot be compared to one another using this
 215.216 +     *         set's comparator (or, if the set has no comparator, using
 215.217 +     *         natural ordering).  Implementations may, but are not required
 215.218 +     *         to, throw this exception if {@code fromElement} or
 215.219 +     *         {@code toElement} cannot be compared to elements currently in
 215.220 +     *         the set.
 215.221 +     * @throws NullPointerException if {@code fromElement} or
 215.222 +     *         {@code toElement} is null and this set does
 215.223 +     *         not permit null elements
 215.224 +     * @throws IllegalArgumentException if {@code fromElement} is
 215.225 +     *         greater than {@code toElement}; or if this set itself
 215.226 +     *         has a restricted range, and {@code fromElement} or
 215.227 +     *         {@code toElement} lies outside the bounds of the range.
 215.228 +     */
 215.229 +    NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
 215.230 +                           E toElement,   boolean toInclusive);
 215.231 +
 215.232 +    /**
 215.233 +     * Returns a view of the portion of this set whose elements are less than
 215.234 +     * (or equal to, if {@code inclusive} is true) {@code toElement}.  The
 215.235 +     * returned set is backed by this set, so changes in the returned set are
 215.236 +     * reflected in this set, and vice-versa.  The returned set supports all
 215.237 +     * optional set operations that this set supports.
 215.238 +     *
 215.239 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 215.240 +     * on an attempt to insert an element outside its range.
 215.241 +     *
 215.242 +     * @param toElement high endpoint of the returned set
 215.243 +     * @param inclusive {@code true} if the high endpoint
 215.244 +     *        is to be included in the returned view
 215.245 +     * @return a view of the portion of this set whose elements are less than
 215.246 +     *         (or equal to, if {@code inclusive} is true) {@code toElement}
 215.247 +     * @throws ClassCastException if {@code toElement} is not compatible
 215.248 +     *         with this set's comparator (or, if the set has no comparator,
 215.249 +     *         if {@code toElement} does not implement {@link Comparable}).
 215.250 +     *         Implementations may, but are not required to, throw this
 215.251 +     *         exception if {@code toElement} cannot be compared to elements
 215.252 +     *         currently in the set.
 215.253 +     * @throws NullPointerException if {@code toElement} is null and
 215.254 +     *         this set does not permit null elements
 215.255 +     * @throws IllegalArgumentException if this set itself has a
 215.256 +     *         restricted range, and {@code toElement} lies outside the
 215.257 +     *         bounds of the range
 215.258 +     */
 215.259 +    NavigableSet<E> headSet(E toElement, boolean inclusive);
 215.260 +
 215.261 +    /**
 215.262 +     * Returns a view of the portion of this set whose elements are greater
 215.263 +     * than (or equal to, if {@code inclusive} is true) {@code fromElement}.
 215.264 +     * The returned set is backed by this set, so changes in the returned set
 215.265 +     * are reflected in this set, and vice-versa.  The returned set supports
 215.266 +     * all optional set operations that this set supports.
 215.267 +     *
 215.268 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 215.269 +     * on an attempt to insert an element outside its range.
 215.270 +     *
 215.271 +     * @param fromElement low endpoint of the returned set
 215.272 +     * @param inclusive {@code true} if the low endpoint
 215.273 +     *        is to be included in the returned view
 215.274 +     * @return a view of the portion of this set whose elements are greater
 215.275 +     *         than or equal to {@code fromElement}
 215.276 +     * @throws ClassCastException if {@code fromElement} is not compatible
 215.277 +     *         with this set's comparator (or, if the set has no comparator,
 215.278 +     *         if {@code fromElement} does not implement {@link Comparable}).
 215.279 +     *         Implementations may, but are not required to, throw this
 215.280 +     *         exception if {@code fromElement} cannot be compared to elements
 215.281 +     *         currently in the set.
 215.282 +     * @throws NullPointerException if {@code fromElement} is null
 215.283 +     *         and this set does not permit null elements
 215.284 +     * @throws IllegalArgumentException if this set itself has a
 215.285 +     *         restricted range, and {@code fromElement} lies outside the
 215.286 +     *         bounds of the range
 215.287 +     */
 215.288 +    NavigableSet<E> tailSet(E fromElement, boolean inclusive);
 215.289 +
 215.290 +    /**
 215.291 +     * {@inheritDoc}
 215.292 +     *
 215.293 +     * <p>Equivalent to {@code subSet(fromElement, true, toElement, false)}.
 215.294 +     *
 215.295 +     * @throws ClassCastException       {@inheritDoc}
 215.296 +     * @throws NullPointerException     {@inheritDoc}
 215.297 +     * @throws IllegalArgumentException {@inheritDoc}
 215.298 +     */
 215.299 +    SortedSet<E> subSet(E fromElement, E toElement);
 215.300 +
 215.301 +    /**
 215.302 +     * {@inheritDoc}
 215.303 +     *
 215.304 +     * <p>Equivalent to {@code headSet(toElement, false)}.
 215.305 +     *
 215.306 +     * @throws ClassCastException       {@inheritDoc}
 215.307 +     * @throws NullPointerException     {@inheritDoc}
 215.308 +     * @throws IllegalArgumentException {@inheritDoc}
 215.309 +na     */
 215.310 +    SortedSet<E> headSet(E toElement);
 215.311 +
 215.312 +    /**
 215.313 +     * {@inheritDoc}
 215.314 +     *
 215.315 +     * <p>Equivalent to {@code tailSet(fromElement, true)}.
 215.316 +     *
 215.317 +     * @throws ClassCastException       {@inheritDoc}
 215.318 +     * @throws NullPointerException     {@inheritDoc}
 215.319 +     * @throws IllegalArgumentException {@inheritDoc}
 215.320 +     */
 215.321 +    SortedSet<E> tailSet(E fromElement);
 215.322 +}
   216.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   216.2 +++ b/rt/emul/compact/src/main/java/java/util/Properties.java	Wed Apr 30 15:04:10 2014 +0200
   216.3 @@ -0,0 +1,1113 @@
   216.4 +/*
   216.5 + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
   216.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   216.7 + *
   216.8 + * This code is free software; you can redistribute it and/or modify it
   216.9 + * under the terms of the GNU General Public License version 2 only, as
  216.10 + * published by the Free Software Foundation.  Oracle designates this
  216.11 + * particular file as subject to the "Classpath" exception as provided
  216.12 + * by Oracle in the LICENSE file that accompanied this code.
  216.13 + *
  216.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  216.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  216.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  216.17 + * version 2 for more details (a copy is included in the LICENSE file that
  216.18 + * accompanied this code).
  216.19 + *
  216.20 + * You should have received a copy of the GNU General Public License version
  216.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  216.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  216.23 + *
  216.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  216.25 + * or visit www.oracle.com if you need additional information or have any
  216.26 + * questions.
  216.27 + */
  216.28 +
  216.29 +package java.util;
  216.30 +
  216.31 +import java.io.IOException;
  216.32 +import java.io.PrintStream;
  216.33 +import java.io.PrintWriter;
  216.34 +import java.io.InputStream;
  216.35 +import java.io.OutputStream;
  216.36 +import java.io.Reader;
  216.37 +import java.io.Writer;
  216.38 +import java.io.OutputStreamWriter;
  216.39 +import java.io.BufferedWriter;
  216.40 +
  216.41 +/**
  216.42 + * The <code>Properties</code> class represents a persistent set of
  216.43 + * properties. The <code>Properties</code> can be saved to a stream
  216.44 + * or loaded from a stream. Each key and its corresponding value in
  216.45 + * the property list is a string.
  216.46 + * <p>
  216.47 + * A property list can contain another property list as its
  216.48 + * "defaults"; this second property list is searched if
  216.49 + * the property key is not found in the original property list.
  216.50 + * <p>
  216.51 + * Because <code>Properties</code> inherits from <code>Hashtable</code>, the
  216.52 + * <code>put</code> and <code>putAll</code> methods can be applied to a
  216.53 + * <code>Properties</code> object.  Their use is strongly discouraged as they
  216.54 + * allow the caller to insert entries whose keys or values are not
  216.55 + * <code>Strings</code>.  The <code>setProperty</code> method should be used
  216.56 + * instead.  If the <code>store</code> or <code>save</code> method is called
  216.57 + * on a "compromised" <code>Properties</code> object that contains a
  216.58 + * non-<code>String</code> key or value, the call will fail. Similarly,
  216.59 + * the call to the <code>propertyNames</code> or <code>list</code> method
  216.60 + * will fail if it is called on a "compromised" <code>Properties</code>
  216.61 + * object that contains a non-<code>String</code> key.
  216.62 + *
  216.63 + * <p>
  216.64 + * The {@link #load(java.io.Reader) load(Reader)} <tt>/</tt>
  216.65 + * {@link #store(java.io.Writer, java.lang.String) store(Writer, String)}
  216.66 + * methods load and store properties from and to a character based stream
  216.67 + * in a simple line-oriented format specified below.
  216.68 + *
  216.69 + * The {@link #load(java.io.InputStream) load(InputStream)} <tt>/</tt>
  216.70 + * {@link #store(java.io.OutputStream, java.lang.String) store(OutputStream, String)}
  216.71 + * methods work the same way as the load(Reader)/store(Writer, String) pair, except
  216.72 + * the input/output stream is encoded in ISO 8859-1 character encoding.
  216.73 + * Characters that cannot be directly represented in this encoding can be written using
  216.74 + * Unicode escapes as defined in section 3.3 of
  216.75 + * <cite>The Java&trade; Language Specification</cite>;
  216.76 + * only a single 'u' character is allowed in an escape
  216.77 + * sequence. The native2ascii tool can be used to convert property files to and
  216.78 + * from other character encodings.
  216.79 + *
  216.80 + * <p> The {@link #loadFromXML(InputStream)} and {@link
  216.81 + * #storeToXML(OutputStream, String, String)} methods load and store properties
  216.82 + * in a simple XML format.  By default the UTF-8 character encoding is used,
  216.83 + * however a specific encoding may be specified if required.  An XML properties
  216.84 + * document has the following DOCTYPE declaration:
  216.85 + *
  216.86 + * <pre>
  216.87 + * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
  216.88 + * </pre>
  216.89 + * Note that the system URI (http://java.sun.com/dtd/properties.dtd) is
  216.90 + * <i>not</i> accessed when exporting or importing properties; it merely
  216.91 + * serves as a string to uniquely identify the DTD, which is:
  216.92 + * <pre>
  216.93 + *    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  216.94 + *
  216.95 + *    &lt;!-- DTD for properties --&gt;
  216.96 + *
  216.97 + *    &lt;!ELEMENT properties ( comment?, entry* ) &gt;
  216.98 + *
  216.99 + *    &lt;!ATTLIST properties version CDATA #FIXED "1.0"&gt;
 216.100 + *
 216.101 + *    &lt;!ELEMENT comment (#PCDATA) &gt;
 216.102 + *
 216.103 + *    &lt;!ELEMENT entry (#PCDATA) &gt;
 216.104 + *
 216.105 + *    &lt;!ATTLIST entry key CDATA #REQUIRED&gt;
 216.106 + * </pre>
 216.107 + *
 216.108 + * <p>This class is thread-safe: multiple threads can share a single
 216.109 + * <tt>Properties</tt> object without the need for external synchronization.
 216.110 + *
 216.111 + * @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
 216.112 + * @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
 216.113 + *
 216.114 + * @author  Arthur van Hoff
 216.115 + * @author  Michael McCloskey
 216.116 + * @author  Xueming Shen
 216.117 + * @since   JDK1.0
 216.118 + */
 216.119 +public
 216.120 +class Properties extends Hashtable<Object,Object> {
 216.121 +    /**
 216.122 +     * use serialVersionUID from JDK 1.1.X for interoperability
 216.123 +     */
 216.124 +     private static final long serialVersionUID = 4112578634029874840L;
 216.125 +
 216.126 +    /**
 216.127 +     * A property list that contains default values for any keys not
 216.128 +     * found in this property list.
 216.129 +     *
 216.130 +     * @serial
 216.131 +     */
 216.132 +    protected Properties defaults;
 216.133 +
 216.134 +    /**
 216.135 +     * Creates an empty property list with no default values.
 216.136 +     */
 216.137 +    public Properties() {
 216.138 +        this(null);
 216.139 +    }
 216.140 +
 216.141 +    /**
 216.142 +     * Creates an empty property list with the specified defaults.
 216.143 +     *
 216.144 +     * @param   defaults   the defaults.
 216.145 +     */
 216.146 +    public Properties(Properties defaults) {
 216.147 +        this.defaults = defaults;
 216.148 +    }
 216.149 +
 216.150 +    /**
 216.151 +     * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for
 216.152 +     * parallelism with the <tt>getProperty</tt> method. Enforces use of
 216.153 +     * strings for property keys and values. The value returned is the
 216.154 +     * result of the <tt>Hashtable</tt> call to <code>put</code>.
 216.155 +     *
 216.156 +     * @param key the key to be placed into this property list.
 216.157 +     * @param value the value corresponding to <tt>key</tt>.
 216.158 +     * @return     the previous value of the specified key in this property
 216.159 +     *             list, or <code>null</code> if it did not have one.
 216.160 +     * @see #getProperty
 216.161 +     * @since    1.2
 216.162 +     */
 216.163 +    public synchronized Object setProperty(String key, String value) {
 216.164 +        return put(key, value);
 216.165 +    }
 216.166 +
 216.167 +
 216.168 +    /**
 216.169 +     * Reads a property list (key and element pairs) from the input
 216.170 +     * character stream in a simple line-oriented format.
 216.171 +     * <p>
 216.172 +     * Properties are processed in terms of lines. There are two
 216.173 +     * kinds of line, <i>natural lines</i> and <i>logical lines</i>.
 216.174 +     * A natural line is defined as a line of
 216.175 +     * characters that is terminated either by a set of line terminator
 216.176 +     * characters (<code>\n</code> or <code>\r</code> or <code>\r\n</code>)
 216.177 +     * or by the end of the stream. A natural line may be either a blank line,
 216.178 +     * a comment line, or hold all or some of a key-element pair. A logical
 216.179 +     * line holds all the data of a key-element pair, which may be spread
 216.180 +     * out across several adjacent natural lines by escaping
 216.181 +     * the line terminator sequence with a backslash character
 216.182 +     * <code>\</code>.  Note that a comment line cannot be extended
 216.183 +     * in this manner; every natural line that is a comment must have
 216.184 +     * its own comment indicator, as described below. Lines are read from
 216.185 +     * input until the end of the stream is reached.
 216.186 +     *
 216.187 +     * <p>
 216.188 +     * A natural line that contains only white space characters is
 216.189 +     * considered blank and is ignored.  A comment line has an ASCII
 216.190 +     * <code>'#'</code> or <code>'!'</code> as its first non-white
 216.191 +     * space character; comment lines are also ignored and do not
 216.192 +     * encode key-element information.  In addition to line
 216.193 +     * terminators, this format considers the characters space
 216.194 +     * (<code>' '</code>, <code>'&#92;u0020'</code>), tab
 216.195 +     * (<code>'\t'</code>, <code>'&#92;u0009'</code>), and form feed
 216.196 +     * (<code>'\f'</code>, <code>'&#92;u000C'</code>) to be white
 216.197 +     * space.
 216.198 +     *
 216.199 +     * <p>
 216.200 +     * If a logical line is spread across several natural lines, the
 216.201 +     * backslash escaping the line terminator sequence, the line
 216.202 +     * terminator sequence, and any white space at the start of the
 216.203 +     * following line have no affect on the key or element values.
 216.204 +     * The remainder of the discussion of key and element parsing
 216.205 +     * (when loading) will assume all the characters constituting
 216.206 +     * the key and element appear on a single natural line after
 216.207 +     * line continuation characters have been removed.  Note that
 216.208 +     * it is <i>not</i> sufficient to only examine the character
 216.209 +     * preceding a line terminator sequence to decide if the line
 216.210 +     * terminator is escaped; there must be an odd number of
 216.211 +     * contiguous backslashes for the line terminator to be escaped.
 216.212 +     * Since the input is processed from left to right, a
 216.213 +     * non-zero even number of 2<i>n</i> contiguous backslashes
 216.214 +     * before a line terminator (or elsewhere) encodes <i>n</i>
 216.215 +     * backslashes after escape processing.
 216.216 +     *
 216.217 +     * <p>
 216.218 +     * The key contains all of the characters in the line starting
 216.219 +     * with the first non-white space character and up to, but not
 216.220 +     * including, the first unescaped <code>'='</code>,
 216.221 +     * <code>':'</code>, or white space character other than a line
 216.222 +     * terminator. All of these key termination characters may be
 216.223 +     * included in the key by escaping them with a preceding backslash
 216.224 +     * character; for example,<p>
 216.225 +     *
 216.226 +     * <code>\:\=</code><p>
 216.227 +     *
 216.228 +     * would be the two-character key <code>":="</code>.  Line
 216.229 +     * terminator characters can be included using <code>\r</code> and
 216.230 +     * <code>\n</code> escape sequences.  Any white space after the
 216.231 +     * key is skipped; if the first non-white space character after
 216.232 +     * the key is <code>'='</code> or <code>':'</code>, then it is
 216.233 +     * ignored and any white space characters after it are also
 216.234 +     * skipped.  All remaining characters on the line become part of
 216.235 +     * the associated element string; if there are no remaining
 216.236 +     * characters, the element is the empty string
 216.237 +     * <code>&quot;&quot;</code>.  Once the raw character sequences
 216.238 +     * constituting the key and element are identified, escape
 216.239 +     * processing is performed as described above.
 216.240 +     *
 216.241 +     * <p>
 216.242 +     * As an example, each of the following three lines specifies the key
 216.243 +     * <code>"Truth"</code> and the associated element value
 216.244 +     * <code>"Beauty"</code>:
 216.245 +     * <p>
 216.246 +     * <pre>
 216.247 +     * Truth = Beauty
 216.248 +     *  Truth:Beauty
 216.249 +     * Truth                    :Beauty
 216.250 +     * </pre>
 216.251 +     * As another example, the following three lines specify a single
 216.252 +     * property:
 216.253 +     * <p>
 216.254 +     * <pre>
 216.255 +     * fruits                           apple, banana, pear, \
 216.256 +     *                                  cantaloupe, watermelon, \
 216.257 +     *                                  kiwi, mango
 216.258 +     * </pre>
 216.259 +     * The key is <code>"fruits"</code> and the associated element is:
 216.260 +     * <p>
 216.261 +     * <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre>
 216.262 +     * Note that a space appears before each <code>\</code> so that a space
 216.263 +     * will appear after each comma in the final result; the <code>\</code>,
 216.264 +     * line terminator, and leading white space on the continuation line are
 216.265 +     * merely discarded and are <i>not</i> replaced by one or more other
 216.266 +     * characters.
 216.267 +     * <p>
 216.268 +     * As a third example, the line:
 216.269 +     * <p>
 216.270 +     * <pre>cheeses
 216.271 +     * </pre>
 216.272 +     * specifies that the key is <code>"cheeses"</code> and the associated
 216.273 +     * element is the empty string <code>""</code>.<p>
 216.274 +     * <p>
 216.275 +     *
 216.276 +     * <a name="unicodeescapes"></a>
 216.277 +     * Characters in keys and elements can be represented in escape
 216.278 +     * sequences similar to those used for character and string literals
 216.279 +     * (see sections 3.3 and 3.10.6 of
 216.280 +     * <cite>The Java&trade; Language Specification</cite>).
 216.281 +     *
 216.282 +     * The differences from the character escape sequences and Unicode
 216.283 +     * escapes used for characters and strings are:
 216.284 +     *
 216.285 +     * <ul>
 216.286 +     * <li> Octal escapes are not recognized.
 216.287 +     *
 216.288 +     * <li> The character sequence <code>\b</code> does <i>not</i>
 216.289 +     * represent a backspace character.
 216.290 +     *
 216.291 +     * <li> The method does not treat a backslash character,
 216.292 +     * <code>\</code>, before a non-valid escape character as an
 216.293 +     * error; the backslash is silently dropped.  For example, in a
 216.294 +     * Java string the sequence <code>"\z"</code> would cause a
 216.295 +     * compile time error.  In contrast, this method silently drops
 216.296 +     * the backslash.  Therefore, this method treats the two character
 216.297 +     * sequence <code>"\b"</code> as equivalent to the single
 216.298 +     * character <code>'b'</code>.
 216.299 +     *
 216.300 +     * <li> Escapes are not necessary for single and double quotes;
 216.301 +     * however, by the rule above, single and double quote characters
 216.302 +     * preceded by a backslash still yield single and double quote
 216.303 +     * characters, respectively.
 216.304 +     *
 216.305 +     * <li> Only a single 'u' character is allowed in a Uniocde escape
 216.306 +     * sequence.
 216.307 +     *
 216.308 +     * </ul>
 216.309 +     * <p>
 216.310 +     * The specified stream remains open after this method returns.
 216.311 +     *
 216.312 +     * @param   reader   the input character stream.
 216.313 +     * @throws  IOException  if an error occurred when reading from the
 216.314 +     *          input stream.
 216.315 +     * @throws  IllegalArgumentException if a malformed Unicode escape
 216.316 +     *          appears in the input.
 216.317 +     * @since   1.6
 216.318 +     */
 216.319 +    public synchronized void load(Reader reader) throws IOException {
 216.320 +        load0(new LineReader(reader));
 216.321 +    }
 216.322 +
 216.323 +    /**
 216.324 +     * Reads a property list (key and element pairs) from the input
 216.325 +     * byte stream. The input stream is in a simple line-oriented
 216.326 +     * format as specified in
 216.327 +     * {@link #load(java.io.Reader) load(Reader)} and is assumed to use
 216.328 +     * the ISO 8859-1 character encoding; that is each byte is one Latin1
 216.329 +     * character. Characters not in Latin1, and certain special characters,
 216.330 +     * are represented in keys and elements using Unicode escapes as defined in
 216.331 +     * section 3.3 of
 216.332 +     * <cite>The Java&trade; Language Specification</cite>.
 216.333 +     * <p>
 216.334 +     * The specified stream remains open after this method returns.
 216.335 +     *
 216.336 +     * @param      inStream   the input stream.
 216.337 +     * @exception  IOException  if an error occurred when reading from the
 216.338 +     *             input stream.
 216.339 +     * @throws     IllegalArgumentException if the input stream contains a
 216.340 +     *             malformed Unicode escape sequence.
 216.341 +     * @since 1.2
 216.342 +     */
 216.343 +    public synchronized void load(InputStream inStream) throws IOException {
 216.344 +        load0(new LineReader(inStream));
 216.345 +    }
 216.346 +
 216.347 +    private void load0 (LineReader lr) throws IOException {
 216.348 +        char[] convtBuf = new char[1024];
 216.349 +        int limit;
 216.350 +        int keyLen;
 216.351 +        int valueStart;
 216.352 +        char c;
 216.353 +        boolean hasSep;
 216.354 +        boolean precedingBackslash;
 216.355 +
 216.356 +        while ((limit = lr.readLine()) >= 0) {
 216.357 +            c = 0;
 216.358 +            keyLen = 0;
 216.359 +            valueStart = limit;
 216.360 +            hasSep = false;
 216.361 +
 216.362 +            //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
 216.363 +            precedingBackslash = false;
 216.364 +            while (keyLen < limit) {
 216.365 +                c = lr.lineBuf[keyLen];
 216.366 +                //need check if escaped.
 216.367 +                if ((c == '=' ||  c == ':') && !precedingBackslash) {
 216.368 +                    valueStart = keyLen + 1;
 216.369 +                    hasSep = true;
 216.370 +                    break;
 216.371 +                } else if ((c == ' ' || c == '\t' ||  c == '\f') && !precedingBackslash) {
 216.372 +                    valueStart = keyLen + 1;
 216.373 +                    break;
 216.374 +                }
 216.375 +                if (c == '\\') {
 216.376 +                    precedingBackslash = !precedingBackslash;
 216.377 +                } else {
 216.378 +                    precedingBackslash = false;
 216.379 +                }
 216.380 +                keyLen++;
 216.381 +            }
 216.382 +            while (valueStart < limit) {
 216.383 +                c = lr.lineBuf[valueStart];
 216.384 +                if (c != ' ' && c != '\t' &&  c != '\f') {
 216.385 +                    if (!hasSep && (c == '=' ||  c == ':')) {
 216.386 +                        hasSep = true;
 216.387 +                    } else {
 216.388 +                        break;
 216.389 +                    }
 216.390 +                }
 216.391 +                valueStart++;
 216.392 +            }
 216.393 +            String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
 216.394 +            String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
 216.395 +            put(key, value);
 216.396 +        }
 216.397 +    }
 216.398 +
 216.399 +    /* Read in a "logical line" from an InputStream/Reader, skip all comment
 216.400 +     * and blank lines and filter out those leading whitespace characters
 216.401 +     * (\u0020, \u0009 and \u000c) from the beginning of a "natural line".
 216.402 +     * Method returns the char length of the "logical line" and stores
 216.403 +     * the line in "lineBuf".
 216.404 +     */
 216.405 +    class LineReader {
 216.406 +        public LineReader(InputStream inStream) {
 216.407 +            this.inStream = inStream;
 216.408 +            inByteBuf = new byte[8192];
 216.409 +        }
 216.410 +
 216.411 +        public LineReader(Reader reader) {
 216.412 +            this.reader = reader;
 216.413 +            inCharBuf = new char[8192];
 216.414 +        }
 216.415 +
 216.416 +        byte[] inByteBuf;
 216.417 +        char[] inCharBuf;
 216.418 +        char[] lineBuf = new char[1024];
 216.419 +        int inLimit = 0;
 216.420 +        int inOff = 0;
 216.421 +        InputStream inStream;
 216.422 +        Reader reader;
 216.423 +
 216.424 +        int readLine() throws IOException {
 216.425 +            int len = 0;
 216.426 +            char c = 0;
 216.427 +
 216.428 +            boolean skipWhiteSpace = true;
 216.429 +            boolean isCommentLine = false;
 216.430 +            boolean isNewLine = true;
 216.431 +            boolean appendedLineBegin = false;
 216.432 +            boolean precedingBackslash = false;
 216.433 +            boolean skipLF = false;
 216.434 +
 216.435 +            while (true) {
 216.436 +                if (inOff >= inLimit) {
 216.437 +                    inLimit = (inStream==null)?reader.read(inCharBuf)
 216.438 +                                              :inStream.read(inByteBuf);
 216.439 +                    inOff = 0;
 216.440 +                    if (inLimit <= 0) {
 216.441 +                        if (len == 0 || isCommentLine) {
 216.442 +                            return -1;
 216.443 +                        }
 216.444 +                        return len;
 216.445 +                    }
 216.446 +                }
 216.447 +                if (inStream != null) {
 216.448 +                    //The line below is equivalent to calling a
 216.449 +                    //ISO8859-1 decoder.
 216.450 +                    c = (char) (0xff & inByteBuf[inOff++]);
 216.451 +                } else {
 216.452 +                    c = inCharBuf[inOff++];
 216.453 +                }
 216.454 +                if (skipLF) {
 216.455 +                    skipLF = false;
 216.456 +                    if (c == '\n') {
 216.457 +                        continue;
 216.458 +                    }
 216.459 +                }
 216.460 +                if (skipWhiteSpace) {
 216.461 +                    if (c == ' ' || c == '\t' || c == '\f') {
 216.462 +                        continue;
 216.463 +                    }
 216.464 +                    if (!appendedLineBegin && (c == '\r' || c == '\n')) {
 216.465 +                        continue;
 216.466 +                    }
 216.467 +                    skipWhiteSpace = false;
 216.468 +                    appendedLineBegin = false;
 216.469 +                }
 216.470 +                if (isNewLine) {
 216.471 +                    isNewLine = false;
 216.472 +                    if (c == '#' || c == '!') {
 216.473 +                        isCommentLine = true;
 216.474 +                        continue;
 216.475 +                    }
 216.476 +                }
 216.477 +
 216.478 +                if (c != '\n' && c != '\r') {
 216.479 +                    lineBuf[len++] = c;
 216.480 +                    if (len == lineBuf.length) {
 216.481 +                        int newLength = lineBuf.length * 2;
 216.482 +                        if (newLength < 0) {
 216.483 +                            newLength = Integer.MAX_VALUE;
 216.484 +                        }
 216.485 +                        char[] buf = new char[newLength];
 216.486 +                        System.arraycopy(lineBuf, 0, buf, 0, lineBuf.length);
 216.487 +                        lineBuf = buf;
 216.488 +                    }
 216.489 +                    //flip the preceding backslash flag
 216.490 +                    if (c == '\\') {
 216.491 +                        precedingBackslash = !precedingBackslash;
 216.492 +                    } else {
 216.493 +                        precedingBackslash = false;
 216.494 +                    }
 216.495 +                }
 216.496 +                else {
 216.497 +                    // reached EOL
 216.498 +                    if (isCommentLine || len == 0) {
 216.499 +                        isCommentLine = false;
 216.500 +                        isNewLine = true;
 216.501 +                        skipWhiteSpace = true;
 216.502 +                        len = 0;
 216.503 +                        continue;
 216.504 +                    }
 216.505 +                    if (inOff >= inLimit) {
 216.506 +                        inLimit = (inStream==null)
 216.507 +                                  ?reader.read(inCharBuf)
 216.508 +                                  :inStream.read(inByteBuf);
 216.509 +                        inOff = 0;
 216.510 +                        if (inLimit <= 0) {
 216.511 +                            return len;
 216.512 +                        }
 216.513 +                    }
 216.514 +                    if (precedingBackslash) {
 216.515 +                        len -= 1;
 216.516 +                        //skip the leading whitespace characters in following line
 216.517 +                        skipWhiteSpace = true;
 216.518 +                        appendedLineBegin = true;
 216.519 +                        precedingBackslash = false;
 216.520 +                        if (c == '\r') {
 216.521 +                            skipLF = true;
 216.522 +                        }
 216.523 +                    } else {
 216.524 +                        return len;
 216.525 +                    }
 216.526 +                }
 216.527 +            }
 216.528 +        }
 216.529 +    }
 216.530 +
 216.531 +    /*
 216.532 +     * Converts encoded &#92;uxxxx to unicode chars
 216.533 +     * and changes special saved chars to their original forms
 216.534 +     */
 216.535 +    private String loadConvert (char[] in, int off, int len, char[] convtBuf) {
 216.536 +        if (convtBuf.length < len) {
 216.537 +            int newLen = len * 2;
 216.538 +            if (newLen < 0) {
 216.539 +                newLen = Integer.MAX_VALUE;
 216.540 +            }
 216.541 +            convtBuf = new char[newLen];
 216.542 +        }
 216.543 +        char aChar;
 216.544 +        char[] out = convtBuf;
 216.545 +        int outLen = 0;
 216.546 +        int end = off + len;
 216.547 +
 216.548 +        while (off < end) {
 216.549 +            aChar = in[off++];
 216.550 +            if (aChar == '\\') {
 216.551 +                aChar = in[off++];
 216.552 +                if(aChar == 'u') {
 216.553 +                    // Read the xxxx
 216.554 +                    int value=0;
 216.555 +                    for (int i=0; i<4; i++) {
 216.556 +                        aChar = in[off++];
 216.557 +                        switch (aChar) {
 216.558 +                          case '0': case '1': case '2': case '3': case '4':
 216.559 +                          case '5': case '6': case '7': case '8': case '9':
 216.560 +                             value = (value << 4) + aChar - '0';
 216.561 +                             break;
 216.562 +                          case 'a': case 'b': case 'c':
 216.563 +                          case 'd': case 'e': case 'f':
 216.564 +                             value = (value << 4) + 10 + aChar - 'a';
 216.565 +                             break;
 216.566 +                          case 'A': case 'B': case 'C':
 216.567 +                          case 'D': case 'E': case 'F':
 216.568 +                             value = (value << 4) + 10 + aChar - 'A';
 216.569 +                             break;
 216.570 +                          default:
 216.571 +                              throw new IllegalArgumentException(
 216.572 +                                           "Malformed \\uxxxx encoding.");
 216.573 +                        }
 216.574 +                     }
 216.575 +                    out[outLen++] = (char)value;
 216.576 +                } else {
 216.577 +                    if (aChar == 't') aChar = '\t';
 216.578 +                    else if (aChar == 'r') aChar = '\r';
 216.579 +                    else if (aChar == 'n') aChar = '\n';
 216.580 +                    else if (aChar == 'f') aChar = '\f';
 216.581 +                    out[outLen++] = aChar;
 216.582 +                }
 216.583 +            } else {
 216.584 +                out[outLen++] = aChar;
 216.585 +            }
 216.586 +        }
 216.587 +        return new String (out, 0, outLen);
 216.588 +    }
 216.589 +
 216.590 +    /*
 216.591 +     * Converts unicodes to encoded &#92;uxxxx and escapes
 216.592 +     * special characters with a preceding slash
 216.593 +     */
 216.594 +    private String saveConvert(String theString,
 216.595 +                               boolean escapeSpace,
 216.596 +                               boolean escapeUnicode) {
 216.597 +        int len = theString.length();
 216.598 +        int bufLen = len * 2;
 216.599 +        if (bufLen < 0) {
 216.600 +            bufLen = Integer.MAX_VALUE;
 216.601 +        }
 216.602 +        StringBuffer outBuffer = new StringBuffer(bufLen);
 216.603 +
 216.604 +        for(int x=0; x<len; x++) {
 216.605 +            char aChar = theString.charAt(x);
 216.606 +            // Handle common case first, selecting largest block that
 216.607 +            // avoids the specials below
 216.608 +            if ((aChar > 61) && (aChar < 127)) {
 216.609 +                if (aChar == '\\') {
 216.610 +                    outBuffer.append('\\'); outBuffer.append('\\');
 216.611 +                    continue;
 216.612 +                }
 216.613 +                outBuffer.append(aChar);
 216.614 +                continue;
 216.615 +            }
 216.616 +            switch(aChar) {
 216.617 +                case ' ':
 216.618 +                    if (x == 0 || escapeSpace)
 216.619 +                        outBuffer.append('\\');
 216.620 +                    outBuffer.append(' ');
 216.621 +                    break;
 216.622 +                case '\t':outBuffer.append('\\'); outBuffer.append('t');
 216.623 +                          break;
 216.624 +                case '\n':outBuffer.append('\\'); outBuffer.append('n');
 216.625 +                          break;
 216.626 +                case '\r':outBuffer.append('\\'); outBuffer.append('r');
 216.627 +                          break;
 216.628 +                case '\f':outBuffer.append('\\'); outBuffer.append('f');
 216.629 +                          break;
 216.630 +                case '=': // Fall through
 216.631 +                case ':': // Fall through
 216.632 +                case '#': // Fall through
 216.633 +                case '!':
 216.634 +                    outBuffer.append('\\'); outBuffer.append(aChar);
 216.635 +                    break;
 216.636 +                default:
 216.637 +                    if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode ) {
 216.638 +                        outBuffer.append('\\');
 216.639 +                        outBuffer.append('u');
 216.640 +                        outBuffer.append(toHex((aChar >> 12) & 0xF));
 216.641 +                        outBuffer.append(toHex((aChar >>  8) & 0xF));
 216.642 +                        outBuffer.append(toHex((aChar >>  4) & 0xF));
 216.643 +                        outBuffer.append(toHex( aChar        & 0xF));
 216.644 +                    } else {
 216.645 +                        outBuffer.append(aChar);
 216.646 +                    }
 216.647 +            }
 216.648 +        }
 216.649 +        return outBuffer.toString();
 216.650 +    }
 216.651 +
 216.652 +    private static void writeComments(BufferedWriter bw, String comments)
 216.653 +        throws IOException {
 216.654 +        bw.write("#");
 216.655 +        int len = comments.length();
 216.656 +        int current = 0;
 216.657 +        int last = 0;
 216.658 +        char[] uu = new char[6];
 216.659 +        uu[0] = '\\';
 216.660 +        uu[1] = 'u';
 216.661 +        while (current < len) {
 216.662 +            char c = comments.charAt(current);
 216.663 +            if (c > '\u00ff' || c == '\n' || c == '\r') {
 216.664 +                if (last != current)
 216.665 +                    bw.write(comments.substring(last, current));
 216.666 +                if (c > '\u00ff') {
 216.667 +                    uu[2] = toHex((c >> 12) & 0xf);
 216.668 +                    uu[3] = toHex((c >>  8) & 0xf);
 216.669 +                    uu[4] = toHex((c >>  4) & 0xf);
 216.670 +                    uu[5] = toHex( c        & 0xf);
 216.671 +                    bw.write(new String(uu));
 216.672 +                } else {
 216.673 +                    bw.newLine();
 216.674 +                    if (c == '\r' &&
 216.675 +                        current != len - 1 &&
 216.676 +                        comments.charAt(current + 1) == '\n') {
 216.677 +                        current++;
 216.678 +                    }
 216.679 +                    if (current == len - 1 ||
 216.680 +                        (comments.charAt(current + 1) != '#' &&
 216.681 +                        comments.charAt(current + 1) != '!'))
 216.682 +                        bw.write("#");
 216.683 +                }
 216.684 +                last = current + 1;
 216.685 +            }
 216.686 +            current++;
 216.687 +        }
 216.688 +        if (last != current)
 216.689 +            bw.write(comments.substring(last, current));
 216.690 +        bw.newLine();
 216.691 +    }
 216.692 +
 216.693 +    /**
 216.694 +     * Calls the <code>store(OutputStream out, String comments)</code> method
 216.695 +     * and suppresses IOExceptions that were thrown.
 216.696 +     *
 216.697 +     * @deprecated This method does not throw an IOException if an I/O error
 216.698 +     * occurs while saving the property list.  The preferred way to save a
 216.699 +     * properties list is via the <code>store(OutputStream out,
 216.700 +     * String comments)</code> method or the
 216.701 +     * <code>storeToXML(OutputStream os, String comment)</code> method.
 216.702 +     *
 216.703 +     * @param   out      an output stream.
 216.704 +     * @param   comments   a description of the property list.
 216.705 +     * @exception  ClassCastException  if this <code>Properties</code> object
 216.706 +     *             contains any keys or values that are not
 216.707 +     *             <code>Strings</code>.
 216.708 +     */
 216.709 +    @Deprecated
 216.710 +    public void save(OutputStream out, String comments)  {
 216.711 +        try {
 216.712 +            store(out, comments);
 216.713 +        } catch (IOException e) {
 216.714 +        }
 216.715 +    }
 216.716 +
 216.717 +    /**
 216.718 +     * Writes this property list (key and element pairs) in this
 216.719 +     * <code>Properties</code> table to the output character stream in a
 216.720 +     * format suitable for using the {@link #load(java.io.Reader) load(Reader)}
 216.721 +     * method.
 216.722 +     * <p>
 216.723 +     * Properties from the defaults table of this <code>Properties</code>
 216.724 +     * table (if any) are <i>not</i> written out by this method.
 216.725 +     * <p>
 216.726 +     * If the comments argument is not null, then an ASCII <code>#</code>
 216.727 +     * character, the comments string, and a line separator are first written
 216.728 +     * to the output stream. Thus, the <code>comments</code> can serve as an
 216.729 +     * identifying comment. Any one of a line feed ('\n'), a carriage
 216.730 +     * return ('\r'), or a carriage return followed immediately by a line feed
 216.731 +     * in comments is replaced by a line separator generated by the <code>Writer</code>
 216.732 +     * and if the next character in comments is not character <code>#</code> or
 216.733 +     * character <code>!</code> then an ASCII <code>#</code> is written out
 216.734 +     * after that line separator.
 216.735 +     * <p>
 216.736 +     * Next, a comment line is always written, consisting of an ASCII
 216.737 +     * <code>#</code> character, the current date and time (as if produced
 216.738 +     * by the <code>toString</code> method of <code>Date</code> for the
 216.739 +     * current time), and a line separator as generated by the <code>Writer</code>.
 216.740 +     * <p>
 216.741 +     * Then every entry in this <code>Properties</code> table is
 216.742 +     * written out, one per line. For each entry the key string is
 216.743 +     * written, then an ASCII <code>=</code>, then the associated
 216.744 +     * element string. For the key, all space characters are
 216.745 +     * written with a preceding <code>\</code> character.  For the
 216.746 +     * element, leading space characters, but not embedded or trailing
 216.747 +     * space characters, are written with a preceding <code>\</code>
 216.748 +     * character. The key and element characters <code>#</code>,
 216.749 +     * <code>!</code>, <code>=</code>, and <code>:</code> are written
 216.750 +     * with a preceding backslash to ensure that they are properly loaded.
 216.751 +     * <p>
 216.752 +     * After the entries have been written, the output stream is flushed.
 216.753 +     * The output stream remains open after this method returns.
 216.754 +     * <p>
 216.755 +     *
 216.756 +     * @param   writer      an output character stream writer.
 216.757 +     * @param   comments   a description of the property list.
 216.758 +     * @exception  IOException if writing this property list to the specified
 216.759 +     *             output stream throws an <tt>IOException</tt>.
 216.760 +     * @exception  ClassCastException  if this <code>Properties</code> object
 216.761 +     *             contains any keys or values that are not <code>Strings</code>.
 216.762 +     * @exception  NullPointerException  if <code>writer</code> is null.
 216.763 +     * @since 1.6
 216.764 +     */
 216.765 +    public void store(Writer writer, String comments)
 216.766 +        throws IOException
 216.767 +    {
 216.768 +        store0((writer instanceof BufferedWriter)?(BufferedWriter)writer
 216.769 +                                                 : new BufferedWriter(writer),
 216.770 +               comments,
 216.771 +               false);
 216.772 +    }
 216.773 +
 216.774 +    /**
 216.775 +     * Writes this property list (key and element pairs) in this
 216.776 +     * <code>Properties</code> table to the output stream in a format suitable
 216.777 +     * for loading into a <code>Properties</code> table using the
 216.778 +     * {@link #load(InputStream) load(InputStream)} method.
 216.779 +     * <p>
 216.780 +     * Properties from the defaults table of this <code>Properties</code>
 216.781 +     * table (if any) are <i>not</i> written out by this method.
 216.782 +     * <p>
 216.783 +     * This method outputs the comments, properties keys and values in
 216.784 +     * the same format as specified in
 216.785 +     * {@link #store(java.io.Writer, java.lang.String) store(Writer)},
 216.786 +     * with the following differences:
 216.787 +     * <ul>
 216.788 +     * <li>The stream is written using the ISO 8859-1 character encoding.
 216.789 +     *
 216.790 +     * <li>Characters not in Latin-1 in the comments are written as
 216.791 +     * <code>&#92;u</code><i>xxxx</i> for their appropriate unicode
 216.792 +     * hexadecimal value <i>xxxx</i>.
 216.793 +     *
 216.794 +     * <li>Characters less than <code>&#92;u0020</code> and characters greater
 216.795 +     * than <code>&#92;u007E</code> in property keys or values are written
 216.796 +     * as <code>&#92;u</code><i>xxxx</i> for the appropriate hexadecimal
 216.797 +     * value <i>xxxx</i>.
 216.798 +     * </ul>
 216.799 +     * <p>
 216.800 +     * After the entries have been written, the output stream is flushed.
 216.801 +     * The output stream remains open after this method returns.
 216.802 +     * <p>
 216.803 +     * @param   out      an output stream.
 216.804 +     * @param   comments   a description of the property list.
 216.805 +     * @exception  IOException if writing this property list to the specified
 216.806 +     *             output stream throws an <tt>IOException</tt>.
 216.807 +     * @exception  ClassCastException  if this <code>Properties</code> object
 216.808 +     *             contains any keys or values that are not <code>Strings</code>.
 216.809 +     * @exception  NullPointerException  if <code>out</code> is null.
 216.810 +     * @since 1.2
 216.811 +     */
 216.812 +    public void store(OutputStream out, String comments)
 216.813 +        throws IOException
 216.814 +    {
 216.815 +        store0(new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
 216.816 +               comments,
 216.817 +               true);
 216.818 +    }
 216.819 +
 216.820 +    private void store0(BufferedWriter bw, String comments, boolean escUnicode)
 216.821 +        throws IOException
 216.822 +    {
 216.823 +        if (comments != null) {
 216.824 +            writeComments(bw, comments);
 216.825 +        }
 216.826 +        bw.write("#" + new Date().toString());
 216.827 +        bw.newLine();
 216.828 +        synchronized (this) {
 216.829 +            for (Enumeration e = keys(); e.hasMoreElements();) {
 216.830 +                String key = (String)e.nextElement();
 216.831 +                String val = (String)get(key);
 216.832 +                key = saveConvert(key, true, escUnicode);
 216.833 +                /* No need to escape embedded and trailing spaces for value, hence
 216.834 +                 * pass false to flag.
 216.835 +                 */
 216.836 +                val = saveConvert(val, false, escUnicode);
 216.837 +                bw.write(key + "=" + val);
 216.838 +                bw.newLine();
 216.839 +            }
 216.840 +        }
 216.841 +        bw.flush();
 216.842 +    }
 216.843 +
 216.844 +    /**
 216.845 +     * Loads all of the properties represented by the XML document on the
 216.846 +     * specified input stream into this properties table.
 216.847 +     *
 216.848 +     * <p>The XML document must have the following DOCTYPE declaration:
 216.849 +     * <pre>
 216.850 +     * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
 216.851 +     * </pre>
 216.852 +     * Furthermore, the document must satisfy the properties DTD described
 216.853 +     * above.
 216.854 +     *
 216.855 +     * <p>The specified stream is closed after this method returns.
 216.856 +     *
 216.857 +     * @param in the input stream from which to read the XML document.
 216.858 +     * @throws IOException if reading from the specified input stream
 216.859 +     *         results in an <tt>IOException</tt>.
 216.860 +     * @throws InvalidPropertiesFormatException Data on input stream does not
 216.861 +     *         constitute a valid XML document with the mandated document type.
 216.862 +     * @throws NullPointerException if <code>in</code> is null.
 216.863 +     * @see    #storeToXML(OutputStream, String, String)
 216.864 +     * @since 1.5
 216.865 +     */
 216.866 +    public synchronized void loadFromXML(InputStream in)
 216.867 +        throws IOException
 216.868 +    {
 216.869 +        if (in == null)
 216.870 +            throw new NullPointerException();
 216.871 +        throw new IOException();
 216.872 +    }
 216.873 +
 216.874 +    /**
 216.875 +     * Emits an XML document representing all of the properties contained
 216.876 +     * in this table.
 216.877 +     *
 216.878 +     * <p> An invocation of this method of the form <tt>props.storeToXML(os,
 216.879 +     * comment)</tt> behaves in exactly the same way as the invocation
 216.880 +     * <tt>props.storeToXML(os, comment, "UTF-8");</tt>.
 216.881 +     *
 216.882 +     * @param os the output stream on which to emit the XML document.
 216.883 +     * @param comment a description of the property list, or <code>null</code>
 216.884 +     *        if no comment is desired.
 216.885 +     * @throws IOException if writing to the specified output stream
 216.886 +     *         results in an <tt>IOException</tt>.
 216.887 +     * @throws NullPointerException if <code>os</code> is null.
 216.888 +     * @throws ClassCastException  if this <code>Properties</code> object
 216.889 +     *         contains any keys or values that are not
 216.890 +     *         <code>Strings</code>.
 216.891 +     * @see    #loadFromXML(InputStream)
 216.892 +     * @since 1.5
 216.893 +     */
 216.894 +    public void storeToXML(OutputStream os, String comment)
 216.895 +        throws IOException
 216.896 +    {
 216.897 +        if (os == null)
 216.898 +            throw new NullPointerException();
 216.899 +        storeToXML(os, comment, "UTF-8");
 216.900 +    }
 216.901 +
 216.902 +    /**
 216.903 +     * Emits an XML document representing all of the properties contained
 216.904 +     * in this table, using the specified encoding.
 216.905 +     *
 216.906 +     * <p>The XML document will have the following DOCTYPE declaration:
 216.907 +     * <pre>
 216.908 +     * &lt;!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"&gt;
 216.909 +     * </pre>
 216.910 +     *
 216.911 +     *<p>If the specified comment is <code>null</code> then no comment
 216.912 +     * will be stored in the document.
 216.913 +     *
 216.914 +     * <p>The specified stream remains open after this method returns.
 216.915 +     *
 216.916 +     * @param os        the output stream on which to emit the XML document.
 216.917 +     * @param comment   a description of the property list, or <code>null</code>
 216.918 +     *                  if no comment is desired.
 216.919 +     * @param  encoding the name of a supported
 216.920 +     *                  <a href="../lang/package-summary.html#charenc">
 216.921 +     *                  character encoding</a>
 216.922 +     *
 216.923 +     * @throws IOException if writing to the specified output stream
 216.924 +     *         results in an <tt>IOException</tt>.
 216.925 +     * @throws NullPointerException if <code>os</code> is <code>null</code>,
 216.926 +     *         or if <code>encoding</code> is <code>null</code>.
 216.927 +     * @throws ClassCastException  if this <code>Properties</code> object
 216.928 +     *         contains any keys or values that are not
 216.929 +     *         <code>Strings</code>.
 216.930 +     * @see    #loadFromXML(InputStream)
 216.931 +     * @since 1.5
 216.932 +     */
 216.933 +    public void storeToXML(OutputStream os, String comment, String encoding)
 216.934 +        throws IOException
 216.935 +    {
 216.936 +        if (os == null)
 216.937 +            throw new NullPointerException();
 216.938 +        throw new IOException();
 216.939 +    }
 216.940 +
 216.941 +    /**
 216.942 +     * Searches for the property with the specified key in this property list.
 216.943 +     * If the key is not found in this property list, the default property list,
 216.944 +     * and its defaults, recursively, are then checked. The method returns
 216.945 +     * <code>null</code> if the property is not found.
 216.946 +     *
 216.947 +     * @param   key   the property key.
 216.948 +     * @return  the value in this property list with the specified key value.
 216.949 +     * @see     #setProperty
 216.950 +     * @see     #defaults
 216.951 +     */
 216.952 +    public String getProperty(String key) {
 216.953 +        Object oval = super.get(key);
 216.954 +        String sval = (oval instanceof String) ? (String)oval : null;
 216.955 +        return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
 216.956 +    }
 216.957 +
 216.958 +    /**
 216.959 +     * Searches for the property with the specified key in this property list.
 216.960 +     * If the key is not found in this property list, the default property list,
 216.961 +     * and its defaults, recursively, are then checked. The method returns the
 216.962 +     * default value argument if the property is not found.
 216.963 +     *
 216.964 +     * @param   key            the hashtable key.
 216.965 +     * @param   defaultValue   a default value.
 216.966 +     *
 216.967 +     * @return  the value in this property list with the specified key value.
 216.968 +     * @see     #setProperty
 216.969 +     * @see     #defaults
 216.970 +     */
 216.971 +    public String getProperty(String key, String defaultValue) {
 216.972 +        String val = getProperty(key);
 216.973 +        return (val == null) ? defaultValue : val;
 216.974 +    }
 216.975 +
 216.976 +    /**
 216.977 +     * Returns an enumeration of all the keys in this property list,
 216.978 +     * including distinct keys in the default property list if a key
 216.979 +     * of the same name has not already been found from the main
 216.980 +     * properties list.
 216.981 +     *
 216.982 +     * @return  an enumeration of all the keys in this property list, including
 216.983 +     *          the keys in the default property list.
 216.984 +     * @throws  ClassCastException if any key in this property list
 216.985 +     *          is not a string.
 216.986 +     * @see     java.util.Enumeration
 216.987 +     * @see     java.util.Properties#defaults
 216.988 +     * @see     #stringPropertyNames
 216.989 +     */
 216.990 +    public Enumeration<?> propertyNames() {
 216.991 +        Hashtable h = new Hashtable();
 216.992 +        enumerate(h);
 216.993 +        return h.keys();
 216.994 +    }
 216.995 +
 216.996 +    /**
 216.997 +     * Returns a set of keys in this property list where
 216.998 +     * the key and its corresponding value are strings,
 216.999 +     * including distinct keys in the default property list if a key
216.1000 +     * of the same name has not already been found from the main
216.1001 +     * properties list.  Properties whose key or value is not
216.1002 +     * of type <tt>String</tt> are omitted.
216.1003 +     * <p>
216.1004 +     * The returned set is not backed by the <tt>Properties</tt> object.
216.1005 +     * Changes to this <tt>Properties</tt> are not reflected in the set,
216.1006 +     * or vice versa.
216.1007 +     *
216.1008 +     * @return  a set of keys in this property list where
216.1009 +     *          the key and its corresponding value are strings,
216.1010 +     *          including the keys in the default property list.
216.1011 +     * @see     java.util.Properties#defaults
216.1012 +     * @since   1.6
216.1013 +     */
216.1014 +    public Set<String> stringPropertyNames() {
216.1015 +        Hashtable<String, String> h = new Hashtable<>();
216.1016 +        enumerateStringProperties(h);
216.1017 +        return h.keySet();
216.1018 +    }
216.1019 +
216.1020 +    /**
216.1021 +     * Prints this property list out to the specified output stream.
216.1022 +     * This method is useful for debugging.
216.1023 +     *
216.1024 +     * @param   out   an output stream.
216.1025 +     * @throws  ClassCastException if any key in this property list
216.1026 +     *          is not a string.
216.1027 +     */
216.1028 +    public void list(PrintStream out) {
216.1029 +        out.println("-- listing properties --");
216.1030 +        Hashtable h = new Hashtable();
216.1031 +        enumerate(h);
216.1032 +        for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
216.1033 +            String key = (String)e.nextElement();
216.1034 +            String val = (String)h.get(key);
216.1035 +            if (val.length() > 40) {
216.1036 +                val = val.substring(0, 37) + "...";
216.1037 +            }
216.1038 +            out.println(key + "=" + val);
216.1039 +        }
216.1040 +    }
216.1041 +
216.1042 +    /**
216.1043 +     * Prints this property list out to the specified output stream.
216.1044 +     * This method is useful for debugging.
216.1045 +     *
216.1046 +     * @param   out   an output stream.
216.1047 +     * @throws  ClassCastException if any key in this property list
216.1048 +     *          is not a string.
216.1049 +     * @since   JDK1.1
216.1050 +     */
216.1051 +    /*
216.1052 +     * Rather than use an anonymous inner class to share common code, this
216.1053 +     * method is duplicated in order to ensure that a non-1.1 compiler can
216.1054 +     * compile this file.
216.1055 +     */
216.1056 +    public void list(PrintWriter out) {
216.1057 +        out.println("-- listing properties --");
216.1058 +        Hashtable h = new Hashtable();
216.1059 +        enumerate(h);
216.1060 +        for (Enumeration e = h.keys() ; e.hasMoreElements() ;) {
216.1061 +            String key = (String)e.nextElement();
216.1062 +            String val = (String)h.get(key);
216.1063 +            if (val.length() > 40) {
216.1064 +                val = val.substring(0, 37) + "...";
216.1065 +            }
216.1066 +            out.println(key + "=" + val);
216.1067 +        }
216.1068 +    }
216.1069 +
216.1070 +    /**
216.1071 +     * Enumerates all key/value pairs in the specified hashtable.
216.1072 +     * @param h the hashtable
216.1073 +     * @throws ClassCastException if any of the property keys
216.1074 +     *         is not of String type.
216.1075 +     */
216.1076 +    private synchronized void enumerate(Hashtable h) {
216.1077 +        if (defaults != null) {
216.1078 +            defaults.enumerate(h);
216.1079 +        }
216.1080 +        for (Enumeration e = keys() ; e.hasMoreElements() ;) {
216.1081 +            String key = (String)e.nextElement();
216.1082 +            h.put(key, get(key));
216.1083 +        }
216.1084 +    }
216.1085 +
216.1086 +    /**
216.1087 +     * Enumerates all key/value pairs in the specified hashtable
216.1088 +     * and omits the property if the key or value is not a string.
216.1089 +     * @param h the hashtable
216.1090 +     */
216.1091 +    private synchronized void enumerateStringProperties(Hashtable<String, String> h) {
216.1092 +        if (defaults != null) {
216.1093 +            defaults.enumerateStringProperties(h);
216.1094 +        }
216.1095 +        for (Enumeration e = keys() ; e.hasMoreElements() ;) {
216.1096 +            Object k = e.nextElement();
216.1097 +            Object v = get(k);
216.1098 +            if (k instanceof String && v instanceof String) {
216.1099 +                h.put((String) k, (String) v);
216.1100 +            }
216.1101 +        }
216.1102 +    }
216.1103 +
216.1104 +    /**
216.1105 +     * Convert a nibble to a hex character
216.1106 +     * @param   nibble  the nibble to convert.
216.1107 +     */
216.1108 +    private static char toHex(int nibble) {
216.1109 +        return hexDigit[(nibble & 0xF)];
216.1110 +    }
216.1111 +
216.1112 +    /** A table of hex digits */
216.1113 +    private static final char[] hexDigit = {
216.1114 +        '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
216.1115 +    };
216.1116 +}
   217.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   217.2 +++ b/rt/emul/compact/src/main/java/java/util/PropertyResourceBundle.java	Wed Apr 30 15:04:10 2014 +0200
   217.3 @@ -0,0 +1,242 @@
   217.4 +/*
   217.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   217.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   217.7 + *
   217.8 + * This code is free software; you can redistribute it and/or modify it
   217.9 + * under the terms of the GNU General Public License version 2 only, as
  217.10 + * published by the Free Software Foundation.  Oracle designates this
  217.11 + * particular file as subject to the "Classpath" exception as provided
  217.12 + * by Oracle in the LICENSE file that accompanied this code.
  217.13 + *
  217.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  217.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  217.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  217.17 + * version 2 for more details (a copy is included in the LICENSE file that
  217.18 + * accompanied this code).
  217.19 + *
  217.20 + * You should have received a copy of the GNU General Public License version
  217.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  217.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  217.23 + *
  217.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  217.25 + * or visit www.oracle.com if you need additional information or have any
  217.26 + * questions.
  217.27 + */
  217.28 +
  217.29 +/*
  217.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  217.31 + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  217.32 + *
  217.33 + * The original version of this source code and documentation
  217.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
  217.35 + * subsidiary of IBM. These materials are provided under terms
  217.36 + * of a License Agreement between Taligent and Sun. This technology
  217.37 + * is protected by multiple US and International patents.
  217.38 + *
  217.39 + * This notice and attribution to Taligent may not be removed.
  217.40 + * Taligent is a registered trademark of Taligent, Inc.
  217.41 + */
  217.42 +
  217.43 +package java.util;
  217.44 +
  217.45 +import java.io.InputStream;
  217.46 +import java.io.Reader;
  217.47 +import java.io.IOException;
  217.48 +
  217.49 +/**
  217.50 + * <code>PropertyResourceBundle</code> is a concrete subclass of
  217.51 + * <code>ResourceBundle</code> that manages resources for a locale
  217.52 + * using a set of static strings from a property file. See
  217.53 + * {@link ResourceBundle ResourceBundle} for more information about resource
  217.54 + * bundles.
  217.55 + *
  217.56 + * <p>
  217.57 + * Unlike other types of resource bundle, you don't subclass
  217.58 + * <code>PropertyResourceBundle</code>.  Instead, you supply properties
  217.59 + * files containing the resource data.  <code>ResourceBundle.getBundle</code>
  217.60 + * will automatically look for the appropriate properties file and create a
  217.61 + * <code>PropertyResourceBundle</code> that refers to it. See
  217.62 + * {@link ResourceBundle#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) ResourceBundle.getBundle}
  217.63 + * for a complete description of the search and instantiation strategy.
  217.64 + *
  217.65 + * <p>
  217.66 + * The following <a name="sample">example</a> shows a member of a resource
  217.67 + * bundle family with the base name "MyResources".
  217.68 + * The text defines the bundle "MyResources_de",
  217.69 + * the German member of the bundle family.
  217.70 + * This member is based on <code>PropertyResourceBundle</code>, and the text
  217.71 + * therefore is the content of the file "MyResources_de.properties"
  217.72 + * (a related <a href="ListResourceBundle.html#sample">example</a> shows
  217.73 + * how you can add bundles to this family that are implemented as subclasses
  217.74 + * of <code>ListResourceBundle</code>).
  217.75 + * The keys in this example are of the form "s1" etc. The actual
  217.76 + * keys are entirely up to your choice, so long as they are the same as
  217.77 + * the keys you use in your program to retrieve the objects from the bundle.
  217.78 + * Keys are case-sensitive.
  217.79 + * <blockquote>
  217.80 + * <pre>
  217.81 + * # MessageFormat pattern
  217.82 + * s1=Die Platte \"{1}\" enth&auml;lt {0}.
  217.83 + *
  217.84 + * # location of {0} in pattern
  217.85 + * s2=1
  217.86 + *
  217.87 + * # sample disk name
  217.88 + * s3=Meine Platte
  217.89 + *
  217.90 + * # first ChoiceFormat choice
  217.91 + * s4=keine Dateien
  217.92 + *
  217.93 + * # second ChoiceFormat choice
  217.94 + * s5=eine Datei
  217.95 + *
  217.96 + * # third ChoiceFormat choice
  217.97 + * s6={0,number} Dateien
  217.98 + *
  217.99 + * # sample date
 217.100 + * s7=3. M&auml;rz 1996
 217.101 + * </pre>
 217.102 + * </blockquote>
 217.103 + *
 217.104 + * <p>
 217.105 + * <strong>Note:</strong> PropertyResourceBundle can be constructed either
 217.106 + * from an InputStream or a Reader, which represents a property file.
 217.107 + * Constructing a PropertyResourceBundle instance from an InputStream requires
 217.108 + * that the input stream be encoded in ISO-8859-1.  In that case, characters
 217.109 + * that cannot be represented in ISO-8859-1 encoding must be represented by Unicode Escapes
 217.110 + * as defined in section 3.3 of
 217.111 + * <cite>The Java&trade; Language Specification</cite>
 217.112 + * whereas the other constructor which takes a Reader does not have that limitation.
 217.113 + *
 217.114 + * @see ResourceBundle
 217.115 + * @see ListResourceBundle
 217.116 + * @see Properties
 217.117 + * @since JDK1.1
 217.118 + */
 217.119 +public class PropertyResourceBundle extends ResourceBundle {
 217.120 +    /**
 217.121 +     * Creates a property resource bundle from an {@link java.io.InputStream
 217.122 +     * InputStream}.  The property file read with this constructor
 217.123 +     * must be encoded in ISO-8859-1.
 217.124 +     *
 217.125 +     * @param stream an InputStream that represents a property file
 217.126 +     *        to read from.
 217.127 +     * @throws IOException if an I/O error occurs
 217.128 +     * @throws NullPointerException if <code>stream</code> is null
 217.129 +     */
 217.130 +    public PropertyResourceBundle (InputStream stream) throws IOException {
 217.131 +        Properties properties = new Properties();
 217.132 +        properties.load(stream);
 217.133 +        lookup = new HashMap(properties);
 217.134 +    }
 217.135 +
 217.136 +    /**
 217.137 +     * Creates a property resource bundle from a {@link java.io.Reader
 217.138 +     * Reader}.  Unlike the constructor
 217.139 +     * {@link #PropertyResourceBundle(java.io.InputStream) PropertyResourceBundle(InputStream)},
 217.140 +     * there is no limitation as to the encoding of the input property file.
 217.141 +     *
 217.142 +     * @param reader a Reader that represents a property file to
 217.143 +     *        read from.
 217.144 +     * @throws IOException if an I/O error occurs
 217.145 +     * @throws NullPointerException if <code>reader</code> is null
 217.146 +     * @since 1.6
 217.147 +     */
 217.148 +    public PropertyResourceBundle (Reader reader) throws IOException {
 217.149 +        Properties properties = new Properties();
 217.150 +        properties.load(reader);
 217.151 +        lookup = new HashMap(properties);
 217.152 +    }
 217.153 +
 217.154 +    // Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
 217.155 +    public Object handleGetObject(String key) {
 217.156 +        if (key == null) {
 217.157 +            throw new NullPointerException();
 217.158 +        }
 217.159 +        return lookup.get(key);
 217.160 +    }
 217.161 +
 217.162 +    /**
 217.163 +     * Returns an <code>Enumeration</code> of the keys contained in
 217.164 +     * this <code>ResourceBundle</code> and its parent bundles.
 217.165 +     *
 217.166 +     * @return an <code>Enumeration</code> of the keys contained in
 217.167 +     *         this <code>ResourceBundle</code> and its parent bundles.
 217.168 +     * @see #keySet()
 217.169 +     */
 217.170 +    public Enumeration<String> getKeys() {
 217.171 +        ResourceBundle parent = this.parent;
 217.172 +        return new ResourceBundleEnumeration(lookup.keySet(),
 217.173 +                (parent != null) ? parent.getKeys() : null);
 217.174 +    }
 217.175 +
 217.176 +    /**
 217.177 +     * Returns a <code>Set</code> of the keys contained
 217.178 +     * <em>only</em> in this <code>ResourceBundle</code>.
 217.179 +     *
 217.180 +     * @return a <code>Set</code> of the keys contained only in this
 217.181 +     *         <code>ResourceBundle</code>
 217.182 +     * @since 1.6
 217.183 +     * @see #keySet()
 217.184 +     */
 217.185 +    protected Set<String> handleKeySet() {
 217.186 +        return lookup.keySet();
 217.187 +    }
 217.188 +
 217.189 +    // ==================privates====================
 217.190 +
 217.191 +    private Map<String,Object> lookup;
 217.192 +    
 217.193 +
 217.194 +    /**
 217.195 +     * Implements an Enumeration that combines elements from a Set and
 217.196 +     * an Enumeration. Used by ListResourceBundle and PropertyResourceBundle.
 217.197 +     */
 217.198 +    static class ResourceBundleEnumeration implements Enumeration<String> {
 217.199 +
 217.200 +        Set<String> set;
 217.201 +        Iterator<String> iterator;
 217.202 +        Enumeration<String> enumeration; // may remain null
 217.203 +
 217.204 +        /**
 217.205 +         * Constructs a resource bundle enumeration.
 217.206 +         * @param set an set providing some elements of the enumeration
 217.207 +         * @param enumeration an enumeration providing more elements of the enumeration.
 217.208 +         *        enumeration may be null.
 217.209 +         */
 217.210 +        public ResourceBundleEnumeration(Set<String> set, Enumeration<String> enumeration) {
 217.211 +            this.set = set;
 217.212 +            this.iterator = set.iterator();
 217.213 +            this.enumeration = enumeration;
 217.214 +        }
 217.215 +
 217.216 +        String next = null;
 217.217 +
 217.218 +        public boolean hasMoreElements() {
 217.219 +            if (next == null) {
 217.220 +                if (iterator.hasNext()) {
 217.221 +                    next = iterator.next();
 217.222 +                } else if (enumeration != null) {
 217.223 +                    while (next == null && enumeration.hasMoreElements()) {
 217.224 +                        next = enumeration.nextElement();
 217.225 +                        if (set.contains(next)) {
 217.226 +                            next = null;
 217.227 +                        }
 217.228 +                    }
 217.229 +                }
 217.230 +            }
 217.231 +            return next != null;
 217.232 +        }
 217.233 +
 217.234 +        public String nextElement() {
 217.235 +            if (hasMoreElements()) {
 217.236 +                String result = next;
 217.237 +                next = null;
 217.238 +                return result;
 217.239 +            } else {
 217.240 +                throw new NoSuchElementException();
 217.241 +            }
 217.242 +        }
 217.243 +    }
 217.244 +    
 217.245 +}
   218.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   218.2 +++ b/rt/emul/compact/src/main/java/java/util/RegularEnumSet.java	Wed Apr 30 15:04:10 2014 +0200
   218.3 @@ -0,0 +1,303 @@
   218.4 +/*
   218.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   218.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   218.7 + *
   218.8 + * This code is free software; you can redistribute it and/or modify it
   218.9 + * under the terms of the GNU General Public License version 2 only, as
  218.10 + * published by the Free Software Foundation.  Oracle designates this
  218.11 + * particular file as subject to the "Classpath" exception as provided
  218.12 + * by Oracle in the LICENSE file that accompanied this code.
  218.13 + *
  218.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  218.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  218.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  218.17 + * version 2 for more details (a copy is included in the LICENSE file that
  218.18 + * accompanied this code).
  218.19 + *
  218.20 + * You should have received a copy of the GNU General Public License version
  218.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  218.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  218.23 + *
  218.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  218.25 + * or visit www.oracle.com if you need additional information or have any
  218.26 + * questions.
  218.27 + */
  218.28 +
  218.29 +package java.util;
  218.30 +
  218.31 +/**
  218.32 + * Private implementation class for EnumSet, for "regular sized" enum types
  218.33 + * (i.e., those with 64 or fewer enum constants).
  218.34 + *
  218.35 + * @author Josh Bloch
  218.36 + * @since 1.5
  218.37 + * @serial exclude
  218.38 + */
  218.39 +class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
  218.40 +    private static final long serialVersionUID = 3411599620347842686L;
  218.41 +    /**
  218.42 +     * Bit vector representation of this set.  The 2^k bit indicates the
  218.43 +     * presence of universe[k] in this set.
  218.44 +     */
  218.45 +    private long elements = 0L;
  218.46 +
  218.47 +    RegularEnumSet(Class<E>elementType, Enum[] universe) {
  218.48 +        super(elementType, universe);
  218.49 +    }
  218.50 +
  218.51 +    void addRange(E from, E to) {
  218.52 +        elements = (-1L >>>  (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
  218.53 +    }
  218.54 +
  218.55 +    void addAll() {
  218.56 +        if (universe.length != 0)
  218.57 +            elements = -1L >>> -universe.length;
  218.58 +    }
  218.59 +
  218.60 +    void complement() {
  218.61 +        if (universe.length != 0) {
  218.62 +            elements = ~elements;
  218.63 +            elements &= -1L >>> -universe.length;  // Mask unused bits
  218.64 +        }
  218.65 +    }
  218.66 +
  218.67 +    /**
  218.68 +     * Returns an iterator over the elements contained in this set.  The
  218.69 +     * iterator traverses the elements in their <i>natural order</i> (which is
  218.70 +     * the order in which the enum constants are declared). The returned
  218.71 +     * Iterator is a "snapshot" iterator that will never throw {@link
  218.72 +     * ConcurrentModificationException}; the elements are traversed as they
  218.73 +     * existed when this call was invoked.
  218.74 +     *
  218.75 +     * @return an iterator over the elements contained in this set
  218.76 +     */
  218.77 +    public Iterator<E> iterator() {
  218.78 +        return new EnumSetIterator<>();
  218.79 +    }
  218.80 +
  218.81 +    private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
  218.82 +        /**
  218.83 +         * A bit vector representing the elements in the set not yet
  218.84 +         * returned by this iterator.
  218.85 +         */
  218.86 +        long unseen;
  218.87 +
  218.88 +        /**
  218.89 +         * The bit representing the last element returned by this iterator
  218.90 +         * but not removed, or zero if no such element exists.
  218.91 +         */
  218.92 +        long lastReturned = 0;
  218.93 +
  218.94 +        EnumSetIterator() {
  218.95 +            unseen = elements;
  218.96 +        }
  218.97 +
  218.98 +        public boolean hasNext() {
  218.99 +            return unseen != 0;
 218.100 +        }
 218.101 +
 218.102 +        public E next() {
 218.103 +            if (unseen == 0)
 218.104 +                throw new NoSuchElementException();
 218.105 +            lastReturned = unseen & -unseen;
 218.106 +            unseen -= lastReturned;
 218.107 +            return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
 218.108 +        }
 218.109 +
 218.110 +        public void remove() {
 218.111 +            if (lastReturned == 0)
 218.112 +                throw new IllegalStateException();
 218.113 +            elements &= ~lastReturned;
 218.114 +            lastReturned = 0;
 218.115 +        }
 218.116 +    }
 218.117 +
 218.118 +    /**
 218.119 +     * Returns the number of elements in this set.
 218.120 +     *
 218.121 +     * @return the number of elements in this set
 218.122 +     */
 218.123 +    public int size() {
 218.124 +        return Long.bitCount(elements);
 218.125 +    }
 218.126 +
 218.127 +    /**
 218.128 +     * Returns <tt>true</tt> if this set contains no elements.
 218.129 +     *
 218.130 +     * @return <tt>true</tt> if this set contains no elements
 218.131 +     */
 218.132 +    public boolean isEmpty() {
 218.133 +        return elements == 0;
 218.134 +    }
 218.135 +
 218.136 +    /**
 218.137 +     * Returns <tt>true</tt> if this set contains the specified element.
 218.138 +     *
 218.139 +     * @param e element to be checked for containment in this collection
 218.140 +     * @return <tt>true</tt> if this set contains the specified element
 218.141 +     */
 218.142 +    public boolean contains(Object e) {
 218.143 +        if (e == null)
 218.144 +            return false;
 218.145 +        Class eClass = e.getClass();
 218.146 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 218.147 +            return false;
 218.148 +
 218.149 +        return (elements & (1L << ((Enum)e).ordinal())) != 0;
 218.150 +    }
 218.151 +
 218.152 +    // Modification Operations
 218.153 +
 218.154 +    /**
 218.155 +     * Adds the specified element to this set if it is not already present.
 218.156 +     *
 218.157 +     * @param e element to be added to this set
 218.158 +     * @return <tt>true</tt> if the set changed as a result of the call
 218.159 +     *
 218.160 +     * @throws NullPointerException if <tt>e</tt> is null
 218.161 +     */
 218.162 +    public boolean add(E e) {
 218.163 +        typeCheck(e);
 218.164 +
 218.165 +        long oldElements = elements;
 218.166 +        elements |= (1L << ((Enum)e).ordinal());
 218.167 +        return elements != oldElements;
 218.168 +    }
 218.169 +
 218.170 +    /**
 218.171 +     * Removes the specified element from this set if it is present.
 218.172 +     *
 218.173 +     * @param e element to be removed from this set, if present
 218.174 +     * @return <tt>true</tt> if the set contained the specified element
 218.175 +     */
 218.176 +    public boolean remove(Object e) {
 218.177 +        if (e == null)
 218.178 +            return false;
 218.179 +        Class eClass = e.getClass();
 218.180 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 218.181 +            return false;
 218.182 +
 218.183 +        long oldElements = elements;
 218.184 +        elements &= ~(1L << ((Enum)e).ordinal());
 218.185 +        return elements != oldElements;
 218.186 +    }
 218.187 +
 218.188 +    // Bulk Operations
 218.189 +
 218.190 +    /**
 218.191 +     * Returns <tt>true</tt> if this set contains all of the elements
 218.192 +     * in the specified collection.
 218.193 +     *
 218.194 +     * @param c collection to be checked for containment in this set
 218.195 +     * @return <tt>true</tt> if this set contains all of the elements
 218.196 +     *        in the specified collection
 218.197 +     * @throws NullPointerException if the specified collection is null
 218.198 +     */
 218.199 +    public boolean containsAll(Collection<?> c) {
 218.200 +        if (!(c instanceof RegularEnumSet))
 218.201 +            return super.containsAll(c);
 218.202 +
 218.203 +        RegularEnumSet es = (RegularEnumSet)c;
 218.204 +        if (es.elementType != elementType)
 218.205 +            return es.isEmpty();
 218.206 +
 218.207 +        return (es.elements & ~elements) == 0;
 218.208 +    }
 218.209 +
 218.210 +    /**
 218.211 +     * Adds all of the elements in the specified collection to this set.
 218.212 +     *
 218.213 +     * @param c collection whose elements are to be added to this set
 218.214 +     * @return <tt>true</tt> if this set changed as a result of the call
 218.215 +     * @throws NullPointerException if the specified collection or any
 218.216 +     *     of its elements are null
 218.217 +     */
 218.218 +    public boolean addAll(Collection<? extends E> c) {
 218.219 +        if (!(c instanceof RegularEnumSet))
 218.220 +            return super.addAll(c);
 218.221 +
 218.222 +        RegularEnumSet es = (RegularEnumSet)c;
 218.223 +        if (es.elementType != elementType) {
 218.224 +            if (es.isEmpty())
 218.225 +                return false;
 218.226 +            else
 218.227 +                throw new ClassCastException(
 218.228 +                    es.elementType + " != " + elementType);
 218.229 +        }
 218.230 +
 218.231 +        long oldElements = elements;
 218.232 +        elements |= es.elements;
 218.233 +        return elements != oldElements;
 218.234 +    }
 218.235 +
 218.236 +    /**
 218.237 +     * Removes from this set all of its elements that are contained in
 218.238 +     * the specified collection.
 218.239 +     *
 218.240 +     * @param c elements to be removed from this set
 218.241 +     * @return <tt>true</tt> if this set changed as a result of the call
 218.242 +     * @throws NullPointerException if the specified collection is null
 218.243 +     */
 218.244 +    public boolean removeAll(Collection<?> c) {
 218.245 +        if (!(c instanceof RegularEnumSet))
 218.246 +            return super.removeAll(c);
 218.247 +
 218.248 +        RegularEnumSet es = (RegularEnumSet)c;
 218.249 +        if (es.elementType != elementType)
 218.250 +            return false;
 218.251 +
 218.252 +        long oldElements = elements;
 218.253 +        elements &= ~es.elements;
 218.254 +        return elements != oldElements;
 218.255 +    }
 218.256 +
 218.257 +    /**
 218.258 +     * Retains only the elements in this set that are contained in the
 218.259 +     * specified collection.
 218.260 +     *
 218.261 +     * @param c elements to be retained in this set
 218.262 +     * @return <tt>true</tt> if this set changed as a result of the call
 218.263 +     * @throws NullPointerException if the specified collection is null
 218.264 +     */
 218.265 +    public boolean retainAll(Collection<?> c) {
 218.266 +        if (!(c instanceof RegularEnumSet))
 218.267 +            return super.retainAll(c);
 218.268 +
 218.269 +        RegularEnumSet<?> es = (RegularEnumSet<?>)c;
 218.270 +        if (es.elementType != elementType) {
 218.271 +            boolean changed = (elements != 0);
 218.272 +            elements = 0;
 218.273 +            return changed;
 218.274 +        }
 218.275 +
 218.276 +        long oldElements = elements;
 218.277 +        elements &= es.elements;
 218.278 +        return elements != oldElements;
 218.279 +    }
 218.280 +
 218.281 +    /**
 218.282 +     * Removes all of the elements from this set.
 218.283 +     */
 218.284 +    public void clear() {
 218.285 +        elements = 0;
 218.286 +    }
 218.287 +
 218.288 +    /**
 218.289 +     * Compares the specified object with this set for equality.  Returns
 218.290 +     * <tt>true</tt> if the given object is also a set, the two sets have
 218.291 +     * the same size, and every member of the given set is contained in
 218.292 +     * this set.
 218.293 +     *
 218.294 +     * @param e object to be compared for equality with this set
 218.295 +     * @return <tt>true</tt> if the specified object is equal to this set
 218.296 +     */
 218.297 +    public boolean equals(Object o) {
 218.298 +        if (!(o instanceof RegularEnumSet))
 218.299 +            return super.equals(o);
 218.300 +
 218.301 +        RegularEnumSet es = (RegularEnumSet)o;
 218.302 +        if (es.elementType != elementType)
 218.303 +            return elements == 0 && es.elements == 0;
 218.304 +        return es.elements == elements;
 218.305 +    }
 218.306 +}
   219.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   219.2 +++ b/rt/emul/compact/src/main/java/java/util/ResourceBundle.java	Wed Apr 30 15:04:10 2014 +0200
   219.3 @@ -0,0 +1,2778 @@
   219.4 +/*
   219.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   219.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   219.7 + *
   219.8 + * This code is free software; you can redistribute it and/or modify it
   219.9 + * under the terms of the GNU General Public License version 2 only, as
  219.10 + * published by the Free Software Foundation.  Oracle designates this
  219.11 + * particular file as subject to the "Classpath" exception as provided
  219.12 + * by Oracle in the LICENSE file that accompanied this code.
  219.13 + *
  219.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  219.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  219.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  219.17 + * version 2 for more details (a copy is included in the LICENSE file that
  219.18 + * accompanied this code).
  219.19 + *
  219.20 + * You should have received a copy of the GNU General Public License version
  219.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  219.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  219.23 + *
  219.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  219.25 + * or visit www.oracle.com if you need additional information or have any
  219.26 + * questions.
  219.27 + */
  219.28 +
  219.29 +/*
  219.30 + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  219.31 + * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
  219.32 + *
  219.33 + * The original version of this source code and documentation
  219.34 + * is copyrighted and owned by Taligent, Inc., a wholly-owned
  219.35 + * subsidiary of IBM. These materials are provided under terms
  219.36 + * of a License Agreement between Taligent and Sun. This technology
  219.37 + * is protected by multiple US and International patents.
  219.38 + *
  219.39 + * This notice and attribution to Taligent may not be removed.
  219.40 + * Taligent is a registered trademark of Taligent, Inc.
  219.41 + *
  219.42 + */
  219.43 +
  219.44 +package java.util;
  219.45 +
  219.46 +import java.io.IOException;
  219.47 +import java.io.InputStream;
  219.48 +import java.lang.ref.ReferenceQueue;
  219.49 +import java.lang.ref.SoftReference;
  219.50 +import java.lang.ref.WeakReference;
  219.51 +import java.net.URL;
  219.52 +
  219.53 +
  219.54 +/**
  219.55 + *
  219.56 + * Resource bundles contain locale-specific objects.  When your program needs a
  219.57 + * locale-specific resource, a <code>String</code> for example, your program can
  219.58 + * load it from the resource bundle that is appropriate for the current user's
  219.59 + * locale. In this way, you can write program code that is largely independent
  219.60 + * of the user's locale isolating most, if not all, of the locale-specific
  219.61 + * information in resource bundles.
  219.62 + *
  219.63 + * <p>
  219.64 + * This allows you to write programs that can:
  219.65 + * <UL type=SQUARE>
  219.66 + * <LI> be easily localized, or translated, into different languages
  219.67 + * <LI> handle multiple locales at once
  219.68 + * <LI> be easily modified later to support even more locales
  219.69 + * </UL>
  219.70 + *
  219.71 + * <P>
  219.72 + * Resource bundles belong to families whose members share a common base
  219.73 + * name, but whose names also have additional components that identify
  219.74 + * their locales. For example, the base name of a family of resource
  219.75 + * bundles might be "MyResources". The family should have a default
  219.76 + * resource bundle which simply has the same name as its family -
  219.77 + * "MyResources" - and will be used as the bundle of last resort if a
  219.78 + * specific locale is not supported. The family can then provide as
  219.79 + * many locale-specific members as needed, for example a German one
  219.80 + * named "MyResources_de".
  219.81 + *
  219.82 + * <P>
  219.83 + * Each resource bundle in a family contains the same items, but the items have
  219.84 + * been translated for the locale represented by that resource bundle.
  219.85 + * For example, both "MyResources" and "MyResources_de" may have a
  219.86 + * <code>String</code> that's used on a button for canceling operations.
  219.87 + * In "MyResources" the <code>String</code> may contain "Cancel" and in
  219.88 + * "MyResources_de" it may contain "Abbrechen".
  219.89 + *
  219.90 + * <P>
  219.91 + * If there are different resources for different countries, you
  219.92 + * can make specializations: for example, "MyResources_de_CH" contains objects for
  219.93 + * the German language (de) in Switzerland (CH). If you want to only
  219.94 + * modify some of the resources
  219.95 + * in the specialization, you can do so.
  219.96 + *
  219.97 + * <P>
  219.98 + * When your program needs a locale-specific object, it loads
  219.99 + * the <code>ResourceBundle</code> class using the
 219.100 + * {@link #getBundle(java.lang.String, java.util.Locale) getBundle}
 219.101 + * method:
 219.102 + * <blockquote>
 219.103 + * <pre>
 219.104 + * ResourceBundle myResources =
 219.105 + *      ResourceBundle.getBundle("MyResources", currentLocale);
 219.106 + * </pre>
 219.107 + * </blockquote>
 219.108 + *
 219.109 + * <P>
 219.110 + * Resource bundles contain key/value pairs. The keys uniquely
 219.111 + * identify a locale-specific object in the bundle. Here's an
 219.112 + * example of a <code>ListResourceBundle</code> that contains
 219.113 + * two key/value pairs:
 219.114 + * <blockquote>
 219.115 + * <pre>
 219.116 + * public class MyResources extends ListResourceBundle {
 219.117 + *     protected Object[][] getContents() {
 219.118 + *         return new Object[][] {
 219.119 + *             // LOCALIZE THE SECOND STRING OF EACH ARRAY (e.g., "OK")
 219.120 + *             {"OkKey", "OK"},
 219.121 + *             {"CancelKey", "Cancel"},
 219.122 + *             // END OF MATERIAL TO LOCALIZE
 219.123 + *        };
 219.124 + *     }
 219.125 + * }
 219.126 + * </pre>
 219.127 + * </blockquote>
 219.128 + * Keys are always <code>String</code>s.
 219.129 + * In this example, the keys are "OkKey" and "CancelKey".
 219.130 + * In the above example, the values
 219.131 + * are also <code>String</code>s--"OK" and "Cancel"--but
 219.132 + * they don't have to be. The values can be any type of object.
 219.133 + *
 219.134 + * <P>
 219.135 + * You retrieve an object from resource bundle using the appropriate
 219.136 + * getter method. Because "OkKey" and "CancelKey"
 219.137 + * are both strings, you would use <code>getString</code> to retrieve them:
 219.138 + * <blockquote>
 219.139 + * <pre>
 219.140 + * button1 = new Button(myResources.getString("OkKey"));
 219.141 + * button2 = new Button(myResources.getString("CancelKey"));
 219.142 + * </pre>
 219.143 + * </blockquote>
 219.144 + * The getter methods all require the key as an argument and return
 219.145 + * the object if found. If the object is not found, the getter method
 219.146 + * throws a <code>MissingResourceException</code>.
 219.147 + *
 219.148 + * <P>
 219.149 + * Besides <code>getString</code>, <code>ResourceBundle</code> also provides
 219.150 + * a method for getting string arrays, <code>getStringArray</code>,
 219.151 + * as well as a generic <code>getObject</code> method for any other
 219.152 + * type of object. When using <code>getObject</code>, you'll
 219.153 + * have to cast the result to the appropriate type. For example:
 219.154 + * <blockquote>
 219.155 + * <pre>
 219.156 + * int[] myIntegers = (int[]) myResources.getObject("intList");
 219.157 + * </pre>
 219.158 + * </blockquote>
 219.159 + *
 219.160 + * <P>
 219.161 + * The Java Platform provides two subclasses of <code>ResourceBundle</code>,
 219.162 + * <code>ListResourceBundle</code> and <code>PropertyResourceBundle</code>,
 219.163 + * that provide a fairly simple way to create resources.
 219.164 + * As you saw briefly in a previous example, <code>ListResourceBundle</code>
 219.165 + * manages its resource as a list of key/value pairs.
 219.166 + * <code>PropertyResourceBundle</code> uses a properties file to manage
 219.167 + * its resources.
 219.168 + *
 219.169 + * <p>
 219.170 + * If <code>ListResourceBundle</code> or <code>PropertyResourceBundle</code>
 219.171 + * do not suit your needs, you can write your own <code>ResourceBundle</code>
 219.172 + * subclass.  Your subclasses must override two methods: <code>handleGetObject</code>
 219.173 + * and <code>getKeys()</code>.
 219.174 + *
 219.175 + * <h4>ResourceBundle.Control</h4>
 219.176 + *
 219.177 + * The {@link ResourceBundle.Control} class provides information necessary
 219.178 + * to perform the bundle loading process by the <code>getBundle</code>
 219.179 + * factory methods that take a <code>ResourceBundle.Control</code>
 219.180 + * instance. You can implement your own subclass in order to enable
 219.181 + * non-standard resource bundle formats, change the search strategy, or
 219.182 + * define caching parameters. Refer to the descriptions of the class and the
 219.183 + * {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
 219.184 + * factory method for details.
 219.185 + *
 219.186 + * <h4>Cache Management</h4>
 219.187 + *
 219.188 + * Resource bundle instances created by the <code>getBundle</code> factory
 219.189 + * methods are cached by default, and the factory methods return the same
 219.190 + * resource bundle instance multiple times if it has been
 219.191 + * cached. <code>getBundle</code> clients may clear the cache, manage the
 219.192 + * lifetime of cached resource bundle instances using time-to-live values,
 219.193 + * or specify not to cache resource bundle instances. Refer to the
 219.194 + * descriptions of the {@linkplain #getBundle(String, Locale, ClassLoader,
 219.195 + * Control) <code>getBundle</code> factory method}, {@link
 219.196 + * #clearCache(ClassLoader) clearCache}, {@link
 219.197 + * Control#getTimeToLive(String, Locale)
 219.198 + * ResourceBundle.Control.getTimeToLive}, and {@link
 219.199 + * Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
 219.200 + * long) ResourceBundle.Control.needsReload} for details.
 219.201 + *
 219.202 + * <h4>Example</h4>
 219.203 + *
 219.204 + * The following is a very simple example of a <code>ResourceBundle</code>
 219.205 + * subclass, <code>MyResources</code>, that manages two resources (for a larger number of
 219.206 + * resources you would probably use a <code>Map</code>).
 219.207 + * Notice that you don't need to supply a value if
 219.208 + * a "parent-level" <code>ResourceBundle</code> handles the same
 219.209 + * key with the same value (as for the okKey below).
 219.210 + * <blockquote>
 219.211 + * <pre>
 219.212 + * // default (English language, United States)
 219.213 + * public class MyResources extends ResourceBundle {
 219.214 + *     public Object handleGetObject(String key) {
 219.215 + *         if (key.equals("okKey")) return "Ok";
 219.216 + *         if (key.equals("cancelKey")) return "Cancel";
 219.217 + *         return null;
 219.218 + *     }
 219.219 + *
 219.220 + *     public Enumeration&lt;String&gt; getKeys() {
 219.221 + *         return Collections.enumeration(keySet());
 219.222 + *     }
 219.223 + *
 219.224 + *     // Overrides handleKeySet() so that the getKeys() implementation
 219.225 + *     // can rely on the keySet() value.
 219.226 + *     protected Set&lt;String&gt; handleKeySet() {
 219.227 + *         return new HashSet&lt;String&gt;(Arrays.asList("okKey", "cancelKey"));
 219.228 + *     }
 219.229 + * }
 219.230 + *
 219.231 + * // German language
 219.232 + * public class MyResources_de extends MyResources {
 219.233 + *     public Object handleGetObject(String key) {
 219.234 + *         // don't need okKey, since parent level handles it.
 219.235 + *         if (key.equals("cancelKey")) return "Abbrechen";
 219.236 + *         return null;
 219.237 + *     }
 219.238 + *
 219.239 + *     protected Set&lt;String&gt; handleKeySet() {
 219.240 + *         return new HashSet&lt;String&gt;(Arrays.asList("cancelKey"));
 219.241 + *     }
 219.242 + * }
 219.243 + * </pre>
 219.244 + * </blockquote>
 219.245 + * You do not have to restrict yourself to using a single family of
 219.246 + * <code>ResourceBundle</code>s. For example, you could have a set of bundles for
 219.247 + * exception messages, <code>ExceptionResources</code>
 219.248 + * (<code>ExceptionResources_fr</code>, <code>ExceptionResources_de</code>, ...),
 219.249 + * and one for widgets, <code>WidgetResource</code> (<code>WidgetResources_fr</code>,
 219.250 + * <code>WidgetResources_de</code>, ...); breaking up the resources however you like.
 219.251 + *
 219.252 + * @see ListResourceBundle
 219.253 + * @see PropertyResourceBundle
 219.254 + * @see MissingResourceException
 219.255 + * @since JDK1.1
 219.256 + */
 219.257 +public abstract class ResourceBundle {
 219.258 +
 219.259 +    /** initial size of the bundle cache */
 219.260 +    private static final int INITIAL_CACHE_SIZE = 32;
 219.261 +
 219.262 +    /** constant indicating that no resource bundle exists */
 219.263 +    private static final ResourceBundle NONEXISTENT_BUNDLE = new ResourceBundle() {
 219.264 +            public Enumeration<String> getKeys() { return null; }
 219.265 +            protected Object handleGetObject(String key) { return null; }
 219.266 +            public String toString() { return "NONEXISTENT_BUNDLE"; }
 219.267 +        };
 219.268 +
 219.269 +
 219.270 +    /**
 219.271 +     * The cache is a map from cache keys (with bundle base name, locale, and
 219.272 +     * class loader) to either a resource bundle or NONEXISTENT_BUNDLE wrapped by a
 219.273 +     * BundleReference.
 219.274 +     *
 219.275 +     * The cache is a ConcurrentMap, allowing the cache to be searched
 219.276 +     * concurrently by multiple threads.  This will also allow the cache keys
 219.277 +     * to be reclaimed along with the ClassLoaders they reference.
 219.278 +     *
 219.279 +     * This variable would be better named "cache", but we keep the old
 219.280 +     * name for compatibility with some workarounds for bug 4212439.
 219.281 +     */
 219.282 +    private static final Map<CacheKey, BundleReference> cacheList
 219.283 +        = new HashMap<>(INITIAL_CACHE_SIZE);
 219.284 +
 219.285 +    /**
 219.286 +     * Queue for reference objects referring to class loaders or bundles.
 219.287 +     */
 219.288 +    private static final ReferenceQueue referenceQueue = new ReferenceQueue();
 219.289 +
 219.290 +    /**
 219.291 +     * The parent bundle of this bundle.
 219.292 +     * The parent bundle is searched by {@link #getObject getObject}
 219.293 +     * when this bundle does not contain a particular resource.
 219.294 +     */
 219.295 +    protected ResourceBundle parent = null;
 219.296 +
 219.297 +    /**
 219.298 +     * The locale for this bundle.
 219.299 +     */
 219.300 +    private Locale locale = null;
 219.301 +
 219.302 +    /**
 219.303 +     * The base bundle name for this bundle.
 219.304 +     */
 219.305 +    private String name;
 219.306 +
 219.307 +    /**
 219.308 +     * The flag indicating this bundle has expired in the cache.
 219.309 +     */
 219.310 +    private volatile boolean expired;
 219.311 +
 219.312 +    /**
 219.313 +     * The back link to the cache key. null if this bundle isn't in
 219.314 +     * the cache (yet) or has expired.
 219.315 +     */
 219.316 +    private volatile CacheKey cacheKey;
 219.317 +
 219.318 +    /**
 219.319 +     * A Set of the keys contained only in this ResourceBundle.
 219.320 +     */
 219.321 +    private volatile Set<String> keySet;
 219.322 +
 219.323 +    /**
 219.324 +     * Sole constructor.  (For invocation by subclass constructors, typically
 219.325 +     * implicit.)
 219.326 +     */
 219.327 +    public ResourceBundle() {
 219.328 +    }
 219.329 +
 219.330 +    /**
 219.331 +     * Gets a string for the given key from this resource bundle or one of its parents.
 219.332 +     * Calling this method is equivalent to calling
 219.333 +     * <blockquote>
 219.334 +     * <code>(String) {@link #getObject(java.lang.String) getObject}(key)</code>.
 219.335 +     * </blockquote>
 219.336 +     *
 219.337 +     * @param key the key for the desired string
 219.338 +     * @exception NullPointerException if <code>key</code> is <code>null</code>
 219.339 +     * @exception MissingResourceException if no object for the given key can be found
 219.340 +     * @exception ClassCastException if the object found for the given key is not a string
 219.341 +     * @return the string for the given key
 219.342 +     */
 219.343 +    public final String getString(String key) {
 219.344 +        return (String) getObject(key);
 219.345 +    }
 219.346 +
 219.347 +    /**
 219.348 +     * Gets a string array for the given key from this resource bundle or one of its parents.
 219.349 +     * Calling this method is equivalent to calling
 219.350 +     * <blockquote>
 219.351 +     * <code>(String[]) {@link #getObject(java.lang.String) getObject}(key)</code>.
 219.352 +     * </blockquote>
 219.353 +     *
 219.354 +     * @param key the key for the desired string array
 219.355 +     * @exception NullPointerException if <code>key</code> is <code>null</code>
 219.356 +     * @exception MissingResourceException if no object for the given key can be found
 219.357 +     * @exception ClassCastException if the object found for the given key is not a string array
 219.358 +     * @return the string array for the given key
 219.359 +     */
 219.360 +    public final String[] getStringArray(String key) {
 219.361 +        return (String[]) getObject(key);
 219.362 +    }
 219.363 +
 219.364 +    /**
 219.365 +     * Gets an object for the given key from this resource bundle or one of its parents.
 219.366 +     * This method first tries to obtain the object from this resource bundle using
 219.367 +     * {@link #handleGetObject(java.lang.String) handleGetObject}.
 219.368 +     * If not successful, and the parent resource bundle is not null,
 219.369 +     * it calls the parent's <code>getObject</code> method.
 219.370 +     * If still not successful, it throws a MissingResourceException.
 219.371 +     *
 219.372 +     * @param key the key for the desired object
 219.373 +     * @exception NullPointerException if <code>key</code> is <code>null</code>
 219.374 +     * @exception MissingResourceException if no object for the given key can be found
 219.375 +     * @return the object for the given key
 219.376 +     */
 219.377 +    public final Object getObject(String key) {
 219.378 +        Object obj = handleGetObject(key);
 219.379 +        if (obj == null) {
 219.380 +            if (parent != null) {
 219.381 +                obj = parent.getObject(key);
 219.382 +            }
 219.383 +            if (obj == null)
 219.384 +                throw new MissingResourceException("Can't find resource for bundle "
 219.385 +                                                   +this.getClass().getName()
 219.386 +                                                   +", key "+key,
 219.387 +                                                   this.getClass().getName(),
 219.388 +                                                   key);
 219.389 +        }
 219.390 +        return obj;
 219.391 +    }
 219.392 +
 219.393 +    /**
 219.394 +     * Returns the locale of this resource bundle. This method can be used after a
 219.395 +     * call to getBundle() to determine whether the resource bundle returned really
 219.396 +     * corresponds to the requested locale or is a fallback.
 219.397 +     *
 219.398 +     * @return the locale of this resource bundle
 219.399 +     */
 219.400 +    public Locale getLocale() {
 219.401 +        return locale;
 219.402 +    }
 219.403 +
 219.404 +    /**
 219.405 +     * Sets the parent bundle of this bundle.
 219.406 +     * The parent bundle is searched by {@link #getObject getObject}
 219.407 +     * when this bundle does not contain a particular resource.
 219.408 +     *
 219.409 +     * @param parent this bundle's parent bundle.
 219.410 +     */
 219.411 +    protected void setParent(ResourceBundle parent) {
 219.412 +        assert parent != NONEXISTENT_BUNDLE;
 219.413 +        this.parent = parent;
 219.414 +    }
 219.415 +
 219.416 +    /**
 219.417 +     * Key used for cached resource bundles.  The key checks the base
 219.418 +     * name, the locale, and the class loader to determine if the
 219.419 +     * resource is a match to the requested one. The loader may be
 219.420 +     * null, but the base name and the locale must have a non-null
 219.421 +     * value.
 219.422 +     */
 219.423 +    private static final class CacheKey implements Cloneable {
 219.424 +        // These three are the actual keys for lookup in Map.
 219.425 +        private String name;
 219.426 +        private Locale locale;
 219.427 +
 219.428 +        // bundle format which is necessary for calling
 219.429 +        // Control.needsReload().
 219.430 +        private String format;
 219.431 +
 219.432 +        // These time values are in CacheKey so that NONEXISTENT_BUNDLE
 219.433 +        // doesn't need to be cloned for caching.
 219.434 +
 219.435 +        // The time when the bundle has been loaded
 219.436 +        private volatile long loadTime;
 219.437 +
 219.438 +        // The time when the bundle expires in the cache, or either
 219.439 +        // Control.TTL_DONT_CACHE or Control.TTL_NO_EXPIRATION_CONTROL.
 219.440 +        private volatile long expirationTime;
 219.441 +
 219.442 +        // Placeholder for an error report by a Throwable
 219.443 +        private Throwable cause;
 219.444 +
 219.445 +        // Hash code value cache to avoid recalculating the hash code
 219.446 +        // of this instance.
 219.447 +        private int hashCodeCache;
 219.448 +
 219.449 +        CacheKey(String baseName, Locale locale) {
 219.450 +            this.name = baseName;
 219.451 +            this.locale = locale;
 219.452 +            calculateHashCode();
 219.453 +        }
 219.454 +
 219.455 +        String getName() {
 219.456 +            return name;
 219.457 +        }
 219.458 +
 219.459 +        CacheKey setName(String baseName) {
 219.460 +            if (!this.name.equals(baseName)) {
 219.461 +                this.name = baseName;
 219.462 +                calculateHashCode();
 219.463 +            }
 219.464 +            return this;
 219.465 +        }
 219.466 +
 219.467 +        Locale getLocale() {
 219.468 +            return locale;
 219.469 +        }
 219.470 +
 219.471 +        CacheKey setLocale(Locale locale) {
 219.472 +            if (!this.locale.equals(locale)) {
 219.473 +                this.locale = locale;
 219.474 +                calculateHashCode();
 219.475 +            }
 219.476 +            return this;
 219.477 +        }
 219.478 +
 219.479 +        public boolean equals(Object other) {
 219.480 +            if (this == other) {
 219.481 +                return true;
 219.482 +            }
 219.483 +            try {
 219.484 +                final CacheKey otherEntry = (CacheKey)other;
 219.485 +                //quick check to see if they are not equal
 219.486 +                if (hashCodeCache != otherEntry.hashCodeCache) {
 219.487 +                    return false;
 219.488 +                }
 219.489 +                //are the names the same?
 219.490 +                if (!name.equals(otherEntry.name)) {
 219.491 +                    return false;
 219.492 +                }
 219.493 +                // are the locales the same?
 219.494 +                if (!locale.equals(otherEntry.locale)) {
 219.495 +                    return false;
 219.496 +                }
 219.497 +                return true;
 219.498 +            } catch (NullPointerException e) {
 219.499 +            } catch (ClassCastException e) {
 219.500 +            }
 219.501 +            return false;
 219.502 +        }
 219.503 +
 219.504 +        public int hashCode() {
 219.505 +            return hashCodeCache;
 219.506 +        }
 219.507 +
 219.508 +        private void calculateHashCode() {
 219.509 +            hashCodeCache = name.hashCode() << 3;
 219.510 +            hashCodeCache ^= locale.hashCode();
 219.511 +        }
 219.512 +
 219.513 +        public Object clone() {
 219.514 +            try {
 219.515 +                CacheKey clone = (CacheKey) super.clone();
 219.516 +                // Clear the reference to a Throwable
 219.517 +                clone.cause = null;
 219.518 +                return clone;
 219.519 +            } catch (CloneNotSupportedException e) {
 219.520 +                //this should never happen
 219.521 +                throw new InternalError();
 219.522 +            }
 219.523 +        }
 219.524 +
 219.525 +        String getFormat() {
 219.526 +            return format;
 219.527 +        }
 219.528 +
 219.529 +        void setFormat(String format) {
 219.530 +            this.format = format;
 219.531 +        }
 219.532 +
 219.533 +        private void setCause(Throwable cause) {
 219.534 +            if (this.cause == null) {
 219.535 +                this.cause = cause;
 219.536 +            } else {
 219.537 +                // Override the cause if the previous one is
 219.538 +                // ClassNotFoundException.
 219.539 +                if (this.cause instanceof ClassNotFoundException) {
 219.540 +                    this.cause = cause;
 219.541 +                }
 219.542 +            }
 219.543 +        }
 219.544 +
 219.545 +        private Throwable getCause() {
 219.546 +            return cause;
 219.547 +        }
 219.548 +
 219.549 +        public String toString() {
 219.550 +            String l = locale.toString();
 219.551 +            if (l.length() == 0) {
 219.552 +                if (locale.getVariant().length() != 0) {
 219.553 +                    l = "__" + locale.getVariant();
 219.554 +                } else {
 219.555 +                    l = "\"\"";
 219.556 +                }
 219.557 +            }
 219.558 +            return "CacheKey[" + name + ", lc=" + l
 219.559 +                + "(format=" + format + ")]";
 219.560 +        }
 219.561 +    }
 219.562 +
 219.563 +    /**
 219.564 +     * The common interface to get a CacheKey in LoaderReference and
 219.565 +     * BundleReference.
 219.566 +     */
 219.567 +    private static interface CacheKeyReference {
 219.568 +        public CacheKey getCacheKey();
 219.569 +    }
 219.570 +
 219.571 +    /**
 219.572 +     * References to bundles are soft references so that they can be garbage
 219.573 +     * collected when they have no hard references.
 219.574 +     */
 219.575 +    private static final class BundleReference extends SoftReference<ResourceBundle>
 219.576 +                                               implements CacheKeyReference {
 219.577 +        private CacheKey cacheKey;
 219.578 +
 219.579 +        BundleReference(ResourceBundle referent, ReferenceQueue q, CacheKey key) {
 219.580 +            super(referent, q);
 219.581 +            cacheKey = key;
 219.582 +        }
 219.583 +
 219.584 +        public CacheKey getCacheKey() {
 219.585 +            return cacheKey;
 219.586 +        }
 219.587 +    }
 219.588 +
 219.589 +    /**
 219.590 +     * Gets a resource bundle using the specified base name, the default locale,
 219.591 +     * and the caller's class loader. Calling this method is equivalent to calling
 219.592 +     * <blockquote>
 219.593 +     * <code>getBundle(baseName, Locale.getDefault(), this.getClass().getClassLoader())</code>,
 219.594 +     * </blockquote>
 219.595 +     * except that <code>getClassLoader()</code> is run with the security
 219.596 +     * privileges of <code>ResourceBundle</code>.
 219.597 +     * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 219.598 +     * for a complete description of the search and instantiation strategy.
 219.599 +     *
 219.600 +     * @param baseName the base name of the resource bundle, a fully qualified class name
 219.601 +     * @exception java.lang.NullPointerException
 219.602 +     *     if <code>baseName</code> is <code>null</code>
 219.603 +     * @exception MissingResourceException
 219.604 +     *     if no resource bundle for the specified base name can be found
 219.605 +     * @return a resource bundle for the given base name and the default locale
 219.606 +     */
 219.607 +    public static final ResourceBundle getBundle(String baseName)
 219.608 +    {
 219.609 +        return getBundleImpl(baseName, Locale.getDefault(),
 219.610 +                             Control.INSTANCE);
 219.611 +    }
 219.612 +
 219.613 +    /**
 219.614 +     * Returns a resource bundle using the specified base name, the
 219.615 +     * default locale and the specified control. Calling this method
 219.616 +     * is equivalent to calling
 219.617 +     * <pre>
 219.618 +     * getBundle(baseName, Locale.getDefault(),
 219.619 +     *           this.getClass().getClassLoader(), control),
 219.620 +     * </pre>
 219.621 +     * except that <code>getClassLoader()</code> is run with the security
 219.622 +     * privileges of <code>ResourceBundle</code>.  See {@link
 219.623 +     * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 219.624 +     * complete description of the resource bundle loading process with a
 219.625 +     * <code>ResourceBundle.Control</code>.
 219.626 +     *
 219.627 +     * @param baseName
 219.628 +     *        the base name of the resource bundle, a fully qualified class
 219.629 +     *        name
 219.630 +     * @param control
 219.631 +     *        the control which gives information for the resource bundle
 219.632 +     *        loading process
 219.633 +     * @return a resource bundle for the given base name and the default
 219.634 +     *        locale
 219.635 +     * @exception NullPointerException
 219.636 +     *        if <code>baseName</code> or <code>control</code> is
 219.637 +     *        <code>null</code>
 219.638 +     * @exception MissingResourceException
 219.639 +     *        if no resource bundle for the specified base name can be found
 219.640 +     * @exception IllegalArgumentException
 219.641 +     *        if the given <code>control</code> doesn't perform properly
 219.642 +     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
 219.643 +     *        Note that validation of <code>control</code> is performed as
 219.644 +     *        needed.
 219.645 +     * @since 1.6
 219.646 +     */
 219.647 +    public static final ResourceBundle getBundle(String baseName,
 219.648 +                                                 Control control) {
 219.649 +        return getBundleImpl(baseName, Locale.getDefault(),
 219.650 +                             /* must determine loader here, else we break stack invariant */
 219.651 +                             control);
 219.652 +    }
 219.653 +
 219.654 +    /**
 219.655 +     * Gets a resource bundle using the specified base name and locale,
 219.656 +     * and the caller's class loader. Calling this method is equivalent to calling
 219.657 +     * <blockquote>
 219.658 +     * <code>getBundle(baseName, locale, this.getClass().getClassLoader())</code>,
 219.659 +     * </blockquote>
 219.660 +     * except that <code>getClassLoader()</code> is run with the security
 219.661 +     * privileges of <code>ResourceBundle</code>.
 219.662 +     * See {@link #getBundle(String, Locale, ClassLoader) getBundle}
 219.663 +     * for a complete description of the search and instantiation strategy.
 219.664 +     *
 219.665 +     * @param baseName
 219.666 +     *        the base name of the resource bundle, a fully qualified class name
 219.667 +     * @param locale
 219.668 +     *        the locale for which a resource bundle is desired
 219.669 +     * @exception NullPointerException
 219.670 +     *        if <code>baseName</code> or <code>locale</code> is <code>null</code>
 219.671 +     * @exception MissingResourceException
 219.672 +     *        if no resource bundle for the specified base name can be found
 219.673 +     * @return a resource bundle for the given base name and locale
 219.674 +     */
 219.675 +    public static final ResourceBundle getBundle(String baseName,
 219.676 +                                                 Locale locale)
 219.677 +    {
 219.678 +        return getBundleImpl(baseName, locale,
 219.679 +                             /* must determine loader here, else we break stack invariant */
 219.680 +                             Control.INSTANCE);
 219.681 +    }
 219.682 +
 219.683 +    /**
 219.684 +     * Returns a resource bundle using the specified base name, target
 219.685 +     * locale and control, and the caller's class loader. Calling this
 219.686 +     * method is equivalent to calling
 219.687 +     * <pre>
 219.688 +     * getBundle(baseName, targetLocale, this.getClass().getClassLoader(),
 219.689 +     *           control),
 219.690 +     * </pre>
 219.691 +     * except that <code>getClassLoader()</code> is run with the security
 219.692 +     * privileges of <code>ResourceBundle</code>.  See {@link
 219.693 +     * #getBundle(String, Locale, ClassLoader, Control) getBundle} for the
 219.694 +     * complete description of the resource bundle loading process with a
 219.695 +     * <code>ResourceBundle.Control</code>.
 219.696 +     *
 219.697 +     * @param baseName
 219.698 +     *        the base name of the resource bundle, a fully qualified
 219.699 +     *        class name
 219.700 +     * @param targetLocale
 219.701 +     *        the locale for which a resource bundle is desired
 219.702 +     * @param control
 219.703 +     *        the control which gives information for the resource
 219.704 +     *        bundle loading process
 219.705 +     * @return a resource bundle for the given base name and a
 219.706 +     *        <code>Locale</code> in <code>locales</code>
 219.707 +     * @exception NullPointerException
 219.708 +     *        if <code>baseName</code>, <code>locales</code> or
 219.709 +     *        <code>control</code> is <code>null</code>
 219.710 +     * @exception MissingResourceException
 219.711 +     *        if no resource bundle for the specified base name in any
 219.712 +     *        of the <code>locales</code> can be found.
 219.713 +     * @exception IllegalArgumentException
 219.714 +     *        if the given <code>control</code> doesn't perform properly
 219.715 +     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
 219.716 +     *        Note that validation of <code>control</code> is performed as
 219.717 +     *        needed.
 219.718 +     * @since 1.6
 219.719 +     */
 219.720 +    public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
 219.721 +                                                 Control control) {
 219.722 +        return getBundleImpl(baseName, targetLocale,
 219.723 +                             /* must determine loader here, else we break stack invariant */
 219.724 +                             control);
 219.725 +    }
 219.726 +
 219.727 +    /**
 219.728 +     * Gets a resource bundle using the specified base name, locale, and class
 219.729 +     * loader.
 219.730 +     *
 219.731 +     * <p><a name="default_behavior"/>This method behaves the same as calling
 219.732 +     * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
 219.733 +     * default instance of {@link Control}. The following describes this behavior.
 219.734 +     *
 219.735 +     * <p><code>getBundle</code> uses the base name, the specified locale, and
 219.736 +     * the default locale (obtained from {@link java.util.Locale#getDefault()
 219.737 +     * Locale.getDefault}) to generate a sequence of <a
 219.738 +     * name="candidates"><em>candidate bundle names</em></a>.  If the specified
 219.739 +     * locale's language, script, country, and variant are all empty strings,
 219.740 +     * then the base name is the only candidate bundle name.  Otherwise, a list
 219.741 +     * of candidate locales is generated from the attribute values of the
 219.742 +     * specified locale (language, script, country and variant) and appended to
 219.743 +     * the base name.  Typically, this will look like the following:
 219.744 +     *
 219.745 +     * <pre>
 219.746 +     *     baseName + "_" + language + "_" + script + "_" + country + "_" + variant
 219.747 +     *     baseName + "_" + language + "_" + script + "_" + country
 219.748 +     *     baseName + "_" + language + "_" + script
 219.749 +     *     baseName + "_" + language + "_" + country + "_" + variant
 219.750 +     *     baseName + "_" + language + "_" + country
 219.751 +     *     baseName + "_" + language
 219.752 +     * </pre>
 219.753 +     *
 219.754 +     * <p>Candidate bundle names where the final component is an empty string
 219.755 +     * are omitted, along with the underscore.  For example, if country is an
 219.756 +     * empty string, the second and the fifth candidate bundle names above
 219.757 +     * would be omitted.  Also, if script is an empty string, the candidate names
 219.758 +     * including script are omitted.  For example, a locale with language "de"
 219.759 +     * and variant "JAVA" will produce candidate names with base name
 219.760 +     * "MyResource" below.
 219.761 +     *
 219.762 +     * <pre>
 219.763 +     *     MyResource_de__JAVA
 219.764 +     *     MyResource_de
 219.765 +     * </pre>
 219.766 +     *
 219.767 +     * In the case that the variant contains one or more underscores ('_'), a
 219.768 +     * sequence of bundle names generated by truncating the last underscore and
 219.769 +     * the part following it is inserted after a candidate bundle name with the
 219.770 +     * original variant.  For example, for a locale with language "en", script
 219.771 +     * "Latn, country "US" and variant "WINDOWS_VISTA", and bundle base name
 219.772 +     * "MyResource", the list of candidate bundle names below is generated:
 219.773 +     *
 219.774 +     * <pre>
 219.775 +     * MyResource_en_Latn_US_WINDOWS_VISTA
 219.776 +     * MyResource_en_Latn_US_WINDOWS
 219.777 +     * MyResource_en_Latn_US
 219.778 +     * MyResource_en_Latn
 219.779 +     * MyResource_en_US_WINDOWS_VISTA
 219.780 +     * MyResource_en_US_WINDOWS
 219.781 +     * MyResource_en_US
 219.782 +     * MyResource_en
 219.783 +     * </pre>
 219.784 +     *
 219.785 +     * <blockquote><b>Note:</b> For some <code>Locale</code>s, the list of
 219.786 +     * candidate bundle names contains extra names, or the order of bundle names
 219.787 +     * is slightly modified.  See the description of the default implementation
 219.788 +     * of {@link Control#getCandidateLocales(String, Locale)
 219.789 +     * getCandidateLocales} for details.</blockquote>
 219.790 +     *
 219.791 +     * <p><code>getBundle</code> then iterates over the candidate bundle names
 219.792 +     * to find the first one for which it can <em>instantiate</em> an actual
 219.793 +     * resource bundle. It uses the default controls' {@link Control#getFormats
 219.794 +     * getFormats} method, which generates two bundle names for each generated
 219.795 +     * name, the first a class name and the second a properties file name. For
 219.796 +     * each candidate bundle name, it attempts to create a resource bundle:
 219.797 +     *
 219.798 +     * <ul><li>First, it attempts to load a class using the generated class name.
 219.799 +     * If such a class can be found and loaded using the specified class
 219.800 +     * loader, is assignment compatible with ResourceBundle, is accessible from
 219.801 +     * ResourceBundle, and can be instantiated, <code>getBundle</code> creates a
 219.802 +     * new instance of this class and uses it as the <em>result resource
 219.803 +     * bundle</em>.
 219.804 +     *
 219.805 +     * <li>Otherwise, <code>getBundle</code> attempts to locate a property
 219.806 +     * resource file using the generated properties file name.  It generates a
 219.807 +     * path name from the candidate bundle name by replacing all "." characters
 219.808 +     * with "/" and appending the string ".properties".  It attempts to find a
 219.809 +     * "resource" with this name using {@link
 219.810 +     * java.lang.ClassLoader#getResource(java.lang.String)
 219.811 +     * ClassLoader.getResource}.  (Note that a "resource" in the sense of
 219.812 +     * <code>getResource</code> has nothing to do with the contents of a
 219.813 +     * resource bundle, it is just a container of data, such as a file.)  If it
 219.814 +     * finds a "resource", it attempts to create a new {@link
 219.815 +     * PropertyResourceBundle} instance from its contents.  If successful, this
 219.816 +     * instance becomes the <em>result resource bundle</em>.  </ul>
 219.817 +     *
 219.818 +     * <p>This continues until a result resource bundle is instantiated or the
 219.819 +     * list of candidate bundle names is exhausted.  If no matching resource
 219.820 +     * bundle is found, the default control's {@link Control#getFallbackLocale
 219.821 +     * getFallbackLocale} method is called, which returns the current default
 219.822 +     * locale.  A new sequence of candidate locale names is generated using this
 219.823 +     * locale and and searched again, as above.
 219.824 +     *
 219.825 +     * <p>If still no result bundle is found, the base name alone is looked up. If
 219.826 +     * this still fails, a <code>MissingResourceException</code> is thrown.
 219.827 +     *
 219.828 +     * <p><a name="parent_chain"/> Once a result resource bundle has been found,
 219.829 +     * its <em>parent chain</em> is instantiated.  If the result bundle already
 219.830 +     * has a parent (perhaps because it was returned from a cache) the chain is
 219.831 +     * complete.
 219.832 +     *
 219.833 +     * <p>Otherwise, <code>getBundle</code> examines the remainder of the
 219.834 +     * candidate locale list that was used during the pass that generated the
 219.835 +     * result resource bundle.  (As before, candidate bundle names where the
 219.836 +     * final component is an empty string are omitted.)  When it comes to the
 219.837 +     * end of the candidate list, it tries the plain bundle name.  With each of the
 219.838 +     * candidate bundle names it attempts to instantiate a resource bundle (first
 219.839 +     * looking for a class and then a properties file, as described above).
 219.840 +     *
 219.841 +     * <p>Whenever it succeeds, it calls the previously instantiated resource
 219.842 +     * bundle's {@link #setParent(java.util.ResourceBundle) setParent} method
 219.843 +     * with the new resource bundle.  This continues until the list of names
 219.844 +     * is exhausted or the current bundle already has a non-null parent.
 219.845 +     *
 219.846 +     * <p>Once the parent chain is complete, the bundle is returned.
 219.847 +     *
 219.848 +     * <p><b>Note:</b> <code>getBundle</code> caches instantiated resource
 219.849 +     * bundles and might return the same resource bundle instance multiple times.
 219.850 +     *
 219.851 +     * <p><b>Note:</b>The <code>baseName</code> argument should be a fully
 219.852 +     * qualified class name. However, for compatibility with earlier versions,
 219.853 +     * Sun's Java SE Runtime Environments do not verify this, and so it is
 219.854 +     * possible to access <code>PropertyResourceBundle</code>s by specifying a
 219.855 +     * path name (using "/") instead of a fully qualified class name (using
 219.856 +     * ".").
 219.857 +     *
 219.858 +     * <p><a name="default_behavior_example"/>
 219.859 +     * <strong>Example:</strong>
 219.860 +     * <p>
 219.861 +     * The following class and property files are provided:
 219.862 +     * <pre>
 219.863 +     *     MyResources.class
 219.864 +     *     MyResources.properties
 219.865 +     *     MyResources_fr.properties
 219.866 +     *     MyResources_fr_CH.class
 219.867 +     *     MyResources_fr_CH.properties
 219.868 +     *     MyResources_en.properties
 219.869 +     *     MyResources_es_ES.class
 219.870 +     * </pre>
 219.871 +     *
 219.872 +     * The contents of all files are valid (that is, public non-abstract
 219.873 +     * subclasses of <code>ResourceBundle</code> for the ".class" files,
 219.874 +     * syntactically correct ".properties" files).  The default locale is
 219.875 +     * <code>Locale("en", "GB")</code>.
 219.876 +     *
 219.877 +     * <p>Calling <code>getBundle</code> with the locale arguments below will
 219.878 +     * instantiate resource bundles as follows:
 219.879 +     *
 219.880 +     * <table>
 219.881 +     * <tr><td>Locale("fr", "CH")</td><td>MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class</td></tr>
 219.882 +     * <tr><td>Locale("fr", "FR")</td><td>MyResources_fr.properties, parent MyResources.class</td></tr>
 219.883 +     * <tr><td>Locale("de", "DE")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
 219.884 +     * <tr><td>Locale("en", "US")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
 219.885 +     * <tr><td>Locale("es", "ES")</td><td>MyResources_es_ES.class, parent MyResources.class</td></tr>
 219.886 +     * </table>
 219.887 +     *
 219.888 +     * <p>The file MyResources_fr_CH.properties is never used because it is
 219.889 +     * hidden by the MyResources_fr_CH.class. Likewise, MyResources.properties
 219.890 +     * is also hidden by MyResources.class.
 219.891 +     *
 219.892 +     * @param baseName the base name of the resource bundle, a fully qualified class name
 219.893 +     * @param locale the locale for which a resource bundle is desired
 219.894 +     * @param loader the class loader from which to load the resource bundle
 219.895 +     * @return a resource bundle for the given base name and locale
 219.896 +     * @exception java.lang.NullPointerException
 219.897 +     *        if <code>baseName</code>, <code>locale</code>, or <code>loader</code> is <code>null</code>
 219.898 +     * @exception MissingResourceException
 219.899 +     *        if no resource bundle for the specified base name can be found
 219.900 +     * @since 1.2
 219.901 +     */
 219.902 +    public static ResourceBundle getBundle(String baseName, Locale locale,
 219.903 +                                           ClassLoader loader)
 219.904 +    {
 219.905 +        if (loader == null) {
 219.906 +            throw new NullPointerException();
 219.907 +        }
 219.908 +        return getBundleImpl(baseName, locale, Control.INSTANCE);
 219.909 +    }
 219.910 +
 219.911 +    /**
 219.912 +     * Returns a resource bundle using the specified base name, target
 219.913 +     * locale, class loader and control. Unlike the {@linkplain
 219.914 +     * #getBundle(String, Locale, ClassLoader) <code>getBundle</code>
 219.915 +     * factory methods with no <code>control</code> argument}, the given
 219.916 +     * <code>control</code> specifies how to locate and instantiate resource
 219.917 +     * bundles. Conceptually, the bundle loading process with the given
 219.918 +     * <code>control</code> is performed in the following steps.
 219.919 +     *
 219.920 +     * <p>
 219.921 +     * <ol>
 219.922 +     * <li>This factory method looks up the resource bundle in the cache for
 219.923 +     * the specified <code>baseName</code>, <code>targetLocale</code> and
 219.924 +     * <code>loader</code>.  If the requested resource bundle instance is
 219.925 +     * found in the cache and the time-to-live periods of the instance and
 219.926 +     * all of its parent instances have not expired, the instance is returned
 219.927 +     * to the caller. Otherwise, this factory method proceeds with the
 219.928 +     * loading process below.</li>
 219.929 +     *
 219.930 +     * <li>The {@link ResourceBundle.Control#getFormats(String)
 219.931 +     * control.getFormats} method is called to get resource bundle formats
 219.932 +     * to produce bundle or resource names. The strings
 219.933 +     * <code>"java.class"</code> and <code>"java.properties"</code>
 219.934 +     * designate class-based and {@linkplain PropertyResourceBundle
 219.935 +     * property}-based resource bundles, respectively. Other strings
 219.936 +     * starting with <code>"java."</code> are reserved for future extensions
 219.937 +     * and must not be used for application-defined formats. Other strings
 219.938 +     * designate application-defined formats.</li>
 219.939 +     *
 219.940 +     * <li>The {@link ResourceBundle.Control#getCandidateLocales(String,
 219.941 +     * Locale) control.getCandidateLocales} method is called with the target
 219.942 +     * locale to get a list of <em>candidate <code>Locale</code>s</em> for
 219.943 +     * which resource bundles are searched.</li>
 219.944 +     *
 219.945 +     * <li>The {@link ResourceBundle.Control#newBundle(String, Locale,
 219.946 +     * String, ClassLoader, boolean) control.newBundle} method is called to
 219.947 +     * instantiate a <code>ResourceBundle</code> for the base bundle name, a
 219.948 +     * candidate locale, and a format. (Refer to the note on the cache
 219.949 +     * lookup below.) This step is iterated over all combinations of the
 219.950 +     * candidate locales and formats until the <code>newBundle</code> method
 219.951 +     * returns a <code>ResourceBundle</code> instance or the iteration has
 219.952 +     * used up all the combinations. For example, if the candidate locales
 219.953 +     * are <code>Locale("de", "DE")</code>, <code>Locale("de")</code> and
 219.954 +     * <code>Locale("")</code> and the formats are <code>"java.class"</code>
 219.955 +     * and <code>"java.properties"</code>, then the following is the
 219.956 +     * sequence of locale-format combinations to be used to call
 219.957 +     * <code>control.newBundle</code>.
 219.958 +     *
 219.959 +     * <table style="width: 50%; text-align: left; margin-left: 40px;"
 219.960 +     *  border="0" cellpadding="2" cellspacing="2">
 219.961 +     * <tbody><code>
 219.962 +     * <tr>
 219.963 +     * <td
 219.964 +     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;">Locale<br>
 219.965 +     * </td>
 219.966 +     * <td
 219.967 +     * style="vertical-align: top; text-align: left; font-weight: bold; width: 50%;">format<br>
 219.968 +     * </td>
 219.969 +     * </tr>
 219.970 +     * <tr>
 219.971 +     * <td style="vertical-align: top; width: 50%;">Locale("de", "DE")<br>
 219.972 +     * </td>
 219.973 +     * <td style="vertical-align: top; width: 50%;">java.class<br>
 219.974 +     * </td>
 219.975 +     * </tr>
 219.976 +     * <tr>
 219.977 +     * <td style="vertical-align: top; width: 50%;">Locale("de", "DE")</td>
 219.978 +     * <td style="vertical-align: top; width: 50%;">java.properties<br>
 219.979 +     * </td>
 219.980 +     * </tr>
 219.981 +     * <tr>
 219.982 +     * <td style="vertical-align: top; width: 50%;">Locale("de")</td>
 219.983 +     * <td style="vertical-align: top; width: 50%;">java.class</td>
 219.984 +     * </tr>
 219.985 +     * <tr>
 219.986 +     * <td style="vertical-align: top; width: 50%;">Locale("de")</td>
 219.987 +     * <td style="vertical-align: top; width: 50%;">java.properties</td>
 219.988 +     * </tr>
 219.989 +     * <tr>
 219.990 +     * <td style="vertical-align: top; width: 50%;">Locale("")<br>
 219.991 +     * </td>
 219.992 +     * <td style="vertical-align: top; width: 50%;">java.class</td>
 219.993 +     * </tr>
 219.994 +     * <tr>
 219.995 +     * <td style="vertical-align: top; width: 50%;">Locale("")</td>
 219.996 +     * <td style="vertical-align: top; width: 50%;">java.properties</td>
 219.997 +     * </tr>
 219.998 +     * </code></tbody>
 219.999 +     * </table>
219.1000 +     * </li>
219.1001 +     *
219.1002 +     * <li>If the previous step has found no resource bundle, proceed to
219.1003 +     * Step 6. If a bundle has been found that is a base bundle (a bundle
219.1004 +     * for <code>Locale("")</code>), and the candidate locale list only contained
219.1005 +     * <code>Locale("")</code>, return the bundle to the caller. If a bundle
219.1006 +     * has been found that is a base bundle, but the candidate locale list
219.1007 +     * contained locales other than Locale(""), put the bundle on hold and
219.1008 +     * proceed to Step 6. If a bundle has been found that is not a base
219.1009 +     * bundle, proceed to Step 7.</li>
219.1010 +     *
219.1011 +     * <li>The {@link ResourceBundle.Control#getFallbackLocale(String,
219.1012 +     * Locale) control.getFallbackLocale} method is called to get a fallback
219.1013 +     * locale (alternative to the current target locale) to try further
219.1014 +     * finding a resource bundle. If the method returns a non-null locale,
219.1015 +     * it becomes the next target locale and the loading process starts over
219.1016 +     * from Step 3. Otherwise, if a base bundle was found and put on hold in
219.1017 +     * a previous Step 5, it is returned to the caller now. Otherwise, a
219.1018 +     * MissingResourceException is thrown.</li>
219.1019 +     *
219.1020 +     * <li>At this point, we have found a resource bundle that's not the
219.1021 +     * base bundle. If this bundle set its parent during its instantiation,
219.1022 +     * it is returned to the caller. Otherwise, its <a
219.1023 +     * href="./ResourceBundle.html#parent_chain">parent chain</a> is
219.1024 +     * instantiated based on the list of candidate locales from which it was
219.1025 +     * found. Finally, the bundle is returned to the caller.</li>
219.1026 +     * </ol>
219.1027 +     *
219.1028 +     * <p>During the resource bundle loading process above, this factory
219.1029 +     * method looks up the cache before calling the {@link
219.1030 +     * Control#newBundle(String, Locale, String, ClassLoader, boolean)
219.1031 +     * control.newBundle} method.  If the time-to-live period of the
219.1032 +     * resource bundle found in the cache has expired, the factory method
219.1033 +     * calls the {@link ResourceBundle.Control#needsReload(String, Locale,
219.1034 +     * String, ClassLoader, ResourceBundle, long) control.needsReload}
219.1035 +     * method to determine whether the resource bundle needs to be reloaded.
219.1036 +     * If reloading is required, the factory method calls
219.1037 +     * <code>control.newBundle</code> to reload the resource bundle.  If
219.1038 +     * <code>control.newBundle</code> returns <code>null</code>, the factory
219.1039 +     * method puts a dummy resource bundle in the cache as a mark of
219.1040 +     * nonexistent resource bundles in order to avoid lookup overhead for
219.1041 +     * subsequent requests. Such dummy resource bundles are under the same
219.1042 +     * expiration control as specified by <code>control</code>.
219.1043 +     *
219.1044 +     * <p>All resource bundles loaded are cached by default. Refer to
219.1045 +     * {@link Control#getTimeToLive(String,Locale)
219.1046 +     * control.getTimeToLive} for details.
219.1047 +     *
219.1048 +     * <p>The following is an example of the bundle loading process with the
219.1049 +     * default <code>ResourceBundle.Control</code> implementation.
219.1050 +     *
219.1051 +     * <p>Conditions:
219.1052 +     * <ul>
219.1053 +     * <li>Base bundle name: <code>foo.bar.Messages</code>
219.1054 +     * <li>Requested <code>Locale</code>: {@link Locale#ITALY}</li>
219.1055 +     * <li>Default <code>Locale</code>: {@link Locale#FRENCH}</li>
219.1056 +     * <li>Available resource bundles:
219.1057 +     * <code>foo/bar/Messages_fr.properties</code> and
219.1058 +     * <code>foo/bar/Messages.properties</code></li>
219.1059 +     * </ul>
219.1060 +     *
219.1061 +     * <p>First, <code>getBundle</code> tries loading a resource bundle in
219.1062 +     * the following sequence.
219.1063 +     *
219.1064 +     * <ul>
219.1065 +     * <li>class <code>foo.bar.Messages_it_IT</code>
219.1066 +     * <li>file <code>foo/bar/Messages_it_IT.properties</code>
219.1067 +     * <li>class <code>foo.bar.Messages_it</code></li>
219.1068 +     * <li>file <code>foo/bar/Messages_it.properties</code></li>
219.1069 +     * <li>class <code>foo.bar.Messages</code></li>
219.1070 +     * <li>file <code>foo/bar/Messages.properties</code></li>
219.1071 +     * </ul>
219.1072 +     *
219.1073 +     * <p>At this point, <code>getBundle</code> finds
219.1074 +     * <code>foo/bar/Messages.properties</code>, which is put on hold
219.1075 +     * because it's the base bundle.  <code>getBundle</code> calls {@link
219.1076 +     * Control#getFallbackLocale(String, Locale)
219.1077 +     * control.getFallbackLocale("foo.bar.Messages", Locale.ITALY)} which
219.1078 +     * returns <code>Locale.FRENCH</code>. Next, <code>getBundle</code>
219.1079 +     * tries loading a bundle in the following sequence.
219.1080 +     *
219.1081 +     * <ul>
219.1082 +     * <li>class <code>foo.bar.Messages_fr</code></li>
219.1083 +     * <li>file <code>foo/bar/Messages_fr.properties</code></li>
219.1084 +     * <li>class <code>foo.bar.Messages</code></li>
219.1085 +     * <li>file <code>foo/bar/Messages.properties</code></li>
219.1086 +     * </ul>
219.1087 +     *
219.1088 +     * <p><code>getBundle</code> finds
219.1089 +     * <code>foo/bar/Messages_fr.properties</code> and creates a
219.1090 +     * <code>ResourceBundle</code> instance. Then, <code>getBundle</code>
219.1091 +     * sets up its parent chain from the list of the candiate locales.  Only
219.1092 +     * <code>foo/bar/Messages.properties</code> is found in the list and
219.1093 +     * <code>getBundle</code> creates a <code>ResourceBundle</code> instance
219.1094 +     * that becomes the parent of the instance for
219.1095 +     * <code>foo/bar/Messages_fr.properties</code>.
219.1096 +     *
219.1097 +     * @param baseName
219.1098 +     *        the base name of the resource bundle, a fully qualified
219.1099 +     *        class name
219.1100 +     * @param targetLocale
219.1101 +     *        the locale for which a resource bundle is desired
219.1102 +     * @param loader
219.1103 +     *        the class loader from which to load the resource bundle
219.1104 +     * @param control
219.1105 +     *        the control which gives information for the resource
219.1106 +     *        bundle loading process
219.1107 +     * @return a resource bundle for the given base name and locale
219.1108 +     * @exception NullPointerException
219.1109 +     *        if <code>baseName</code>, <code>targetLocale</code>,
219.1110 +     *        <code>loader</code>, or <code>control</code> is
219.1111 +     *        <code>null</code>
219.1112 +     * @exception MissingResourceException
219.1113 +     *        if no resource bundle for the specified base name can be found
219.1114 +     * @exception IllegalArgumentException
219.1115 +     *        if the given <code>control</code> doesn't perform properly
219.1116 +     *        (e.g., <code>control.getCandidateLocales</code> returns null.)
219.1117 +     *        Note that validation of <code>control</code> is performed as
219.1118 +     *        needed.
219.1119 +     * @since 1.6
219.1120 +     */
219.1121 +    public static ResourceBundle getBundle(String baseName, Locale targetLocale,
219.1122 +                                           ClassLoader loader, Control control) {
219.1123 +        if (loader == null || control == null) {
219.1124 +            throw new NullPointerException();
219.1125 +        }
219.1126 +        return getBundleImpl(baseName, targetLocale, control);
219.1127 +    }
219.1128 +
219.1129 +    private static ResourceBundle getBundleImpl(String baseName, Locale locale,
219.1130 +                                                Control control) {
219.1131 +        if (locale == null || control == null) {
219.1132 +            throw new NullPointerException();
219.1133 +        }
219.1134 +
219.1135 +        // We create a CacheKey here for use by this call. The base
219.1136 +        // name and loader will never change during the bundle loading
219.1137 +        // process. We have to make sure that the locale is set before
219.1138 +        // using it as a cache key.
219.1139 +        CacheKey cacheKey = new CacheKey(baseName, locale);
219.1140 +        ResourceBundle bundle = null;
219.1141 +
219.1142 +        // Quick lookup of the cache.
219.1143 +        BundleReference bundleRef = cacheList.get(cacheKey);
219.1144 +        if (bundleRef != null) {
219.1145 +            bundle = bundleRef.get();
219.1146 +            bundleRef = null;
219.1147 +        }
219.1148 +
219.1149 +        // If this bundle and all of its parents are valid (not expired),
219.1150 +        // then return this bundle. If any of the bundles is expired, we
219.1151 +        // don't call control.needsReload here but instead drop into the
219.1152 +        // complete loading process below.
219.1153 +        if (isValidBundle(bundle) && hasValidParentChain(bundle)) {
219.1154 +            return bundle;
219.1155 +        }
219.1156 +
219.1157 +        // No valid bundle was found in the cache, so we need to load the
219.1158 +        // resource bundle and its parents.
219.1159 +
219.1160 +        boolean isKnownControl = (control == Control.INSTANCE) ||
219.1161 +                                   (control instanceof SingleFormatControl);
219.1162 +        List<String> formats = control.getFormats(baseName);
219.1163 +        if (!isKnownControl && !checkList(formats)) {
219.1164 +            throw new IllegalArgumentException("Invalid Control: getFormats");
219.1165 +        }
219.1166 +
219.1167 +        ResourceBundle baseBundle = null;
219.1168 +        for (Locale targetLocale = locale;
219.1169 +             targetLocale != null;
219.1170 +             targetLocale = control.getFallbackLocale(baseName, targetLocale)) {
219.1171 +            List<Locale> candidateLocales = control.getCandidateLocales(baseName, targetLocale);
219.1172 +            if (!isKnownControl && !checkList(candidateLocales)) {
219.1173 +                throw new IllegalArgumentException("Invalid Control: getCandidateLocales");
219.1174 +            }
219.1175 +
219.1176 +            bundle = findBundle(cacheKey, candidateLocales, formats, 0, control, baseBundle);
219.1177 +
219.1178 +            // If the loaded bundle is the base bundle and exactly for the
219.1179 +            // requested locale or the only candidate locale, then take the
219.1180 +            // bundle as the resulting one. If the loaded bundle is the base
219.1181 +            // bundle, it's put on hold until we finish processing all
219.1182 +            // fallback locales.
219.1183 +            if (isValidBundle(bundle)) {
219.1184 +                boolean isBaseBundle = Locale.ROOT.equals(bundle.locale);
219.1185 +                if (!isBaseBundle || bundle.locale.equals(locale)
219.1186 +                    || (candidateLocales.size() == 1
219.1187 +                        && bundle.locale.equals(candidateLocales.get(0)))) {
219.1188 +                    break;
219.1189 +                }
219.1190 +
219.1191 +                // If the base bundle has been loaded, keep the reference in
219.1192 +                // baseBundle so that we can avoid any redundant loading in case
219.1193 +                // the control specify not to cache bundles.
219.1194 +                if (isBaseBundle && baseBundle == null) {
219.1195 +                    baseBundle = bundle;
219.1196 +                }
219.1197 +            }
219.1198 +        }
219.1199 +
219.1200 +        if (bundle == null) {
219.1201 +            if (baseBundle == null) {
219.1202 +                throwMissingResourceException(baseName, locale, cacheKey.getCause());
219.1203 +            }
219.1204 +            bundle = baseBundle;
219.1205 +        }
219.1206 +
219.1207 +        return bundle;
219.1208 +    }
219.1209 +
219.1210 +    /**
219.1211 +     * Checks if the given <code>List</code> is not null, not empty,
219.1212 +     * not having null in its elements.
219.1213 +     */
219.1214 +    private static final boolean checkList(List a) {
219.1215 +        boolean valid = (a != null && a.size() != 0);
219.1216 +        if (valid) {
219.1217 +            int size = a.size();
219.1218 +            for (int i = 0; valid && i < size; i++) {
219.1219 +                valid = (a.get(i) != null);
219.1220 +            }
219.1221 +        }
219.1222 +        return valid;
219.1223 +    }
219.1224 +
219.1225 +    private static final ResourceBundle findBundle(CacheKey cacheKey,
219.1226 +                                                   List<Locale> candidateLocales,
219.1227 +                                                   List<String> formats,
219.1228 +                                                   int index,
219.1229 +                                                   Control control,
219.1230 +                                                   ResourceBundle baseBundle) {
219.1231 +        Locale targetLocale = candidateLocales.get(index);
219.1232 +        ResourceBundle parent = null;
219.1233 +        if (index != candidateLocales.size() - 1) {
219.1234 +            parent = findBundle(cacheKey, candidateLocales, formats, index + 1,
219.1235 +                                control, baseBundle);
219.1236 +        } else if (baseBundle != null && Locale.ROOT.equals(targetLocale)) {
219.1237 +            return baseBundle;
219.1238 +        }
219.1239 +
219.1240 +        // Before we do the real loading work, see whether we need to
219.1241 +        // do some housekeeping: If references to class loaders or
219.1242 +        // resource bundles have been nulled out, remove all related
219.1243 +        // information from the cache.
219.1244 +        Object ref;
219.1245 +        while ((ref = referenceQueue.poll()) != null) {
219.1246 +            cacheList.remove(((CacheKeyReference)ref).getCacheKey());
219.1247 +        }
219.1248 +
219.1249 +        // flag indicating the resource bundle has expired in the cache
219.1250 +        boolean expiredBundle = false;
219.1251 +
219.1252 +        // First, look up the cache to see if it's in the cache, without
219.1253 +        // attempting to load bundle.
219.1254 +        cacheKey.setLocale(targetLocale);
219.1255 +        ResourceBundle bundle = findBundleInCache(cacheKey, control);
219.1256 +        if (isValidBundle(bundle)) {
219.1257 +            expiredBundle = bundle.expired;
219.1258 +            if (!expiredBundle) {
219.1259 +                // If its parent is the one asked for by the candidate
219.1260 +                // locales (the runtime lookup path), we can take the cached
219.1261 +                // one. (If it's not identical, then we'd have to check the
219.1262 +                // parent's parents to be consistent with what's been
219.1263 +                // requested.)
219.1264 +                if (bundle.parent == parent) {
219.1265 +                    return bundle;
219.1266 +                }
219.1267 +                // Otherwise, remove the cached one since we can't keep
219.1268 +                // the same bundles having different parents.
219.1269 +                BundleReference bundleRef = cacheList.get(cacheKey);
219.1270 +                if (bundleRef != null && bundleRef.get() == bundle) {
219.1271 +                    cacheList.remove(cacheKey);
219.1272 +                }
219.1273 +            }
219.1274 +        }
219.1275 +
219.1276 +        if (bundle != NONEXISTENT_BUNDLE) {
219.1277 +            CacheKey constKey = (CacheKey) cacheKey.clone();
219.1278 +
219.1279 +            try {
219.1280 +                bundle = loadBundle(cacheKey, formats, control, expiredBundle);
219.1281 +                if (bundle != null) {
219.1282 +                    if (bundle.parent == null) {
219.1283 +                        bundle.setParent(parent);
219.1284 +                    }
219.1285 +                    bundle.locale = targetLocale;
219.1286 +                    bundle = putBundleInCache(cacheKey, bundle, control);
219.1287 +                    return bundle;
219.1288 +                }
219.1289 +
219.1290 +                // Put NONEXISTENT_BUNDLE in the cache as a mark that there's no bundle
219.1291 +                // instance for the locale.
219.1292 +                putBundleInCache(cacheKey, NONEXISTENT_BUNDLE, control);
219.1293 +            } finally {
219.1294 +                if (constKey.getCause() instanceof InterruptedException) {
219.1295 +                    Thread.currentThread().interrupt();
219.1296 +                }
219.1297 +            }
219.1298 +        }
219.1299 +        return parent;
219.1300 +    }
219.1301 +
219.1302 +    private static final ResourceBundle loadBundle(CacheKey cacheKey,
219.1303 +                                                   List<String> formats,
219.1304 +                                                   Control control,
219.1305 +                                                   boolean reload) {
219.1306 +
219.1307 +        // Here we actually load the bundle in the order of formats
219.1308 +        // specified by the getFormats() value.
219.1309 +        Locale targetLocale = cacheKey.getLocale();
219.1310 +
219.1311 +        ResourceBundle bundle = null;
219.1312 +        int size = formats.size();
219.1313 +        for (int i = 0; i < size; i++) {
219.1314 +            String format = formats.get(i);
219.1315 +            try {
219.1316 +                bundle = control.newBundle(cacheKey.getName(), targetLocale, format,
219.1317 +                                           null, reload);
219.1318 +            } catch (LinkageError error) {
219.1319 +                // We need to handle the LinkageError case due to
219.1320 +                // inconsistent case-sensitivity in ClassLoader.
219.1321 +                // See 6572242 for details.
219.1322 +                cacheKey.setCause(error);
219.1323 +            } catch (Exception cause) {
219.1324 +                cacheKey.setCause(cause);
219.1325 +            }
219.1326 +            if (bundle != null) {
219.1327 +                // Set the format in the cache key so that it can be
219.1328 +                // used when calling needsReload later.
219.1329 +                cacheKey.setFormat(format);
219.1330 +                bundle.name = cacheKey.getName();
219.1331 +                bundle.locale = targetLocale;
219.1332 +                // Bundle provider might reuse instances. So we should make
219.1333 +                // sure to clear the expired flag here.
219.1334 +                bundle.expired = false;
219.1335 +                break;
219.1336 +            }
219.1337 +        }
219.1338 +
219.1339 +        return bundle;
219.1340 +    }
219.1341 +
219.1342 +    private static final boolean isValidBundle(ResourceBundle bundle) {
219.1343 +        return bundle != null && bundle != NONEXISTENT_BUNDLE;
219.1344 +    }
219.1345 +
219.1346 +    /**
219.1347 +     * Determines whether any of resource bundles in the parent chain,
219.1348 +     * including the leaf, have expired.
219.1349 +     */
219.1350 +    private static final boolean hasValidParentChain(ResourceBundle bundle) {
219.1351 +        long now = System.currentTimeMillis();
219.1352 +        while (bundle != null) {
219.1353 +            if (bundle.expired) {
219.1354 +                return false;
219.1355 +            }
219.1356 +            CacheKey key = bundle.cacheKey;
219.1357 +            if (key != null) {
219.1358 +                long expirationTime = key.expirationTime;
219.1359 +                if (expirationTime >= 0 && expirationTime <= now) {
219.1360 +                    return false;
219.1361 +                }
219.1362 +            }
219.1363 +            bundle = bundle.parent;
219.1364 +        }
219.1365 +        return true;
219.1366 +    }
219.1367 +
219.1368 +    /**
219.1369 +     * Throw a MissingResourceException with proper message
219.1370 +     */
219.1371 +    private static final void throwMissingResourceException(String baseName,
219.1372 +                                                            Locale locale,
219.1373 +                                                            Throwable cause) {
219.1374 +        // If the cause is a MissingResourceException, avoid creating
219.1375 +        // a long chain. (6355009)
219.1376 +        if (cause instanceof MissingResourceException) {
219.1377 +            cause = null;
219.1378 +        }
219.1379 +        throw new MissingResourceException("Can't find bundle for base name "
219.1380 +                                           + baseName + ", locale " + locale,
219.1381 +                                           baseName + "_" + locale, // className
219.1382 +                                           "",                      // key
219.1383 +                                           cause);
219.1384 +    }
219.1385 +
219.1386 +    /**
219.1387 +     * Finds a bundle in the cache. Any expired bundles are marked as
219.1388 +     * `expired' and removed from the cache upon return.
219.1389 +     *
219.1390 +     * @param cacheKey the key to look up the cache
219.1391 +     * @param control the Control to be used for the expiration control
219.1392 +     * @return the cached bundle, or null if the bundle is not found in the
219.1393 +     * cache or its parent has expired. <code>bundle.expire</code> is true
219.1394 +     * upon return if the bundle in the cache has expired.
219.1395 +     */
219.1396 +    private static final ResourceBundle findBundleInCache(CacheKey cacheKey,
219.1397 +                                                          Control control) {
219.1398 +        BundleReference bundleRef = cacheList.get(cacheKey);
219.1399 +        if (bundleRef == null) {
219.1400 +            return null;
219.1401 +        }
219.1402 +        ResourceBundle bundle = bundleRef.get();
219.1403 +        if (bundle == null) {
219.1404 +            return null;
219.1405 +        }
219.1406 +        ResourceBundle p = bundle.parent;
219.1407 +        assert p != NONEXISTENT_BUNDLE;
219.1408 +        // If the parent has expired, then this one must also expire. We
219.1409 +        // check only the immediate parent because the actual loading is
219.1410 +        // done from the root (base) to leaf (child) and the purpose of
219.1411 +        // checking is to propagate expiration towards the leaf. For
219.1412 +        // example, if the requested locale is ja_JP_JP and there are
219.1413 +        // bundles for all of the candidates in the cache, we have a list,
219.1414 +        //
219.1415 +        // base <- ja <- ja_JP <- ja_JP_JP
219.1416 +        //
219.1417 +        // If ja has expired, then it will reload ja and the list becomes a
219.1418 +        // tree.
219.1419 +        //
219.1420 +        // base <- ja (new)
219.1421 +        //  "   <- ja (expired) <- ja_JP <- ja_JP_JP
219.1422 +        //
219.1423 +        // When looking up ja_JP in the cache, it finds ja_JP in the cache
219.1424 +        // which references to the expired ja. Then, ja_JP is marked as
219.1425 +        // expired and removed from the cache. This will be propagated to
219.1426 +        // ja_JP_JP.
219.1427 +        //
219.1428 +        // Now, it's possible, for example, that while loading new ja_JP,
219.1429 +        // someone else has started loading the same bundle and finds the
219.1430 +        // base bundle has expired. Then, what we get from the first
219.1431 +        // getBundle call includes the expired base bundle. However, if
219.1432 +        // someone else didn't start its loading, we wouldn't know if the
219.1433 +        // base bundle has expired at the end of the loading process. The
219.1434 +        // expiration control doesn't guarantee that the returned bundle and
219.1435 +        // its parents haven't expired.
219.1436 +        //
219.1437 +        // We could check the entire parent chain to see if there's any in
219.1438 +        // the chain that has expired. But this process may never end. An
219.1439 +        // extreme case would be that getTimeToLive returns 0 and
219.1440 +        // needsReload always returns true.
219.1441 +        if (p != null && p.expired) {
219.1442 +            assert bundle != NONEXISTENT_BUNDLE;
219.1443 +            bundle.expired = true;
219.1444 +            bundle.cacheKey = null;
219.1445 +            cacheList.remove(cacheKey);
219.1446 +            bundle = null;
219.1447 +        } else {
219.1448 +            CacheKey key = bundleRef.getCacheKey();
219.1449 +            long expirationTime = key.expirationTime;
219.1450 +            if (!bundle.expired && expirationTime >= 0 &&
219.1451 +                expirationTime <= System.currentTimeMillis()) {
219.1452 +                // its TTL period has expired.
219.1453 +                if (bundle != NONEXISTENT_BUNDLE) {
219.1454 +                    // Synchronize here to call needsReload to avoid
219.1455 +                    // redundant concurrent calls for the same bundle.
219.1456 +                    synchronized (bundle) {
219.1457 +                        expirationTime = key.expirationTime;
219.1458 +                        if (!bundle.expired && expirationTime >= 0 &&
219.1459 +                            expirationTime <= System.currentTimeMillis()) {
219.1460 +                            try {
219.1461 +                                bundle.expired = control.needsReload(key.getName(),
219.1462 +                                                                     key.getLocale(),
219.1463 +                                                                     key.getFormat(),
219.1464 +                                                                     null,
219.1465 +                                                                     bundle,
219.1466 +                                                                     key.loadTime);
219.1467 +                            } catch (Exception e) {
219.1468 +                                cacheKey.setCause(e);
219.1469 +                            }
219.1470 +                            if (bundle.expired) {
219.1471 +                                // If the bundle needs to be reloaded, then
219.1472 +                                // remove the bundle from the cache, but
219.1473 +                                // return the bundle with the expired flag
219.1474 +                                // on.
219.1475 +                                bundle.cacheKey = null;
219.1476 +                                cacheList.remove(cacheKey);
219.1477 +                            } else {
219.1478 +                                // Update the expiration control info. and reuse
219.1479 +                                // the same bundle instance
219.1480 +                                setExpirationTime(key, control);
219.1481 +                            }
219.1482 +                        }
219.1483 +                    }
219.1484 +                } else {
219.1485 +                    // We just remove NONEXISTENT_BUNDLE from the cache.
219.1486 +                    cacheList.remove(cacheKey);
219.1487 +                    bundle = null;
219.1488 +                }
219.1489 +            }
219.1490 +        }
219.1491 +        return bundle;
219.1492 +    }
219.1493 +
219.1494 +    /**
219.1495 +     * Put a new bundle in the cache.
219.1496 +     *
219.1497 +     * @param cacheKey the key for the resource bundle
219.1498 +     * @param bundle the resource bundle to be put in the cache
219.1499 +     * @return the ResourceBundle for the cacheKey; if someone has put
219.1500 +     * the bundle before this call, the one found in the cache is
219.1501 +     * returned.
219.1502 +     */
219.1503 +    private static final ResourceBundle putBundleInCache(CacheKey cacheKey,
219.1504 +                                                         ResourceBundle bundle,
219.1505 +                                                         Control control) {
219.1506 +        setExpirationTime(cacheKey, control);
219.1507 +        if (cacheKey.expirationTime != Control.TTL_DONT_CACHE) {
219.1508 +            CacheKey key = (CacheKey) cacheKey.clone();
219.1509 +            BundleReference bundleRef = new BundleReference(bundle, referenceQueue, key);
219.1510 +            bundle.cacheKey = key;
219.1511 +
219.1512 +            // Put the bundle in the cache if it's not been in the cache.
219.1513 +            BundleReference result = cacheList.put(key, bundleRef);
219.1514 +
219.1515 +            // If someone else has put the same bundle in the cache before
219.1516 +            // us and it has not expired, we should use the one in the cache.
219.1517 +            if (result != null) {
219.1518 +                ResourceBundle rb = result.get();
219.1519 +                if (rb != null && !rb.expired) {
219.1520 +                    // Clear the back link to the cache key
219.1521 +                    bundle.cacheKey = null;
219.1522 +                    bundle = rb;
219.1523 +                    // Clear the reference in the BundleReference so that
219.1524 +                    // it won't be enqueued.
219.1525 +                    bundleRef.clear();
219.1526 +                } else {
219.1527 +                    // Replace the invalid (garbage collected or expired)
219.1528 +                    // instance with the valid one.
219.1529 +                    cacheList.put(key, bundleRef);
219.1530 +                }
219.1531 +            }
219.1532 +        }
219.1533 +        return bundle;
219.1534 +    }
219.1535 +
219.1536 +    private static final void setExpirationTime(CacheKey cacheKey, Control control) {
219.1537 +        long ttl = control.getTimeToLive(cacheKey.getName(),
219.1538 +                                         cacheKey.getLocale());
219.1539 +        if (ttl >= 0) {
219.1540 +            // If any expiration time is specified, set the time to be
219.1541 +            // expired in the cache.
219.1542 +            long now = System.currentTimeMillis();
219.1543 +            cacheKey.loadTime = now;
219.1544 +            cacheKey.expirationTime = now + ttl;
219.1545 +        } else if (ttl >= Control.TTL_NO_EXPIRATION_CONTROL) {
219.1546 +            cacheKey.expirationTime = ttl;
219.1547 +        } else {
219.1548 +            throw new IllegalArgumentException("Invalid Control: TTL=" + ttl);
219.1549 +        }
219.1550 +    }
219.1551 +
219.1552 +    /**
219.1553 +     * Removes all resource bundles from the cache that have been loaded
219.1554 +     * using the caller's class loader.
219.1555 +     *
219.1556 +     * @since 1.6
219.1557 +     * @see ResourceBundle.Control#getTimeToLive(String,Locale)
219.1558 +     */
219.1559 +    public static final void clearCache() {
219.1560 +        clearCache(null);
219.1561 +    }
219.1562 +
219.1563 +    /**
219.1564 +     * Removes all resource bundles from the cache that have been loaded
219.1565 +     * using the given class loader.
219.1566 +     *
219.1567 +     * @param loader the class loader
219.1568 +     * @exception NullPointerException if <code>loader</code> is null
219.1569 +     * @since 1.6
219.1570 +     * @see ResourceBundle.Control#getTimeToLive(String,Locale)
219.1571 +     */
219.1572 +    public static final void clearCache(ClassLoader loader) {
219.1573 +        if (loader == null) {
219.1574 +            throw new NullPointerException();
219.1575 +        }
219.1576 +        Set<CacheKey> set = cacheList.keySet();
219.1577 +        for (CacheKey key : set) {
219.1578 +            set.remove(key);
219.1579 +        }
219.1580 +    }
219.1581 +
219.1582 +    /**
219.1583 +     * Gets an object for the given key from this resource bundle.
219.1584 +     * Returns null if this resource bundle does not contain an
219.1585 +     * object for the given key.
219.1586 +     *
219.1587 +     * @param key the key for the desired object
219.1588 +     * @exception NullPointerException if <code>key</code> is <code>null</code>
219.1589 +     * @return the object for the given key, or null
219.1590 +     */
219.1591 +    protected abstract Object handleGetObject(String key);
219.1592 +
219.1593 +    /**
219.1594 +     * Returns an enumeration of the keys.
219.1595 +     *
219.1596 +     * @return an <code>Enumeration</code> of the keys contained in
219.1597 +     *         this <code>ResourceBundle</code> and its parent bundles.
219.1598 +     */
219.1599 +    public abstract Enumeration<String> getKeys();
219.1600 +
219.1601 +    /**
219.1602 +     * Determines whether the given <code>key</code> is contained in
219.1603 +     * this <code>ResourceBundle</code> or its parent bundles.
219.1604 +     *
219.1605 +     * @param key
219.1606 +     *        the resource <code>key</code>
219.1607 +     * @return <code>true</code> if the given <code>key</code> is
219.1608 +     *        contained in this <code>ResourceBundle</code> or its
219.1609 +     *        parent bundles; <code>false</code> otherwise.
219.1610 +     * @exception NullPointerException
219.1611 +     *         if <code>key</code> is <code>null</code>
219.1612 +     * @since 1.6
219.1613 +     */
219.1614 +    public boolean containsKey(String key) {
219.1615 +        if (key == null) {
219.1616 +            throw new NullPointerException();
219.1617 +        }
219.1618 +        for (ResourceBundle rb = this; rb != null; rb = rb.parent) {
219.1619 +            if (rb.handleKeySet().contains(key)) {
219.1620 +                return true;
219.1621 +            }
219.1622 +        }
219.1623 +        return false;
219.1624 +    }
219.1625 +
219.1626 +    /**
219.1627 +     * Returns a <code>Set</code> of all keys contained in this
219.1628 +     * <code>ResourceBundle</code> and its parent bundles.
219.1629 +     *
219.1630 +     * @return a <code>Set</code> of all keys contained in this
219.1631 +     *         <code>ResourceBundle</code> and its parent bundles.
219.1632 +     * @since 1.6
219.1633 +     */
219.1634 +    public Set<String> keySet() {
219.1635 +        Set<String> keys = new HashSet<>();
219.1636 +        for (ResourceBundle rb = this; rb != null; rb = rb.parent) {
219.1637 +            keys.addAll(rb.handleKeySet());
219.1638 +        }
219.1639 +        return keys;
219.1640 +    }
219.1641 +
219.1642 +    /**
219.1643 +     * Returns a <code>Set</code> of the keys contained <em>only</em>
219.1644 +     * in this <code>ResourceBundle</code>.
219.1645 +     *
219.1646 +     * <p>The default implementation returns a <code>Set</code> of the
219.1647 +     * keys returned by the {@link #getKeys() getKeys} method except
219.1648 +     * for the ones for which the {@link #handleGetObject(String)
219.1649 +     * handleGetObject} method returns <code>null</code>. Once the
219.1650 +     * <code>Set</code> has been created, the value is kept in this
219.1651 +     * <code>ResourceBundle</code> in order to avoid producing the
219.1652 +     * same <code>Set</code> in subsequent calls. Subclasses can
219.1653 +     * override this method for faster handling.
219.1654 +     *
219.1655 +     * @return a <code>Set</code> of the keys contained only in this
219.1656 +     *        <code>ResourceBundle</code>
219.1657 +     * @since 1.6
219.1658 +     */
219.1659 +    protected Set<String> handleKeySet() {
219.1660 +        if (keySet == null) {
219.1661 +            synchronized (this) {
219.1662 +                if (keySet == null) {
219.1663 +                    Set<String> keys = new HashSet<>();
219.1664 +                    Enumeration<String> enumKeys = getKeys();
219.1665 +                    while (enumKeys.hasMoreElements()) {
219.1666 +                        String key = enumKeys.nextElement();
219.1667 +                        if (handleGetObject(key) != null) {
219.1668 +                            keys.add(key);
219.1669 +                        }
219.1670 +                    }
219.1671 +                    keySet = keys;
219.1672 +                }
219.1673 +            }
219.1674 +        }
219.1675 +        return keySet;
219.1676 +    }
219.1677 +
219.1678 +
219.1679 +
219.1680 +    /**
219.1681 +     * <code>ResourceBundle.Control</code> defines a set of callback methods
219.1682 +     * that are invoked by the {@link ResourceBundle#getBundle(String,
219.1683 +     * Locale, ClassLoader, Control) ResourceBundle.getBundle} factory
219.1684 +     * methods during the bundle loading process. In other words, a
219.1685 +     * <code>ResourceBundle.Control</code> collaborates with the factory
219.1686 +     * methods for loading resource bundles. The default implementation of
219.1687 +     * the callback methods provides the information necessary for the
219.1688 +     * factory methods to perform the <a
219.1689 +     * href="./ResourceBundle.html#default_behavior">default behavior</a>.
219.1690 +     *
219.1691 +     * <p>In addition to the callback methods, the {@link
219.1692 +     * #toBundleName(String, Locale) toBundleName} and {@link
219.1693 +     * #toResourceName(String, String) toResourceName} methods are defined
219.1694 +     * primarily for convenience in implementing the callback
219.1695 +     * methods. However, the <code>toBundleName</code> method could be
219.1696 +     * overridden to provide different conventions in the organization and
219.1697 +     * packaging of localized resources.  The <code>toResourceName</code>
219.1698 +     * method is <code>final</code> to avoid use of wrong resource and class
219.1699 +     * name separators.
219.1700 +     *
219.1701 +     * <p>Two factory methods, {@link #getControl(List)} and {@link
219.1702 +     * #getNoFallbackControl(List)}, provide
219.1703 +     * <code>ResourceBundle.Control</code> instances that implement common
219.1704 +     * variations of the default bundle loading process.
219.1705 +     *
219.1706 +     * <p>The formats returned by the {@link Control#getFormats(String)
219.1707 +     * getFormats} method and candidate locales returned by the {@link
219.1708 +     * ResourceBundle.Control#getCandidateLocales(String, Locale)
219.1709 +     * getCandidateLocales} method must be consistent in all
219.1710 +     * <code>ResourceBundle.getBundle</code> invocations for the same base
219.1711 +     * bundle. Otherwise, the <code>ResourceBundle.getBundle</code> methods
219.1712 +     * may return unintended bundles. For example, if only
219.1713 +     * <code>"java.class"</code> is returned by the <code>getFormats</code>
219.1714 +     * method for the first call to <code>ResourceBundle.getBundle</code>
219.1715 +     * and only <code>"java.properties"</code> for the second call, then the
219.1716 +     * second call will return the class-based one that has been cached
219.1717 +     * during the first call.
219.1718 +     *
219.1719 +     * <p>A <code>ResourceBundle.Control</code> instance must be thread-safe
219.1720 +     * if it's simultaneously used by multiple threads.
219.1721 +     * <code>ResourceBundle.getBundle</code> does not synchronize to call
219.1722 +     * the <code>ResourceBundle.Control</code> methods. The default
219.1723 +     * implementations of the methods are thread-safe.
219.1724 +     *
219.1725 +     * <p>Applications can specify <code>ResourceBundle.Control</code>
219.1726 +     * instances returned by the <code>getControl</code> factory methods or
219.1727 +     * created from a subclass of <code>ResourceBundle.Control</code> to
219.1728 +     * customize the bundle loading process. The following are examples of
219.1729 +     * changing the default bundle loading process.
219.1730 +     *
219.1731 +     * <p><b>Example 1</b>
219.1732 +     *
219.1733 +     * <p>The following code lets <code>ResourceBundle.getBundle</code> look
219.1734 +     * up only properties-based resources.
219.1735 +     *
219.1736 +     * <pre>
219.1737 +     * import java.util.*;
219.1738 +     * import static java.util.ResourceBundle.Control.*;
219.1739 +     * ...
219.1740 +     * ResourceBundle bundle =
219.1741 +     *   ResourceBundle.getBundle("MyResources", new Locale("fr", "CH"),
219.1742 +     *                            ResourceBundle.Control.getControl(FORMAT_PROPERTIES));
219.1743 +     * </pre>
219.1744 +     *
219.1745 +     * Given the resource bundles in the <a
219.1746 +     * href="./ResourceBundle.html#default_behavior_example">example</a> in
219.1747 +     * the <code>ResourceBundle.getBundle</code> description, this
219.1748 +     * <code>ResourceBundle.getBundle</code> call loads
219.1749 +     * <code>MyResources_fr_CH.properties</code> whose parent is
219.1750 +     * <code>MyResources_fr.properties</code> whose parent is
219.1751 +     * <code>MyResources.properties</code>. (<code>MyResources_fr_CH.properties</code>
219.1752 +     * is not hidden, but <code>MyResources_fr_CH.class</code> is.)
219.1753 +     *
219.1754 +     * <p><b>Example 2</b>
219.1755 +     *
219.1756 +     * <p>The following is an example of loading XML-based bundles
219.1757 +     * using {@link Properties#loadFromXML(java.io.InputStream)
219.1758 +     * Properties.loadFromXML}.
219.1759 +     *
219.1760 +     * <pre>
219.1761 +     * ResourceBundle rb = ResourceBundle.getBundle("Messages",
219.1762 +     *     new ResourceBundle.Control() {
219.1763 +     *         public List&lt;String&gt; getFormats(String baseName) {
219.1764 +     *             if (baseName == null)
219.1765 +     *                 throw new NullPointerException();
219.1766 +     *             return Arrays.asList("xml");
219.1767 +     *         }
219.1768 +     *         public ResourceBundle newBundle(String baseName,
219.1769 +     *                                         Locale locale,
219.1770 +     *                                         String format,
219.1771 +     *                                         ClassLoader loader,
219.1772 +     *                                         boolean reload)
219.1773 +     *                          throws IllegalAccessException,
219.1774 +     *                                 InstantiationException,
219.1775 +     *                                 IOException {
219.1776 +     *             if (baseName == null || locale == null
219.1777 +     *                   || format == null || loader == null)
219.1778 +     *                 throw new NullPointerException();
219.1779 +     *             ResourceBundle bundle = null;
219.1780 +     *             if (format.equals("xml")) {
219.1781 +     *                 String bundleName = toBundleName(baseName, locale);
219.1782 +     *                 String resourceName = toResourceName(bundleName, format);
219.1783 +     *                 InputStream stream = null;
219.1784 +     *                 if (reload) {
219.1785 +     *                     URL url = loader.getResource(resourceName);
219.1786 +     *                     if (url != null) {
219.1787 +     *                         URLConnection connection = url.openConnection();
219.1788 +     *                         if (connection != null) {
219.1789 +     *                             // Disable caches to get fresh data for
219.1790 +     *                             // reloading.
219.1791 +     *                             connection.setUseCaches(false);
219.1792 +     *                             stream = connection.getInputStream();
219.1793 +     *                         }
219.1794 +     *                     }
219.1795 +     *                 } else {
219.1796 +     *                     stream = loader.getResourceAsStream(resourceName);
219.1797 +     *                 }
219.1798 +     *                 if (stream != null) {
219.1799 +     *                     BufferedInputStream bis = new BufferedInputStream(stream);
219.1800 +     *                     bundle = new XMLResourceBundle(bis);
219.1801 +     *                     bis.close();
219.1802 +     *                 }
219.1803 +     *             }
219.1804 +     *             return bundle;
219.1805 +     *         }
219.1806 +     *     });
219.1807 +     *
219.1808 +     * ...
219.1809 +     *
219.1810 +     * private static class XMLResourceBundle extends ResourceBundle {
219.1811 +     *     private Properties props;
219.1812 +     *     XMLResourceBundle(InputStream stream) throws IOException {
219.1813 +     *         props = new Properties();
219.1814 +     *         props.loadFromXML(stream);
219.1815 +     *     }
219.1816 +     *     protected Object handleGetObject(String key) {
219.1817 +     *         return props.getProperty(key);
219.1818 +     *     }
219.1819 +     *     public Enumeration&lt;String&gt; getKeys() {
219.1820 +     *         ...
219.1821 +     *     }
219.1822 +     * }
219.1823 +     * </pre>
219.1824 +     *
219.1825 +     * @since 1.6
219.1826 +     */
219.1827 +    public static class Control {
219.1828 +        /**
219.1829 +         * The default format <code>List</code>, which contains the strings
219.1830 +         * <code>"java.class"</code> and <code>"java.properties"</code>, in
219.1831 +         * this order. This <code>List</code> is {@linkplain
219.1832 +         * Collections#unmodifiableList(List) unmodifiable}.
219.1833 +         *
219.1834 +         * @see #getFormats(String)
219.1835 +         */
219.1836 +        public static final List<String> FORMAT_DEFAULT
219.1837 +            = Collections.unmodifiableList(Arrays.asList("java.class",
219.1838 +                                                         "java.properties"));
219.1839 +
219.1840 +        /**
219.1841 +         * The class-only format <code>List</code> containing
219.1842 +         * <code>"java.class"</code>. This <code>List</code> is {@linkplain
219.1843 +         * Collections#unmodifiableList(List) unmodifiable}.
219.1844 +         *
219.1845 +         * @see #getFormats(String)
219.1846 +         */
219.1847 +        public static final List<String> FORMAT_CLASS
219.1848 +            = Collections.unmodifiableList(Arrays.asList("java.class"));
219.1849 +
219.1850 +        /**
219.1851 +         * The properties-only format <code>List</code> containing
219.1852 +         * <code>"java.properties"</code>. This <code>List</code> is
219.1853 +         * {@linkplain Collections#unmodifiableList(List) unmodifiable}.
219.1854 +         *
219.1855 +         * @see #getFormats(String)
219.1856 +         */
219.1857 +        public static final List<String> FORMAT_PROPERTIES
219.1858 +            = Collections.unmodifiableList(Arrays.asList("java.properties"));
219.1859 +
219.1860 +        /**
219.1861 +         * The time-to-live constant for not caching loaded resource bundle
219.1862 +         * instances.
219.1863 +         *
219.1864 +         * @see #getTimeToLive(String, Locale)
219.1865 +         */
219.1866 +        public static final long TTL_DONT_CACHE = -1;
219.1867 +
219.1868 +        /**
219.1869 +         * The time-to-live constant for disabling the expiration control
219.1870 +         * for loaded resource bundle instances in the cache.
219.1871 +         *
219.1872 +         * @see #getTimeToLive(String, Locale)
219.1873 +         */
219.1874 +        public static final long TTL_NO_EXPIRATION_CONTROL = -2;
219.1875 +
219.1876 +        private static final Control INSTANCE = new Control();
219.1877 +
219.1878 +        /**
219.1879 +         * Sole constructor. (For invocation by subclass constructors,
219.1880 +         * typically implicit.)
219.1881 +         */
219.1882 +        protected Control() {
219.1883 +        }
219.1884 +
219.1885 +        /**
219.1886 +         * Returns a <code>ResourceBundle.Control</code> in which the {@link
219.1887 +         * #getFormats(String) getFormats} method returns the specified
219.1888 +         * <code>formats</code>. The <code>formats</code> must be equal to
219.1889 +         * one of {@link Control#FORMAT_PROPERTIES}, {@link
219.1890 +         * Control#FORMAT_CLASS} or {@link
219.1891 +         * Control#FORMAT_DEFAULT}. <code>ResourceBundle.Control</code>
219.1892 +         * instances returned by this method are singletons and thread-safe.
219.1893 +         *
219.1894 +         * <p>Specifying {@link Control#FORMAT_DEFAULT} is equivalent to
219.1895 +         * instantiating the <code>ResourceBundle.Control</code> class,
219.1896 +         * except that this method returns a singleton.
219.1897 +         *
219.1898 +         * @param formats
219.1899 +         *        the formats to be returned by the
219.1900 +         *        <code>ResourceBundle.Control.getFormats</code> method
219.1901 +         * @return a <code>ResourceBundle.Control</code> supporting the
219.1902 +         *        specified <code>formats</code>
219.1903 +         * @exception NullPointerException
219.1904 +         *        if <code>formats</code> is <code>null</code>
219.1905 +         * @exception IllegalArgumentException
219.1906 +         *        if <code>formats</code> is unknown
219.1907 +         */
219.1908 +        public static final Control getControl(List<String> formats) {
219.1909 +            if (formats.equals(Control.FORMAT_PROPERTIES)) {
219.1910 +                return SingleFormatControl.PROPERTIES_ONLY;
219.1911 +            }
219.1912 +            if (formats.equals(Control.FORMAT_CLASS)) {
219.1913 +                return SingleFormatControl.CLASS_ONLY;
219.1914 +            }
219.1915 +            if (formats.equals(Control.FORMAT_DEFAULT)) {
219.1916 +                return Control.INSTANCE;
219.1917 +            }
219.1918 +            throw new IllegalArgumentException();
219.1919 +        }
219.1920 +
219.1921 +        /**
219.1922 +         * Returns a <code>ResourceBundle.Control</code> in which the {@link
219.1923 +         * #getFormats(String) getFormats} method returns the specified
219.1924 +         * <code>formats</code> and the {@link
219.1925 +         * Control#getFallbackLocale(String, Locale) getFallbackLocale}
219.1926 +         * method returns <code>null</code>. The <code>formats</code> must
219.1927 +         * be equal to one of {@link Control#FORMAT_PROPERTIES}, {@link
219.1928 +         * Control#FORMAT_CLASS} or {@link Control#FORMAT_DEFAULT}.
219.1929 +         * <code>ResourceBundle.Control</code> instances returned by this
219.1930 +         * method are singletons and thread-safe.
219.1931 +         *
219.1932 +         * @param formats
219.1933 +         *        the formats to be returned by the
219.1934 +         *        <code>ResourceBundle.Control.getFormats</code> method
219.1935 +         * @return a <code>ResourceBundle.Control</code> supporting the
219.1936 +         *        specified <code>formats</code> with no fallback
219.1937 +         *        <code>Locale</code> support
219.1938 +         * @exception NullPointerException
219.1939 +         *        if <code>formats</code> is <code>null</code>
219.1940 +         * @exception IllegalArgumentException
219.1941 +         *        if <code>formats</code> is unknown
219.1942 +         */
219.1943 +        public static final Control getNoFallbackControl(List<String> formats) {
219.1944 +            if (formats.equals(Control.FORMAT_DEFAULT)) {
219.1945 +                return NoFallbackControl.NO_FALLBACK;
219.1946 +            }
219.1947 +            if (formats.equals(Control.FORMAT_PROPERTIES)) {
219.1948 +                return NoFallbackControl.PROPERTIES_ONLY_NO_FALLBACK;
219.1949 +            }
219.1950 +            if (formats.equals(Control.FORMAT_CLASS)) {
219.1951 +                return NoFallbackControl.CLASS_ONLY_NO_FALLBACK;
219.1952 +            }
219.1953 +            throw new IllegalArgumentException();
219.1954 +        }
219.1955 +
219.1956 +        /**
219.1957 +         * Returns a <code>List</code> of <code>String</code>s containing
219.1958 +         * formats to be used to load resource bundles for the given
219.1959 +         * <code>baseName</code>. The <code>ResourceBundle.getBundle</code>
219.1960 +         * factory method tries to load resource bundles with formats in the
219.1961 +         * order specified by the list. The list returned by this method
219.1962 +         * must have at least one <code>String</code>. The predefined
219.1963 +         * formats are <code>"java.class"</code> for class-based resource
219.1964 +         * bundles and <code>"java.properties"</code> for {@linkplain
219.1965 +         * PropertyResourceBundle properties-based} ones. Strings starting
219.1966 +         * with <code>"java."</code> are reserved for future extensions and
219.1967 +         * must not be used by application-defined formats.
219.1968 +         *
219.1969 +         * <p>It is not a requirement to return an immutable (unmodifiable)
219.1970 +         * <code>List</code>.  However, the returned <code>List</code> must
219.1971 +         * not be mutated after it has been returned by
219.1972 +         * <code>getFormats</code>.
219.1973 +         *
219.1974 +         * <p>The default implementation returns {@link #FORMAT_DEFAULT} so
219.1975 +         * that the <code>ResourceBundle.getBundle</code> factory method
219.1976 +         * looks up first class-based resource bundles, then
219.1977 +         * properties-based ones.
219.1978 +         *
219.1979 +         * @param baseName
219.1980 +         *        the base name of the resource bundle, a fully qualified class
219.1981 +         *        name
219.1982 +         * @return a <code>List</code> of <code>String</code>s containing
219.1983 +         *        formats for loading resource bundles.
219.1984 +         * @exception NullPointerException
219.1985 +         *        if <code>baseName</code> is null
219.1986 +         * @see #FORMAT_DEFAULT
219.1987 +         * @see #FORMAT_CLASS
219.1988 +         * @see #FORMAT_PROPERTIES
219.1989 +         */
219.1990 +        public List<String> getFormats(String baseName) {
219.1991 +            if (baseName == null) {
219.1992 +                throw new NullPointerException();
219.1993 +            }
219.1994 +            return FORMAT_DEFAULT;
219.1995 +        }
219.1996 +
219.1997 +        /**
219.1998 +         * Returns a <code>List</code> of <code>Locale</code>s as candidate
219.1999 +         * locales for <code>baseName</code> and <code>locale</code>. This
219.2000 +         * method is called by the <code>ResourceBundle.getBundle</code>
219.2001 +         * factory method each time the factory method tries finding a
219.2002 +         * resource bundle for a target <code>Locale</code>.
219.2003 +         *
219.2004 +         * <p>The sequence of the candidate locales also corresponds to the
219.2005 +         * runtime resource lookup path (also known as the <I>parent
219.2006 +         * chain</I>), if the corresponding resource bundles for the
219.2007 +         * candidate locales exist and their parents are not defined by
219.2008 +         * loaded resource bundles themselves.  The last element of the list
219.2009 +         * must be a {@linkplain Locale#ROOT root locale} if it is desired to
219.2010 +         * have the base bundle as the terminal of the parent chain.
219.2011 +         *
219.2012 +         * <p>If the given locale is equal to <code>Locale.ROOT</code> (the
219.2013 +         * root locale), a <code>List</code> containing only the root
219.2014 +         * <code>Locale</code> must be returned. In this case, the
219.2015 +         * <code>ResourceBundle.getBundle</code> factory method loads only
219.2016 +         * the base bundle as the resulting resource bundle.
219.2017 +         *
219.2018 +         * <p>It is not a requirement to return an immutable (unmodifiable)
219.2019 +         * <code>List</code>. However, the returned <code>List</code> must not
219.2020 +         * be mutated after it has been returned by
219.2021 +         * <code>getCandidateLocales</code>.
219.2022 +         *
219.2023 +         * <p>The default implementation returns a <code>List</code> containing
219.2024 +         * <code>Locale</code>s using the rules described below.  In the
219.2025 +         * description below, <em>L</em>, <em>S</em>, <em>C</em> and <em>V</em>
219.2026 +         * respectively represent non-empty language, script, country, and
219.2027 +         * variant.  For example, [<em>L</em>, <em>C</em>] represents a
219.2028 +         * <code>Locale</code> that has non-empty values only for language and
219.2029 +         * country.  The form <em>L</em>("xx") represents the (non-empty)
219.2030 +         * language value is "xx".  For all cases, <code>Locale</code>s whose
219.2031 +         * final component values are empty strings are omitted.
219.2032 +         *
219.2033 +         * <ol><li>For an input <code>Locale</code> with an empty script value,
219.2034 +         * append candidate <code>Locale</code>s by omitting the final component
219.2035 +         * one by one as below:
219.2036 +         *
219.2037 +         * <ul>
219.2038 +         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
219.2039 +         * <li> [<em>L</em>, <em>C</em>]
219.2040 +         * <li> [<em>L</em>]
219.2041 +         * <li> <code>Locale.ROOT</code>
219.2042 +         * </ul>
219.2043 +         *
219.2044 +         * <li>For an input <code>Locale</code> with a non-empty script value,
219.2045 +         * append candidate <code>Locale</code>s by omitting the final component
219.2046 +         * up to language, then append candidates generated from the
219.2047 +         * <code>Locale</code> with country and variant restored:
219.2048 +         *
219.2049 +         * <ul>
219.2050 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V</em>]
219.2051 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
219.2052 +         * <li> [<em>L</em>, <em>S</em>]
219.2053 +         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
219.2054 +         * <li> [<em>L</em>, <em>C</em>]
219.2055 +         * <li> [<em>L</em>]
219.2056 +         * <li> <code>Locale.ROOT</code>
219.2057 +         * </ul>
219.2058 +         *
219.2059 +         * <li>For an input <code>Locale</code> with a variant value consisting
219.2060 +         * of multiple subtags separated by underscore, generate candidate
219.2061 +         * <code>Locale</code>s by omitting the variant subtags one by one, then
219.2062 +         * insert them after every occurence of <code> Locale</code>s with the
219.2063 +         * full variant value in the original list.  For example, if the
219.2064 +         * the variant consists of two subtags <em>V1</em> and <em>V2</em>:
219.2065 +         *
219.2066 +         * <ul>
219.2067 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
219.2068 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>]
219.2069 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
219.2070 +         * <li> [<em>L</em>, <em>S</em>]
219.2071 +         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
219.2072 +         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>]
219.2073 +         * <li> [<em>L</em>, <em>C</em>]
219.2074 +         * <li> [<em>L</em>]
219.2075 +         * <li> <code>Locale.ROOT</code>
219.2076 +         * </ul>
219.2077 +         *
219.2078 +         * <li>Special cases for Chinese.  When an input <code>Locale</code> has the
219.2079 +         * language "zh" (Chinese) and an empty script value, either "Hans" (Simplified) or
219.2080 +         * "Hant" (Traditional) might be supplied, depending on the country.
219.2081 +         * When the country is "CN" (China) or "SG" (Singapore), "Hans" is supplied.
219.2082 +         * When the country is "HK" (Hong Kong SAR China), "MO" (Macau SAR China),
219.2083 +         * or "TW" (Taiwan), "Hant" is supplied.  For all other countries or when the country
219.2084 +         * is empty, no script is supplied.  For example, for <code>Locale("zh", "CN")
219.2085 +         * </code>, the candidate list will be:
219.2086 +         * <ul>
219.2087 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hans"), <em>C</em>("CN")]
219.2088 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hans")]
219.2089 +         * <li> [<em>L</em>("zh"), <em>C</em>("CN")]
219.2090 +         * <li> [<em>L</em>("zh")]
219.2091 +         * <li> <code>Locale.ROOT</code>
219.2092 +         * </ul>
219.2093 +         *
219.2094 +         * For <code>Locale("zh", "TW")</code>, the candidate list will be:
219.2095 +         * <ul>
219.2096 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hant"), <em>C</em>("TW")]
219.2097 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hant")]
219.2098 +         * <li> [<em>L</em>("zh"), <em>C</em>("TW")]
219.2099 +         * <li> [<em>L</em>("zh")]
219.2100 +         * <li> <code>Locale.ROOT</code>
219.2101 +         * </ul>
219.2102 +         *
219.2103 +         * <li>Special cases for Norwegian.  Both <code>Locale("no", "NO",
219.2104 +         * "NY")</code> and <code>Locale("nn", "NO")</code> represent Norwegian
219.2105 +         * Nynorsk.  When a locale's language is "nn", the standard candidate
219.2106 +         * list is generated up to [<em>L</em>("nn")], and then the following
219.2107 +         * candidates are added:
219.2108 +         *
219.2109 +         * <ul><li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("NY")]
219.2110 +         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
219.2111 +         * <li> [<em>L</em>("no")]
219.2112 +         * <li> <code>Locale.ROOT</code>
219.2113 +         * </ul>
219.2114 +         *
219.2115 +         * If the locale is exactly <code>Locale("no", "NO", "NY")</code>, it is first
219.2116 +         * converted to <code>Locale("nn", "NO")</code> and then the above procedure is
219.2117 +         * followed.
219.2118 +         *
219.2119 +         * <p>Also, Java treats the language "no" as a synonym of Norwegian
219.2120 +         * Bokm&#xE5;l "nb".  Except for the single case <code>Locale("no",
219.2121 +         * "NO", "NY")</code> (handled above), when an input <code>Locale</code>
219.2122 +         * has language "no" or "nb", candidate <code>Locale</code>s with
219.2123 +         * language code "no" and "nb" are interleaved, first using the
219.2124 +         * requested language, then using its synonym. For example,
219.2125 +         * <code>Locale("nb", "NO", "POSIX")</code> generates the following
219.2126 +         * candidate list:
219.2127 +         *
219.2128 +         * <ul>
219.2129 +         * <li> [<em>L</em>("nb"), <em>C</em>("NO"), <em>V</em>("POSIX")]
219.2130 +         * <li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("POSIX")]
219.2131 +         * <li> [<em>L</em>("nb"), <em>C</em>("NO")]
219.2132 +         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
219.2133 +         * <li> [<em>L</em>("nb")]
219.2134 +         * <li> [<em>L</em>("no")]
219.2135 +         * <li> <code>Locale.ROOT</code>
219.2136 +         * </ul>
219.2137 +         *
219.2138 +         * <code>Locale("no", "NO", "POSIX")</code> would generate the same list
219.2139 +         * except that locales with "no" would appear before the corresponding
219.2140 +         * locales with "nb".</li>
219.2141 +         *
219.2142 +         * </li>
219.2143 +         * </ol>
219.2144 +         *
219.2145 +         * <p>The default implementation uses an {@link ArrayList} that
219.2146 +         * overriding implementations may modify before returning it to the
219.2147 +         * caller. However, a subclass must not modify it after it has
219.2148 +         * been returned by <code>getCandidateLocales</code>.
219.2149 +         *
219.2150 +         * <p>For example, if the given <code>baseName</code> is "Messages"
219.2151 +         * and the given <code>locale</code> is
219.2152 +         * <code>Locale("ja",&nbsp;"",&nbsp;"XX")</code>, then a
219.2153 +         * <code>List</code> of <code>Locale</code>s:
219.2154 +         * <pre>
219.2155 +         *     Locale("ja", "", "XX")
219.2156 +         *     Locale("ja")
219.2157 +         *     Locale.ROOT
219.2158 +         * </pre>
219.2159 +         * is returned. And if the resource bundles for the "ja" and
219.2160 +         * "" <code>Locale</code>s are found, then the runtime resource
219.2161 +         * lookup path (parent chain) is:
219.2162 +         * <pre>
219.2163 +         *     Messages_ja -> Messages
219.2164 +         * </pre>
219.2165 +         *
219.2166 +         * @param baseName
219.2167 +         *        the base name of the resource bundle, a fully
219.2168 +         *        qualified class name
219.2169 +         * @param locale
219.2170 +         *        the locale for which a resource bundle is desired
219.2171 +         * @return a <code>List</code> of candidate
219.2172 +         *        <code>Locale</code>s for the given <code>locale</code>
219.2173 +         * @exception NullPointerException
219.2174 +         *        if <code>baseName</code> or <code>locale</code> is
219.2175 +         *        <code>null</code>
219.2176 +         */
219.2177 +        public List<Locale> getCandidateLocales(String baseName, Locale locale) {
219.2178 +            if (baseName == null) {
219.2179 +                throw new NullPointerException();
219.2180 +            }
219.2181 +            return new ArrayList<>(CANDIDATES_CACHE.get(locale));
219.2182 +        }
219.2183 +
219.2184 +        private static final CandidateListCache CANDIDATES_CACHE = new CandidateListCache();
219.2185 +
219.2186 +        private static class CandidateListCache {
219.2187 +            private Locale prevQuery;
219.2188 +            private List<Locale> prevResult;
219.2189 +            
219.2190 +            public List<Locale> get(Locale l) {
219.2191 +                if (prevQuery == l) {
219.2192 +                    return prevResult;
219.2193 +                }
219.2194 +                prevResult = createObject(l);
219.2195 +                prevQuery = l;
219.2196 +                return prevResult;
219.2197 +            }
219.2198 +            
219.2199 +            protected List<Locale> createObject(Locale base) {
219.2200 +                String language = base.getLanguage();
219.2201 +                String script = base.getScript();
219.2202 +                String region = base.getRegion();
219.2203 +                String variant = base.getVariant();
219.2204 +
219.2205 +                // Special handling for Norwegian
219.2206 +                boolean isNorwegianBokmal = false;
219.2207 +                boolean isNorwegianNynorsk = false;
219.2208 +                if (language.equals("no")) {
219.2209 +                    if (region.equals("NO") && variant.equals("NY")) {
219.2210 +                        variant = "";
219.2211 +                        isNorwegianNynorsk = true;
219.2212 +                    } else {
219.2213 +                        isNorwegianBokmal = true;
219.2214 +                    }
219.2215 +                }
219.2216 +                if (language.equals("nb") || isNorwegianBokmal) {
219.2217 +                    List<Locale> tmpList = getDefaultList("nb", script, region, variant);
219.2218 +                    // Insert a locale replacing "nb" with "no" for every list entry
219.2219 +                    List<Locale> bokmalList = new LinkedList<>();
219.2220 +                    for (Locale l : tmpList) {
219.2221 +                        bokmalList.add(l);
219.2222 +                        if (l.getLanguage().length() == 0) {
219.2223 +                            break;
219.2224 +                        }
219.2225 +                        bokmalList.add(Locale.getInstance("no", l.getScript(), l.getCountry(),
219.2226 +                                l.getVariant(), null));
219.2227 +                    }
219.2228 +                    return bokmalList;
219.2229 +                } else if (language.equals("nn") || isNorwegianNynorsk) {
219.2230 +                    // Insert no_NO_NY, no_NO, no after nn
219.2231 +                    List<Locale> nynorskList = getDefaultList("nn", script, region, variant);
219.2232 +                    int idx = nynorskList.size() - 1;
219.2233 +                    nynorskList.add(idx++, Locale.getInstance("no", "NO", "NY"));
219.2234 +                    nynorskList.add(idx++, Locale.getInstance("no", "NO", ""));
219.2235 +                    nynorskList.add(idx++, Locale.getInstance("no", "", ""));
219.2236 +                    return nynorskList;
219.2237 +                }
219.2238 +                // Special handling for Chinese
219.2239 +                else if (language.equals("zh")) {
219.2240 +                    if (script.length() == 0 && region.length() > 0) {
219.2241 +                        // Supply script for users who want to use zh_Hans/zh_Hant
219.2242 +                        // as bundle names (recommended for Java7+)
219.2243 +                        if (region.equals("TW") || region.equals("HK") || region.equals("MO")) {
219.2244 +                            script = "Hant";
219.2245 +                        } else if (region.equals("CN") || region.equals("SG")) {
219.2246 +                            script = "Hans";
219.2247 +                        }
219.2248 +                    } else if (script.length() > 0 && region.length() == 0) {
219.2249 +                        // Supply region(country) for users who still package Chinese
219.2250 +                        // bundles using old convension.
219.2251 +                        if (script.equals("Hans")) {
219.2252 +                            region = "CN";
219.2253 +                        } else if (script.equals("Hant")) {
219.2254 +                            region = "TW";
219.2255 +                        }
219.2256 +                    }
219.2257 +                }
219.2258 +
219.2259 +                return getDefaultList(language, script, region, variant);
219.2260 +            }
219.2261 +
219.2262 +            private static List<Locale> getDefaultList(String language, String script, String region, String variant) {
219.2263 +                List<String> variants = null;
219.2264 +
219.2265 +                if (variant.length() > 0) {
219.2266 +                    variants = new LinkedList<>();
219.2267 +                    int idx = variant.length();
219.2268 +                    while (idx != -1) {
219.2269 +                        variants.add(variant.substring(0, idx));
219.2270 +                        idx = variant.lastIndexOf('_', --idx);
219.2271 +                    }
219.2272 +                }
219.2273 +
219.2274 +                List<Locale> list = new LinkedList<>();
219.2275 +
219.2276 +                if (variants != null) {
219.2277 +                    for (String v : variants) {
219.2278 +                        list.add(Locale.getInstance(language, script, region, v, null));
219.2279 +                    }
219.2280 +                }
219.2281 +                if (region.length() > 0) {
219.2282 +                    list.add(Locale.getInstance(language, script, region, "", null));
219.2283 +                }
219.2284 +                if (script.length() > 0) {
219.2285 +                    list.add(Locale.getInstance(language, script, "", "", null));
219.2286 +
219.2287 +                    // With script, after truncating variant, region and script,
219.2288 +                    // start over without script.
219.2289 +                    if (variants != null) {
219.2290 +                        for (String v : variants) {
219.2291 +                            list.add(Locale.getInstance(language, "", region, v, null));
219.2292 +                        }
219.2293 +                    }
219.2294 +                    if (region.length() > 0) {
219.2295 +                        list.add(Locale.getInstance(language, "", region, "", null));
219.2296 +                    }
219.2297 +                }
219.2298 +                if (language.length() > 0) {
219.2299 +                    list.add(Locale.getInstance(language, "", "", "", null));
219.2300 +                }
219.2301 +                // Add root locale at the end
219.2302 +                list.add(Locale.ROOT);
219.2303 +
219.2304 +                return list;
219.2305 +            }
219.2306 +        }
219.2307 +
219.2308 +        /**
219.2309 +         * Returns a <code>Locale</code> to be used as a fallback locale for
219.2310 +         * further resource bundle searches by the
219.2311 +         * <code>ResourceBundle.getBundle</code> factory method. This method
219.2312 +         * is called from the factory method every time when no resulting
219.2313 +         * resource bundle has been found for <code>baseName</code> and
219.2314 +         * <code>locale</code>, where locale is either the parameter for
219.2315 +         * <code>ResourceBundle.getBundle</code> or the previous fallback
219.2316 +         * locale returned by this method.
219.2317 +         *
219.2318 +         * <p>The method returns <code>null</code> if no further fallback
219.2319 +         * search is desired.
219.2320 +         *
219.2321 +         * <p>The default implementation returns the {@linkplain
219.2322 +         * Locale#getDefault() default <code>Locale</code>} if the given
219.2323 +         * <code>locale</code> isn't the default one.  Otherwise,
219.2324 +         * <code>null</code> is returned.
219.2325 +         *
219.2326 +         * @param baseName
219.2327 +         *        the base name of the resource bundle, a fully
219.2328 +         *        qualified class name for which
219.2329 +         *        <code>ResourceBundle.getBundle</code> has been
219.2330 +         *        unable to find any resource bundles (except for the
219.2331 +         *        base bundle)
219.2332 +         * @param locale
219.2333 +         *        the <code>Locale</code> for which
219.2334 +         *        <code>ResourceBundle.getBundle</code> has been
219.2335 +         *        unable to find any resource bundles (except for the
219.2336 +         *        base bundle)
219.2337 +         * @return a <code>Locale</code> for the fallback search,
219.2338 +         *        or <code>null</code> if no further fallback search
219.2339 +         *        is desired.
219.2340 +         * @exception NullPointerException
219.2341 +         *        if <code>baseName</code> or <code>locale</code>
219.2342 +         *        is <code>null</code>
219.2343 +         */
219.2344 +        public Locale getFallbackLocale(String baseName, Locale locale) {
219.2345 +            if (baseName == null) {
219.2346 +                throw new NullPointerException();
219.2347 +            }
219.2348 +            Locale defaultLocale = Locale.getDefault();
219.2349 +            return locale.equals(defaultLocale) ? null : defaultLocale;
219.2350 +        }
219.2351 +
219.2352 +        /**
219.2353 +         * Instantiates a resource bundle for the given bundle name of the
219.2354 +         * given format and locale, using the given class loader if
219.2355 +         * necessary. This method returns <code>null</code> if there is no
219.2356 +         * resource bundle available for the given parameters. If a resource
219.2357 +         * bundle can't be instantiated due to an unexpected error, the
219.2358 +         * error must be reported by throwing an <code>Error</code> or
219.2359 +         * <code>Exception</code> rather than simply returning
219.2360 +         * <code>null</code>.
219.2361 +         *
219.2362 +         * <p>If the <code>reload</code> flag is <code>true</code>, it
219.2363 +         * indicates that this method is being called because the previously
219.2364 +         * loaded resource bundle has expired.
219.2365 +         *
219.2366 +         * <p>The default implementation instantiates a
219.2367 +         * <code>ResourceBundle</code> as follows.
219.2368 +         *
219.2369 +         * <ul>
219.2370 +         *
219.2371 +         * <li>The bundle name is obtained by calling {@link
219.2372 +         * #toBundleName(String, Locale) toBundleName(baseName,
219.2373 +         * locale)}.</li>
219.2374 +         *
219.2375 +         * <li>If <code>format</code> is <code>"java.class"</code>, the
219.2376 +         * {@link Class} specified by the bundle name is loaded by calling
219.2377 +         * {@link ClassLoader#loadClass(String)}. Then, a
219.2378 +         * <code>ResourceBundle</code> is instantiated by calling {@link
219.2379 +         * Class#newInstance()}.  Note that the <code>reload</code> flag is
219.2380 +         * ignored for loading class-based resource bundles in this default
219.2381 +         * implementation.</li>
219.2382 +         *
219.2383 +         * <li>If <code>format</code> is <code>"java.properties"</code>,
219.2384 +         * {@link #toResourceName(String, String) toResourceName(bundlename,
219.2385 +         * "properties")} is called to get the resource name.
219.2386 +         * If <code>reload</code> is <code>true</code>, {@link
219.2387 +         * ClassLoader#getResource(String) load.getResource} is called
219.2388 +         * to get a {@link URL} for creating a {@link
219.2389 +         * URLConnection}. This <code>URLConnection</code> is used to
219.2390 +         * {@linkplain URLConnection#setUseCaches(boolean) disable the
219.2391 +         * caches} of the underlying resource loading layers,
219.2392 +         * and to {@linkplain URLConnection#getInputStream() get an
219.2393 +         * <code>InputStream</code>}.
219.2394 +         * Otherwise, {@link ClassLoader#getResourceAsStream(String)
219.2395 +         * loader.getResourceAsStream} is called to get an {@link
219.2396 +         * InputStream}. Then, a {@link
219.2397 +         * PropertyResourceBundle} is constructed with the
219.2398 +         * <code>InputStream</code>.</li>
219.2399 +         *
219.2400 +         * <li>If <code>format</code> is neither <code>"java.class"</code>
219.2401 +         * nor <code>"java.properties"</code>, an
219.2402 +         * <code>IllegalArgumentException</code> is thrown.</li>
219.2403 +         *
219.2404 +         * </ul>
219.2405 +         *
219.2406 +         * @param baseName
219.2407 +         *        the base bundle name of the resource bundle, a fully
219.2408 +         *        qualified class name
219.2409 +         * @param locale
219.2410 +         *        the locale for which the resource bundle should be
219.2411 +         *        instantiated
219.2412 +         * @param format
219.2413 +         *        the resource bundle format to be loaded
219.2414 +         * @param loader
219.2415 +         *        the <code>ClassLoader</code> to use to load the bundle
219.2416 +         * @param reload
219.2417 +         *        the flag to indicate bundle reloading; <code>true</code>
219.2418 +         *        if reloading an expired resource bundle,
219.2419 +         *        <code>false</code> otherwise
219.2420 +         * @return the resource bundle instance,
219.2421 +         *        or <code>null</code> if none could be found.
219.2422 +         * @exception NullPointerException
219.2423 +         *        if <code>bundleName</code>, <code>locale</code>,
219.2424 +         *        <code>format</code>, or <code>loader</code> is
219.2425 +         *        <code>null</code>, or if <code>null</code> is returned by
219.2426 +         *        {@link #toBundleName(String, Locale) toBundleName}
219.2427 +         * @exception IllegalArgumentException
219.2428 +         *        if <code>format</code> is unknown, or if the resource
219.2429 +         *        found for the given parameters contains malformed data.
219.2430 +         * @exception ClassCastException
219.2431 +         *        if the loaded class cannot be cast to <code>ResourceBundle</code>
219.2432 +         * @exception IllegalAccessException
219.2433 +         *        if the class or its nullary constructor is not
219.2434 +         *        accessible.
219.2435 +         * @exception InstantiationException
219.2436 +         *        if the instantiation of a class fails for some other
219.2437 +         *        reason.
219.2438 +         * @exception ExceptionInInitializerError
219.2439 +         *        if the initialization provoked by this method fails.
219.2440 +         * @exception SecurityException
219.2441 +         *        If a security manager is present and creation of new
219.2442 +         *        instances is denied. See {@link Class#newInstance()}
219.2443 +         *        for details.
219.2444 +         * @exception IOException
219.2445 +         *        if an error occurred when reading resources using
219.2446 +         *        any I/O operations
219.2447 +         */
219.2448 +        public ResourceBundle newBundle(String baseName, Locale locale, String format,
219.2449 +                                        ClassLoader loader, boolean reload)
219.2450 +                    throws IllegalAccessException, InstantiationException, IOException {
219.2451 +            String bundleName = toBundleName(baseName, locale);
219.2452 +            ResourceBundle bundle = null;
219.2453 +            if (format.equals("java.class")) {
219.2454 +                try {
219.2455 +                    Class<? extends ResourceBundle> bundleClass
219.2456 +                        = (Class<? extends ResourceBundle>)(loader != null ? 
219.2457 +                        loader.loadClass(bundleName) :
219.2458 +                        Class.forName(bundleName));
219.2459 +
219.2460 +                    // If the class isn't a ResourceBundle subclass, throw a
219.2461 +                    // ClassCastException.
219.2462 +                    if (ResourceBundle.class.isAssignableFrom(bundleClass)) {
219.2463 +                        bundle = bundleClass.newInstance();
219.2464 +                    } else {
219.2465 +                        throw new ClassCastException(bundleClass.getName()
219.2466 +                                     + " cannot be cast to ResourceBundle");
219.2467 +                    }
219.2468 +                } catch (ClassNotFoundException e) {
219.2469 +                }
219.2470 +            } else if (format.equals("java.properties")) {
219.2471 +                final String resourceName = toResourceName(bundleName, "properties");
219.2472 +                final ClassLoader classLoader = loader;
219.2473 +                final boolean reloadFlag = reload;
219.2474 +                InputStream stream = classLoader != null ? classLoader.getResourceAsStream(resourceName) :
219.2475 +                    ResourceBundle.class.getResourceAsStream("/" + resourceName);
219.2476 +                if (stream != null) {
219.2477 +                    try {
219.2478 +                        bundle = new PropertyResourceBundle(stream);
219.2479 +                    } finally {
219.2480 +                        stream.close();
219.2481 +                    }
219.2482 +                }   
219.2483 +            } else {
219.2484 +                throw new IllegalArgumentException("unknown format: " + format);
219.2485 +            }
219.2486 +            return bundle;
219.2487 +        }
219.2488 +
219.2489 +        /**
219.2490 +         * Returns the time-to-live (TTL) value for resource bundles that
219.2491 +         * are loaded under this
219.2492 +         * <code>ResourceBundle.Control</code>. Positive time-to-live values
219.2493 +         * specify the number of milliseconds a bundle can remain in the
219.2494 +         * cache without being validated against the source data from which
219.2495 +         * it was constructed. The value 0 indicates that a bundle must be
219.2496 +         * validated each time it is retrieved from the cache. {@link
219.2497 +         * #TTL_DONT_CACHE} specifies that loaded resource bundles are not
219.2498 +         * put in the cache. {@link #TTL_NO_EXPIRATION_CONTROL} specifies
219.2499 +         * that loaded resource bundles are put in the cache with no
219.2500 +         * expiration control.
219.2501 +         *
219.2502 +         * <p>The expiration affects only the bundle loading process by the
219.2503 +         * <code>ResourceBundle.getBundle</code> factory method.  That is,
219.2504 +         * if the factory method finds a resource bundle in the cache that
219.2505 +         * has expired, the factory method calls the {@link
219.2506 +         * #needsReload(String, Locale, String, ClassLoader, ResourceBundle,
219.2507 +         * long) needsReload} method to determine whether the resource
219.2508 +         * bundle needs to be reloaded. If <code>needsReload</code> returns
219.2509 +         * <code>true</code>, the cached resource bundle instance is removed
219.2510 +         * from the cache. Otherwise, the instance stays in the cache,
219.2511 +         * updated with the new TTL value returned by this method.
219.2512 +         *
219.2513 +         * <p>All cached resource bundles are subject to removal from the
219.2514 +         * cache due to memory constraints of the runtime environment.
219.2515 +         * Returning a large positive value doesn't mean to lock loaded
219.2516 +         * resource bundles in the cache.
219.2517 +         *
219.2518 +         * <p>The default implementation returns {@link #TTL_NO_EXPIRATION_CONTROL}.
219.2519 +         *
219.2520 +         * @param baseName
219.2521 +         *        the base name of the resource bundle for which the
219.2522 +         *        expiration value is specified.
219.2523 +         * @param locale
219.2524 +         *        the locale of the resource bundle for which the
219.2525 +         *        expiration value is specified.
219.2526 +         * @return the time (0 or a positive millisecond offset from the
219.2527 +         *        cached time) to get loaded bundles expired in the cache,
219.2528 +         *        {@link #TTL_NO_EXPIRATION_CONTROL} to disable the
219.2529 +         *        expiration control, or {@link #TTL_DONT_CACHE} to disable
219.2530 +         *        caching.
219.2531 +         * @exception NullPointerException
219.2532 +         *        if <code>baseName</code> or <code>locale</code> is
219.2533 +         *        <code>null</code>
219.2534 +         */
219.2535 +        public long getTimeToLive(String baseName, Locale locale) {
219.2536 +            if (baseName == null || locale == null) {
219.2537 +                throw new NullPointerException();
219.2538 +            }
219.2539 +            return TTL_NO_EXPIRATION_CONTROL;
219.2540 +        }
219.2541 +
219.2542 +        /**
219.2543 +         * Determines if the expired <code>bundle</code> in the cache needs
219.2544 +         * to be reloaded based on the loading time given by
219.2545 +         * <code>loadTime</code> or some other criteria. The method returns
219.2546 +         * <code>true</code> if reloading is required; <code>false</code>
219.2547 +         * otherwise. <code>loadTime</code> is a millisecond offset since
219.2548 +         * the <a href="Calendar.html#Epoch"> <code>Calendar</code>
219.2549 +         * Epoch</a>.
219.2550 +         *
219.2551 +         * The calling <code>ResourceBundle.getBundle</code> factory method
219.2552 +         * calls this method on the <code>ResourceBundle.Control</code>
219.2553 +         * instance used for its current invocation, not on the instance
219.2554 +         * used in the invocation that originally loaded the resource
219.2555 +         * bundle.
219.2556 +         *
219.2557 +         * <p>The default implementation compares <code>loadTime</code> and
219.2558 +         * the last modified time of the source data of the resource
219.2559 +         * bundle. If it's determined that the source data has been modified
219.2560 +         * since <code>loadTime</code>, <code>true</code> is
219.2561 +         * returned. Otherwise, <code>false</code> is returned. This
219.2562 +         * implementation assumes that the given <code>format</code> is the
219.2563 +         * same string as its file suffix if it's not one of the default
219.2564 +         * formats, <code>"java.class"</code> or
219.2565 +         * <code>"java.properties"</code>.
219.2566 +         *
219.2567 +         * @param baseName
219.2568 +         *        the base bundle name of the resource bundle, a
219.2569 +         *        fully qualified class name
219.2570 +         * @param locale
219.2571 +         *        the locale for which the resource bundle
219.2572 +         *        should be instantiated
219.2573 +         * @param format
219.2574 +         *        the resource bundle format to be loaded
219.2575 +         * @param loader
219.2576 +         *        the <code>ClassLoader</code> to use to load the bundle
219.2577 +         * @param bundle
219.2578 +         *        the resource bundle instance that has been expired
219.2579 +         *        in the cache
219.2580 +         * @param loadTime
219.2581 +         *        the time when <code>bundle</code> was loaded and put
219.2582 +         *        in the cache
219.2583 +         * @return <code>true</code> if the expired bundle needs to be
219.2584 +         *        reloaded; <code>false</code> otherwise.
219.2585 +         * @exception NullPointerException
219.2586 +         *        if <code>baseName</code>, <code>locale</code>,
219.2587 +         *        <code>format</code>, <code>loader</code>, or
219.2588 +         *        <code>bundle</code> is <code>null</code>
219.2589 +         */
219.2590 +        public boolean needsReload(String baseName, Locale locale,
219.2591 +                                   String format, ClassLoader loader,
219.2592 +                                   ResourceBundle bundle, long loadTime) {
219.2593 +            if (bundle == null) {
219.2594 +                throw new NullPointerException();
219.2595 +            }
219.2596 +            if (format.equals("java.class") || format.equals("java.properties")) {
219.2597 +                format = format.substring(5);
219.2598 +            }
219.2599 +            boolean result = false;
219.2600 +            try {
219.2601 +/*
219.2602 +                String resourceName = toResourceName(toBundleName(baseName, locale), format);
219.2603 +                URL url = loader.getResource(resourceName);
219.2604 +                if (url != null) {
219.2605 +                    long lastModified = 0;
219.2606 +                    URLConnection connection = url.openConnection();
219.2607 +                    if (connection != null) {
219.2608 +                        // disable caches to get the correct data
219.2609 +                        connection.setUseCaches(false);
219.2610 +                        if (connection instanceof JarURLConnection) {
219.2611 +                            JarEntry ent = ((JarURLConnection)connection).getJarEntry();
219.2612 +                            if (ent != null) {
219.2613 +                                lastModified = ent.getTime();
219.2614 +                                if (lastModified == -1) {
219.2615 +                                    lastModified = 0;
219.2616 +                                }
219.2617 +                            }
219.2618 +                        } else {
219.2619 +                            lastModified = connection.getLastModified();
219.2620 +                        }
219.2621 +                    }
219.2622 +                    result = lastModified >= loadTime;
219.2623 +                }
219.2624 +                */
219.2625 +            } catch (NullPointerException npe) {
219.2626 +                throw npe;
219.2627 +            } catch (Exception e) {
219.2628 +                // ignore other exceptions
219.2629 +            }
219.2630 +            return result;
219.2631 +        }
219.2632 +
219.2633 +        /**
219.2634 +         * Converts the given <code>baseName</code> and <code>locale</code>
219.2635 +         * to the bundle name. This method is called from the default
219.2636 +         * implementation of the {@link #newBundle(String, Locale, String,
219.2637 +         * ClassLoader, boolean) newBundle} and {@link #needsReload(String,
219.2638 +         * Locale, String, ClassLoader, ResourceBundle, long) needsReload}
219.2639 +         * methods.
219.2640 +         *
219.2641 +         * <p>This implementation returns the following value:
219.2642 +         * <pre>
219.2643 +         *     baseName + "_" + language + "_" + script + "_" + country + "_" + variant
219.2644 +         * </pre>
219.2645 +         * where <code>language</code>, <code>script</code>, <code>country</code>,
219.2646 +         * and <code>variant</code> are the language, script, country, and variant
219.2647 +         * values of <code>locale</code>, respectively. Final component values that
219.2648 +         * are empty Strings are omitted along with the preceding '_'.  When the
219.2649 +         * script is empty, the script value is ommitted along with the preceding '_'.
219.2650 +         * If all of the values are empty strings, then <code>baseName</code>
219.2651 +         * is returned.
219.2652 +         *
219.2653 +         * <p>For example, if <code>baseName</code> is
219.2654 +         * <code>"baseName"</code> and <code>locale</code> is
219.2655 +         * <code>Locale("ja",&nbsp;"",&nbsp;"XX")</code>, then
219.2656 +         * <code>"baseName_ja_&thinsp;_XX"</code> is returned. If the given
219.2657 +         * locale is <code>Locale("en")</code>, then
219.2658 +         * <code>"baseName_en"</code> is returned.
219.2659 +         *
219.2660 +         * <p>Overriding this method allows applications to use different
219.2661 +         * conventions in the organization and packaging of localized
219.2662 +         * resources.
219.2663 +         *
219.2664 +         * @param baseName
219.2665 +         *        the base name of the resource bundle, a fully
219.2666 +         *        qualified class name
219.2667 +         * @param locale
219.2668 +         *        the locale for which a resource bundle should be
219.2669 +         *        loaded
219.2670 +         * @return the bundle name for the resource bundle
219.2671 +         * @exception NullPointerException
219.2672 +         *        if <code>baseName</code> or <code>locale</code>
219.2673 +         *        is <code>null</code>
219.2674 +         */
219.2675 +        public String toBundleName(String baseName, Locale locale) {
219.2676 +            if (locale == Locale.ROOT) {
219.2677 +                return baseName;
219.2678 +            }
219.2679 +
219.2680 +            String language = locale.getLanguage();
219.2681 +            String script = locale.getScript();
219.2682 +            String country = locale.getCountry();
219.2683 +            String variant = locale.getVariant();
219.2684 +
219.2685 +            if (language == "" && country == "" && variant == "") {
219.2686 +                return baseName;
219.2687 +            }
219.2688 +
219.2689 +            StringBuilder sb = new StringBuilder(baseName);
219.2690 +            sb.append('_');
219.2691 +            if (script != "") {
219.2692 +                if (variant != "") {
219.2693 +                    sb.append(language).append('_').append(script).append('_').append(country).append('_').append(variant);
219.2694 +                } else if (country != "") {
219.2695 +                    sb.append(language).append('_').append(script).append('_').append(country);
219.2696 +                } else {
219.2697 +                    sb.append(language).append('_').append(script);
219.2698 +                }
219.2699 +            } else {
219.2700 +                if (variant != "") {
219.2701 +                    sb.append(language).append('_').append(country).append('_').append(variant);
219.2702 +                } else if (country != "") {
219.2703 +                    sb.append(language).append('_').append(country);
219.2704 +                } else {
219.2705 +                    sb.append(language);
219.2706 +                }
219.2707 +            }
219.2708 +            return sb.toString();
219.2709 +
219.2710 +        }
219.2711 +
219.2712 +        /**
219.2713 +         * Converts the given <code>bundleName</code> to the form required
219.2714 +         * by the {@link ClassLoader#getResource ClassLoader.getResource}
219.2715 +         * method by replacing all occurrences of <code>'.'</code> in
219.2716 +         * <code>bundleName</code> with <code>'/'</code> and appending a
219.2717 +         * <code>'.'</code> and the given file <code>suffix</code>. For
219.2718 +         * example, if <code>bundleName</code> is
219.2719 +         * <code>"foo.bar.MyResources_ja_JP"</code> and <code>suffix</code>
219.2720 +         * is <code>"properties"</code>, then
219.2721 +         * <code>"foo/bar/MyResources_ja_JP.properties"</code> is returned.
219.2722 +         *
219.2723 +         * @param bundleName
219.2724 +         *        the bundle name
219.2725 +         * @param suffix
219.2726 +         *        the file type suffix
219.2727 +         * @return the converted resource name
219.2728 +         * @exception NullPointerException
219.2729 +         *         if <code>bundleName</code> or <code>suffix</code>
219.2730 +         *         is <code>null</code>
219.2731 +         */
219.2732 +        public final String toResourceName(String bundleName, String suffix) {
219.2733 +            StringBuilder sb = new StringBuilder(bundleName.length() + 1 + suffix.length());
219.2734 +            sb.append(bundleName.replace('.', '/')).append('.').append(suffix);
219.2735 +            return sb.toString();
219.2736 +        }
219.2737 +    }
219.2738 +
219.2739 +    private static class SingleFormatControl extends Control {
219.2740 +        private static final Control PROPERTIES_ONLY
219.2741 +            = new SingleFormatControl(FORMAT_PROPERTIES);
219.2742 +
219.2743 +        private static final Control CLASS_ONLY
219.2744 +            = new SingleFormatControl(FORMAT_CLASS);
219.2745 +
219.2746 +        private final List<String> formats;
219.2747 +
219.2748 +        protected SingleFormatControl(List<String> formats) {
219.2749 +            this.formats = formats;
219.2750 +        }
219.2751 +
219.2752 +        public List<String> getFormats(String baseName) {
219.2753 +            if (baseName == null) {
219.2754 +                throw new NullPointerException();
219.2755 +            }
219.2756 +            return formats;
219.2757 +        }
219.2758 +    }
219.2759 +
219.2760 +    private static final class NoFallbackControl extends SingleFormatControl {
219.2761 +        private static final Control NO_FALLBACK
219.2762 +            = new NoFallbackControl(FORMAT_DEFAULT);
219.2763 +
219.2764 +        private static final Control PROPERTIES_ONLY_NO_FALLBACK
219.2765 +            = new NoFallbackControl(FORMAT_PROPERTIES);
219.2766 +
219.2767 +        private static final Control CLASS_ONLY_NO_FALLBACK
219.2768 +            = new NoFallbackControl(FORMAT_CLASS);
219.2769 +
219.2770 +        protected NoFallbackControl(List<String> formats) {
219.2771 +            super(formats);
219.2772 +        }
219.2773 +
219.2774 +        public Locale getFallbackLocale(String baseName, Locale locale) {
219.2775 +            if (baseName == null || locale == null) {
219.2776 +                throw new NullPointerException();
219.2777 +            }
219.2778 +            return null;
219.2779 +        }
219.2780 +    }
219.2781 +}
   220.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   220.2 +++ b/rt/emul/compact/src/main/java/java/util/SimpleTimeZone.java	Wed Apr 30 15:04:10 2014 +0200
   220.3 @@ -0,0 +1,1737 @@
   220.4 +/*
   220.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   220.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   220.7 + *
   220.8 + * This code is free software; you can redistribute it and/or modify it
   220.9 + * under the terms of the GNU General Public License version 2 only, as
  220.10 + * published by the Free Software Foundation.  Oracle designates this
  220.11 + * particular file as subject to the "Classpath" exception as provided
  220.12 + * by Oracle in the LICENSE file that accompanied this code.
  220.13 + *
  220.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  220.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  220.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  220.17 + * version 2 for more details (a copy is included in the LICENSE file that
  220.18 + * accompanied this code).
  220.19 + *
  220.20 + * You should have received a copy of the GNU General Public License version
  220.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  220.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  220.23 + *
  220.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  220.25 + * or visit www.oracle.com if you need additional information or have any
  220.26 + * questions.
  220.27 + */
  220.28 +
  220.29 +/*
  220.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  220.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  220.32 + *
  220.33 + *   The original version of this source code and documentation is copyrighted
  220.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  220.35 + * materials are provided under terms of a License Agreement between Taligent
  220.36 + * and Sun. This technology is protected by multiple US and International
  220.37 + * patents. This notice and attribution to Taligent may not be removed.
  220.38 + *   Taligent is a registered trademark of Taligent, Inc.
  220.39 + *
  220.40 + */
  220.41 +
  220.42 +package java.util;
  220.43 +
  220.44 +import java.io.ObjectInputStream;
  220.45 +import java.io.ObjectOutputStream;
  220.46 +import java.io.IOException;
  220.47 +import java.util.Date.BaseCalendar;
  220.48 +
  220.49 +/**
  220.50 + * <code>SimpleTimeZone</code> is a concrete subclass of <code>TimeZone</code>
  220.51 + * that represents a time zone for use with a Gregorian calendar.
  220.52 + * The class holds an offset from GMT, called <em>raw offset</em>, and start
  220.53 + * and end rules for a daylight saving time schedule.  Since it only holds
  220.54 + * single values for each, it cannot handle historical changes in the offset
  220.55 + * from GMT and the daylight saving schedule, except that the {@link
  220.56 + * #setStartYear setStartYear} method can specify the year when the daylight
  220.57 + * saving time schedule starts in effect.
  220.58 + * <p>
  220.59 + * To construct a <code>SimpleTimeZone</code> with a daylight saving time
  220.60 + * schedule, the schedule can be described with a set of rules,
  220.61 + * <em>start-rule</em> and <em>end-rule</em>. A day when daylight saving time
  220.62 + * starts or ends is specified by a combination of <em>month</em>,
  220.63 + * <em>day-of-month</em>, and <em>day-of-week</em> values. The <em>month</em>
  220.64 + * value is represented by a Calendar {@link Calendar#MONTH MONTH} field
  220.65 + * value, such as {@link Calendar#MARCH}. The <em>day-of-week</em> value is
  220.66 + * represented by a Calendar {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} value,
  220.67 + * such as {@link Calendar#SUNDAY SUNDAY}. The meanings of value combinations
  220.68 + * are as follows.
  220.69 + *
  220.70 + * <ul>
  220.71 + * <li><b>Exact day of month</b><br>
  220.72 + * To specify an exact day of month, set the <em>month</em> and
  220.73 + * <em>day-of-month</em> to an exact value, and <em>day-of-week</em> to zero. For
  220.74 + * example, to specify March 1, set the <em>month</em> to {@link Calendar#MARCH
  220.75 + * MARCH}, <em>day-of-month</em> to 1, and <em>day-of-week</em> to 0.</li>
  220.76 + *
  220.77 + * <li><b>Day of week on or after day of month</b><br>
  220.78 + * To specify a day of week on or after an exact day of month, set the
  220.79 + * <em>month</em> to an exact month value, <em>day-of-month</em> to the day on
  220.80 + * or after which the rule is applied, and <em>day-of-week</em> to a negative {@link
  220.81 + * Calendar#DAY_OF_WEEK DAY_OF_WEEK} field value. For example, to specify the
  220.82 + * second Sunday of April, set <em>month</em> to {@link Calendar#APRIL APRIL},
  220.83 + * <em>day-of-month</em> to 8, and <em>day-of-week</em> to <code>-</code>{@link
  220.84 + * Calendar#SUNDAY SUNDAY}.</li>
  220.85 + *
  220.86 + * <li><b>Day of week on or before day of month</b><br>
  220.87 + * To specify a day of the week on or before an exact day of the month, set
  220.88 + * <em>day-of-month</em> and <em>day-of-week</em> to a negative value. For
  220.89 + * example, to specify the last Wednesday on or before the 21st of March, set
  220.90 + * <em>month</em> to {@link Calendar#MARCH MARCH}, <em>day-of-month</em> is -21
  220.91 + * and <em>day-of-week</em> is <code>-</code>{@link Calendar#WEDNESDAY WEDNESDAY}. </li>
  220.92 + *
  220.93 + * <li><b>Last day-of-week of month</b><br>
  220.94 + * To specify, the last day-of-week of the month, set <em>day-of-week</em> to a
  220.95 + * {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} value and <em>day-of-month</em> to
  220.96 + * -1. For example, to specify the last Sunday of October, set <em>month</em>
  220.97 + * to {@link Calendar#OCTOBER OCTOBER}, <em>day-of-week</em> to {@link
  220.98 + * Calendar#SUNDAY SUNDAY} and <em>day-of-month</em> to -1.  </li>
  220.99 + *
 220.100 + * </ul>
 220.101 + * The time of the day at which daylight saving time starts or ends is
 220.102 + * specified by a millisecond value within the day. There are three kinds of
 220.103 + * <em>mode</em>s to specify the time: {@link #WALL_TIME}, {@link
 220.104 + * #STANDARD_TIME} and {@link #UTC_TIME}. For example, if daylight
 220.105 + * saving time ends
 220.106 + * at 2:00 am in the wall clock time, it can be specified by 7200000
 220.107 + * milliseconds in the {@link #WALL_TIME} mode. In this case, the wall clock time
 220.108 + * for an <em>end-rule</em> means the same thing as the daylight time.
 220.109 + * <p>
 220.110 + * The following are examples of parameters for constructing time zone objects.
 220.111 + * <pre><code>
 220.112 + *      // Base GMT offset: -8:00
 220.113 + *      // DST starts:      at 2:00am in standard time
 220.114 + *      //                  on the first Sunday in April
 220.115 + *      // DST ends:        at 2:00am in daylight time
 220.116 + *      //                  on the last Sunday in October
 220.117 + *      // Save:            1 hour
 220.118 + *      SimpleTimeZone(-28800000,
 220.119 + *                     "America/Los_Angeles",
 220.120 + *                     Calendar.APRIL, 1, -Calendar.SUNDAY,
 220.121 + *                     7200000,
 220.122 + *                     Calendar.OCTOBER, -1, Calendar.SUNDAY,
 220.123 + *                     7200000,
 220.124 + *                     3600000)
 220.125 + *
 220.126 + *      // Base GMT offset: +1:00
 220.127 + *      // DST starts:      at 1:00am in UTC time
 220.128 + *      //                  on the last Sunday in March
 220.129 + *      // DST ends:        at 1:00am in UTC time
 220.130 + *      //                  on the last Sunday in October
 220.131 + *      // Save:            1 hour
 220.132 + *      SimpleTimeZone(3600000,
 220.133 + *                     "Europe/Paris",
 220.134 + *                     Calendar.MARCH, -1, Calendar.SUNDAY,
 220.135 + *                     3600000, SimpleTimeZone.UTC_TIME,
 220.136 + *                     Calendar.OCTOBER, -1, Calendar.SUNDAY,
 220.137 + *                     3600000, SimpleTimeZone.UTC_TIME,
 220.138 + *                     3600000)
 220.139 + * </code></pre>
 220.140 + * These parameter rules are also applicable to the set rule methods, such as
 220.141 + * <code>setStartRule</code>.
 220.142 + *
 220.143 + * @since 1.1
 220.144 + * @see      Calendar
 220.145 + * @see      GregorianCalendar
 220.146 + * @see      TimeZone
 220.147 + * @author   David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
 220.148 + */
 220.149 +
 220.150 +public class SimpleTimeZone extends TimeZone {
 220.151 +    /**
 220.152 +     * Constructs a SimpleTimeZone with the given base time zone offset from GMT
 220.153 +     * and time zone ID with no daylight saving time schedule.
 220.154 +     *
 220.155 +     * @param rawOffset  The base time zone offset in milliseconds to GMT.
 220.156 +     * @param ID         The time zone name that is given to this instance.
 220.157 +     */
 220.158 +    public SimpleTimeZone(int rawOffset, String ID)
 220.159 +    {
 220.160 +        this.rawOffset = rawOffset;
 220.161 +        setID (ID);
 220.162 +        dstSavings = millisPerHour; // In case user sets rules later
 220.163 +    }
 220.164 +
 220.165 +    /**
 220.166 +     * Constructs a SimpleTimeZone with the given base time zone offset from
 220.167 +     * GMT, time zone ID, and rules for starting and ending the daylight
 220.168 +     * time.
 220.169 +     * Both <code>startTime</code> and <code>endTime</code> are specified to be
 220.170 +     * represented in the wall clock time. The amount of daylight saving is
 220.171 +     * assumed to be 3600000 milliseconds (i.e., one hour). This constructor is
 220.172 +     * equivalent to:
 220.173 +     * <pre><code>
 220.174 +     *     SimpleTimeZone(rawOffset,
 220.175 +     *                    ID,
 220.176 +     *                    startMonth,
 220.177 +     *                    startDay,
 220.178 +     *                    startDayOfWeek,
 220.179 +     *                    startTime,
 220.180 +     *                    SimpleTimeZone.{@link #WALL_TIME},
 220.181 +     *                    endMonth,
 220.182 +     *                    endDay,
 220.183 +     *                    endDayOfWeek,
 220.184 +     *                    endTime,
 220.185 +     *                    SimpleTimeZone.{@link #WALL_TIME},
 220.186 +     *                    3600000)
 220.187 +     * </code></pre>
 220.188 +     *
 220.189 +     * @param rawOffset       The given base time zone offset from GMT.
 220.190 +     * @param ID              The time zone ID which is given to this object.
 220.191 +     * @param startMonth      The daylight saving time starting month. Month is
 220.192 +     *                        a {@link Calendar#MONTH MONTH} field value (0-based. e.g., 0
 220.193 +     *                        for January).
 220.194 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.195 +     *                        See the class description for the special cases of this parameter.
 220.196 +     * @param startDayOfWeek  The daylight saving time starting day-of-week.
 220.197 +     *                        See the class description for the special cases of this parameter.
 220.198 +     * @param startTime       The daylight saving time starting time in local wall clock
 220.199 +     *                        time (in milliseconds within the day), which is local
 220.200 +     *                        standard time in this case.
 220.201 +     * @param endMonth        The daylight saving time ending month. Month is
 220.202 +     *                        a {@link Calendar#MONTH MONTH} field
 220.203 +     *                        value (0-based. e.g., 9 for October).
 220.204 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.205 +     *                        See the class description for the special cases of this parameter.
 220.206 +     * @param endDayOfWeek    The daylight saving time ending day-of-week.
 220.207 +     *                        See the class description for the special cases of this parameter.
 220.208 +     * @param endTime         The daylight saving ending time in local wall clock time,
 220.209 +     *                        (in milliseconds within the day) which is local daylight
 220.210 +     *                        time in this case.
 220.211 +     * @exception IllegalArgumentException if the month, day, dayOfWeek, or time
 220.212 +     * parameters are out of range for the start or end rule
 220.213 +     */
 220.214 +    public SimpleTimeZone(int rawOffset, String ID,
 220.215 +                          int startMonth, int startDay, int startDayOfWeek, int startTime,
 220.216 +                          int endMonth, int endDay, int endDayOfWeek, int endTime)
 220.217 +    {
 220.218 +        this(rawOffset, ID,
 220.219 +             startMonth, startDay, startDayOfWeek, startTime, WALL_TIME,
 220.220 +             endMonth, endDay, endDayOfWeek, endTime, WALL_TIME,
 220.221 +             millisPerHour);
 220.222 +    }
 220.223 +
 220.224 +    /**
 220.225 +     * Constructs a SimpleTimeZone with the given base time zone offset from
 220.226 +     * GMT, time zone ID, and rules for starting and ending the daylight
 220.227 +     * time.
 220.228 +     * Both <code>startTime</code> and <code>endTime</code> are assumed to be
 220.229 +     * represented in the wall clock time. This constructor is equivalent to:
 220.230 +     * <pre><code>
 220.231 +     *     SimpleTimeZone(rawOffset,
 220.232 +     *                    ID,
 220.233 +     *                    startMonth,
 220.234 +     *                    startDay,
 220.235 +     *                    startDayOfWeek,
 220.236 +     *                    startTime,
 220.237 +     *                    SimpleTimeZone.{@link #WALL_TIME},
 220.238 +     *                    endMonth,
 220.239 +     *                    endDay,
 220.240 +     *                    endDayOfWeek,
 220.241 +     *                    endTime,
 220.242 +     *                    SimpleTimeZone.{@link #WALL_TIME},
 220.243 +     *                    dstSavings)
 220.244 +     * </code></pre>
 220.245 +     *
 220.246 +     * @param rawOffset       The given base time zone offset from GMT.
 220.247 +     * @param ID              The time zone ID which is given to this object.
 220.248 +     * @param startMonth      The daylight saving time starting month. Month is
 220.249 +     *                        a {@link Calendar#MONTH MONTH} field
 220.250 +     *                        value (0-based. e.g., 0 for January).
 220.251 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.252 +     *                        See the class description for the special cases of this parameter.
 220.253 +     * @param startDayOfWeek  The daylight saving time starting day-of-week.
 220.254 +     *                        See the class description for the special cases of this parameter.
 220.255 +     * @param startTime       The daylight saving time starting time in local wall clock
 220.256 +     *                        time, which is local standard time in this case.
 220.257 +     * @param endMonth        The daylight saving time ending month. Month is
 220.258 +     *                        a {@link Calendar#MONTH MONTH} field
 220.259 +     *                        value (0-based. e.g., 9 for October).
 220.260 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.261 +     *                        See the class description for the special cases of this parameter.
 220.262 +     * @param endDayOfWeek    The daylight saving time ending day-of-week.
 220.263 +     *                        See the class description for the special cases of this parameter.
 220.264 +     * @param endTime         The daylight saving ending time in local wall clock time,
 220.265 +     *                        which is local daylight time in this case.
 220.266 +     * @param dstSavings      The amount of time in milliseconds saved during
 220.267 +     *                        daylight saving time.
 220.268 +     * @exception IllegalArgumentException if the month, day, dayOfWeek, or time
 220.269 +     * parameters are out of range for the start or end rule
 220.270 +     * @since 1.2
 220.271 +     */
 220.272 +    public SimpleTimeZone(int rawOffset, String ID,
 220.273 +                          int startMonth, int startDay, int startDayOfWeek, int startTime,
 220.274 +                          int endMonth, int endDay, int endDayOfWeek, int endTime,
 220.275 +                          int dstSavings)
 220.276 +    {
 220.277 +        this(rawOffset, ID,
 220.278 +             startMonth, startDay, startDayOfWeek, startTime, WALL_TIME,
 220.279 +             endMonth, endDay, endDayOfWeek, endTime, WALL_TIME,
 220.280 +             dstSavings);
 220.281 +    }
 220.282 +
 220.283 +    /**
 220.284 +     * Constructs a SimpleTimeZone with the given base time zone offset from
 220.285 +     * GMT, time zone ID, and rules for starting and ending the daylight
 220.286 +     * time.
 220.287 +     * This constructor takes the full set of the start and end rules
 220.288 +     * parameters, including modes of <code>startTime</code> and
 220.289 +     * <code>endTime</code>. The mode specifies either {@link #WALL_TIME wall
 220.290 +     * time} or {@link #STANDARD_TIME standard time} or {@link #UTC_TIME UTC
 220.291 +     * time}.
 220.292 +     *
 220.293 +     * @param rawOffset       The given base time zone offset from GMT.
 220.294 +     * @param ID              The time zone ID which is given to this object.
 220.295 +     * @param startMonth      The daylight saving time starting month. Month is
 220.296 +     *                        a {@link Calendar#MONTH MONTH} field
 220.297 +     *                        value (0-based. e.g., 0 for January).
 220.298 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.299 +     *                        See the class description for the special cases of this parameter.
 220.300 +     * @param startDayOfWeek  The daylight saving time starting day-of-week.
 220.301 +     *                        See the class description for the special cases of this parameter.
 220.302 +     * @param startTime       The daylight saving time starting time in the time mode
 220.303 +     *                        specified by <code>startTimeMode</code>.
 220.304 +     * @param startTimeMode   The mode of the start time specified by startTime.
 220.305 +     * @param endMonth        The daylight saving time ending month. Month is
 220.306 +     *                        a {@link Calendar#MONTH MONTH} field
 220.307 +     *                        value (0-based. e.g., 9 for October).
 220.308 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.309 +     *                        See the class description for the special cases of this parameter.
 220.310 +     * @param endDayOfWeek    The daylight saving time ending day-of-week.
 220.311 +     *                        See the class description for the special cases of this parameter.
 220.312 +     * @param endTime         The daylight saving ending time in time time mode
 220.313 +     *                        specified by <code>endTimeMode</code>.
 220.314 +     * @param endTimeMode     The mode of the end time specified by endTime
 220.315 +     * @param dstSavings      The amount of time in milliseconds saved during
 220.316 +     *                        daylight saving time.
 220.317 +     *
 220.318 +     * @exception IllegalArgumentException if the month, day, dayOfWeek, time more, or
 220.319 +     * time parameters are out of range for the start or end rule, or if a time mode
 220.320 +     * value is invalid.
 220.321 +     *
 220.322 +     * @see #WALL_TIME
 220.323 +     * @see #STANDARD_TIME
 220.324 +     * @see #UTC_TIME
 220.325 +     *
 220.326 +     * @since 1.4
 220.327 +     */
 220.328 +    public SimpleTimeZone(int rawOffset, String ID,
 220.329 +                          int startMonth, int startDay, int startDayOfWeek,
 220.330 +                          int startTime, int startTimeMode,
 220.331 +                          int endMonth, int endDay, int endDayOfWeek,
 220.332 +                          int endTime, int endTimeMode,
 220.333 +                          int dstSavings) {
 220.334 +
 220.335 +        setID(ID);
 220.336 +        this.rawOffset      = rawOffset;
 220.337 +        this.startMonth     = startMonth;
 220.338 +        this.startDay       = startDay;
 220.339 +        this.startDayOfWeek = startDayOfWeek;
 220.340 +        this.startTime      = startTime;
 220.341 +        this.startTimeMode  = startTimeMode;
 220.342 +        this.endMonth       = endMonth;
 220.343 +        this.endDay         = endDay;
 220.344 +        this.endDayOfWeek   = endDayOfWeek;
 220.345 +        this.endTime        = endTime;
 220.346 +        this.endTimeMode    = endTimeMode;
 220.347 +        this.dstSavings     = dstSavings;
 220.348 +
 220.349 +        // this.useDaylight is set by decodeRules
 220.350 +        decodeRules();
 220.351 +        if (dstSavings <= 0) {
 220.352 +            throw new IllegalArgumentException("Illegal daylight saving value: " + dstSavings);
 220.353 +        }
 220.354 +    }
 220.355 +
 220.356 +    /**
 220.357 +     * Sets the daylight saving time starting year.
 220.358 +     *
 220.359 +     * @param year  The daylight saving starting year.
 220.360 +     */
 220.361 +    public void setStartYear(int year)
 220.362 +    {
 220.363 +        startYear = year;
 220.364 +        invalidateCache();
 220.365 +    }
 220.366 +
 220.367 +    /**
 220.368 +     * Sets the daylight saving time start rule. For example, if daylight saving
 220.369 +     * time starts on the first Sunday in April at 2 am in local wall clock
 220.370 +     * time, you can set the start rule by calling:
 220.371 +     * <pre><code>setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000);</code></pre>
 220.372 +     *
 220.373 +     * @param startMonth      The daylight saving time starting month. Month is
 220.374 +     *                        a {@link Calendar#MONTH MONTH} field
 220.375 +     *                        value (0-based. e.g., 0 for January).
 220.376 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.377 +     *                        See the class description for the special cases of this parameter.
 220.378 +     * @param startDayOfWeek  The daylight saving time starting day-of-week.
 220.379 +     *                        See the class description for the special cases of this parameter.
 220.380 +     * @param startTime       The daylight saving time starting time in local wall clock
 220.381 +     *                        time, which is local standard time in this case.
 220.382 +     * @exception IllegalArgumentException if the <code>startMonth</code>, <code>startDay</code>,
 220.383 +     * <code>startDayOfWeek</code>, or <code>startTime</code> parameters are out of range
 220.384 +     */
 220.385 +    public void setStartRule(int startMonth, int startDay, int startDayOfWeek, int startTime)
 220.386 +    {
 220.387 +        this.startMonth = startMonth;
 220.388 +        this.startDay = startDay;
 220.389 +        this.startDayOfWeek = startDayOfWeek;
 220.390 +        this.startTime = startTime;
 220.391 +        startTimeMode = WALL_TIME;
 220.392 +        decodeStartRule();
 220.393 +        invalidateCache();
 220.394 +    }
 220.395 +
 220.396 +    /**
 220.397 +     * Sets the daylight saving time start rule to a fixed date within a month.
 220.398 +     * This method is equivalent to:
 220.399 +     * <pre><code>setStartRule(startMonth, startDay, 0, startTime)</code></pre>
 220.400 +     *
 220.401 +     * @param startMonth      The daylight saving time starting month. Month is
 220.402 +     *                        a {@link Calendar#MONTH MONTH} field
 220.403 +     *                        value (0-based. e.g., 0 for January).
 220.404 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.405 +     * @param startTime       The daylight saving time starting time in local wall clock
 220.406 +     *                        time, which is local standard time in this case.
 220.407 +     *                        See the class description for the special cases of this parameter.
 220.408 +     * @exception IllegalArgumentException if the <code>startMonth</code>,
 220.409 +     * <code>startDayOfMonth</code>, or <code>startTime</code> parameters are out of range
 220.410 +     * @since 1.2
 220.411 +     */
 220.412 +    public void setStartRule(int startMonth, int startDay, int startTime) {
 220.413 +        setStartRule(startMonth, startDay, 0, startTime);
 220.414 +    }
 220.415 +
 220.416 +    /**
 220.417 +     * Sets the daylight saving time start rule to a weekday before or after the given date within
 220.418 +     * a month, e.g., the first Monday on or after the 8th.
 220.419 +     *
 220.420 +     * @param startMonth      The daylight saving time starting month. Month is
 220.421 +     *                        a {@link Calendar#MONTH MONTH} field
 220.422 +     *                        value (0-based. e.g., 0 for January).
 220.423 +     * @param startDay        The day of the month on which the daylight saving time starts.
 220.424 +     * @param startDayOfWeek  The daylight saving time starting day-of-week.
 220.425 +     * @param startTime       The daylight saving time starting time in local wall clock
 220.426 +     *                        time, which is local standard time in this case.
 220.427 +     * @param after           If true, this rule selects the first <code>dayOfWeek</code> on or
 220.428 +     *                        <em>after</em> <code>dayOfMonth</code>.  If false, this rule
 220.429 +     *                        selects the last <code>dayOfWeek</code> on or <em>before</em>
 220.430 +     *                        <code>dayOfMonth</code>.
 220.431 +     * @exception IllegalArgumentException if the <code>startMonth</code>, <code>startDay</code>,
 220.432 +     * <code>startDayOfWeek</code>, or <code>startTime</code> parameters are out of range
 220.433 +     * @since 1.2
 220.434 +     */
 220.435 +    public void setStartRule(int startMonth, int startDay, int startDayOfWeek,
 220.436 +                             int startTime, boolean after)
 220.437 +    {
 220.438 +        // TODO: this method doesn't check the initial values of dayOfMonth or dayOfWeek.
 220.439 +        if (after) {
 220.440 +            setStartRule(startMonth, startDay, -startDayOfWeek, startTime);
 220.441 +        } else {
 220.442 +            setStartRule(startMonth, -startDay, -startDayOfWeek, startTime);
 220.443 +        }
 220.444 +    }
 220.445 +
 220.446 +    /**
 220.447 +     * Sets the daylight saving time end rule. For example, if daylight saving time
 220.448 +     * ends on the last Sunday in October at 2 am in wall clock time,
 220.449 +     * you can set the end rule by calling:
 220.450 +     * <code>setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);</code>
 220.451 +     *
 220.452 +     * @param endMonth        The daylight saving time ending month. Month is
 220.453 +     *                        a {@link Calendar#MONTH MONTH} field
 220.454 +     *                        value (0-based. e.g., 9 for October).
 220.455 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.456 +     *                        See the class description for the special cases of this parameter.
 220.457 +     * @param endDayOfWeek    The daylight saving time ending day-of-week.
 220.458 +     *                        See the class description for the special cases of this parameter.
 220.459 +     * @param endTime         The daylight saving ending time in local wall clock time,
 220.460 +     *                        (in milliseconds within the day) which is local daylight
 220.461 +     *                        time in this case.
 220.462 +     * @exception IllegalArgumentException if the <code>endMonth</code>, <code>endDay</code>,
 220.463 +     * <code>endDayOfWeek</code>, or <code>endTime</code> parameters are out of range
 220.464 +     */
 220.465 +    public void setEndRule(int endMonth, int endDay, int endDayOfWeek,
 220.466 +                           int endTime)
 220.467 +    {
 220.468 +        this.endMonth = endMonth;
 220.469 +        this.endDay = endDay;
 220.470 +        this.endDayOfWeek = endDayOfWeek;
 220.471 +        this.endTime = endTime;
 220.472 +        this.endTimeMode = WALL_TIME;
 220.473 +        decodeEndRule();
 220.474 +        invalidateCache();
 220.475 +    }
 220.476 +
 220.477 +    /**
 220.478 +     * Sets the daylight saving time end rule to a fixed date within a month.
 220.479 +     * This method is equivalent to:
 220.480 +     * <pre><code>setEndRule(endMonth, endDay, 0, endTime)</code></pre>
 220.481 +     *
 220.482 +     * @param endMonth        The daylight saving time ending month. Month is
 220.483 +     *                        a {@link Calendar#MONTH MONTH} field
 220.484 +     *                        value (0-based. e.g., 9 for October).
 220.485 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.486 +     * @param endTime         The daylight saving ending time in local wall clock time,
 220.487 +     *                        (in milliseconds within the day) which is local daylight
 220.488 +     *                        time in this case.
 220.489 +     * @exception IllegalArgumentException the <code>endMonth</code>, <code>endDay</code>,
 220.490 +     * or <code>endTime</code> parameters are out of range
 220.491 +     * @since 1.2
 220.492 +     */
 220.493 +    public void setEndRule(int endMonth, int endDay, int endTime)
 220.494 +    {
 220.495 +        setEndRule(endMonth, endDay, 0, endTime);
 220.496 +    }
 220.497 +
 220.498 +    /**
 220.499 +     * Sets the daylight saving time end rule to a weekday before or after the given date within
 220.500 +     * a month, e.g., the first Monday on or after the 8th.
 220.501 +     *
 220.502 +     * @param endMonth        The daylight saving time ending month. Month is
 220.503 +     *                        a {@link Calendar#MONTH MONTH} field
 220.504 +     *                        value (0-based. e.g., 9 for October).
 220.505 +     * @param endDay          The day of the month on which the daylight saving time ends.
 220.506 +     * @param endDayOfWeek    The daylight saving time ending day-of-week.
 220.507 +     * @param endTime         The daylight saving ending time in local wall clock time,
 220.508 +     *                        (in milliseconds within the day) which is local daylight
 220.509 +     *                        time in this case.
 220.510 +     * @param after           If true, this rule selects the first <code>endDayOfWeek</code> on
 220.511 +     *                        or <em>after</em> <code>endDay</code>.  If false, this rule
 220.512 +     *                        selects the last <code>endDayOfWeek</code> on or before
 220.513 +     *                        <code>endDay</code> of the month.
 220.514 +     * @exception IllegalArgumentException the <code>endMonth</code>, <code>endDay</code>,
 220.515 +     * <code>endDayOfWeek</code>, or <code>endTime</code> parameters are out of range
 220.516 +     * @since 1.2
 220.517 +     */
 220.518 +    public void setEndRule(int endMonth, int endDay, int endDayOfWeek, int endTime, boolean after)
 220.519 +    {
 220.520 +        if (after) {
 220.521 +            setEndRule(endMonth, endDay, -endDayOfWeek, endTime);
 220.522 +        } else {
 220.523 +            setEndRule(endMonth, -endDay, -endDayOfWeek, endTime);
 220.524 +        }
 220.525 +    }
 220.526 +
 220.527 +    /**
 220.528 +     * Returns the offset of this time zone from UTC at the given
 220.529 +     * time. If daylight saving time is in effect at the given time,
 220.530 +     * the offset value is adjusted with the amount of daylight
 220.531 +     * saving.
 220.532 +     *
 220.533 +     * @param date the time at which the time zone offset is found
 220.534 +     * @return the amount of time in milliseconds to add to UTC to get
 220.535 +     * local time.
 220.536 +     * @since 1.4
 220.537 +     */
 220.538 +    public int getOffset(long date) {
 220.539 +        return getOffsets(date, null);
 220.540 +    }
 220.541 +
 220.542 +    /**
 220.543 +     * @see TimeZone#getOffsets
 220.544 +     */
 220.545 +    int getOffsets(long date, int[] offsets) {
 220.546 +        int offset = rawOffset;
 220.547 +
 220.548 +      computeOffset:
 220.549 +        if (useDaylight) {
 220.550 +            synchronized (this) {
 220.551 +                if (cacheStart != 0) {
 220.552 +                    if (date >= cacheStart && date < cacheEnd) {
 220.553 +                        offset += dstSavings;
 220.554 +                        break computeOffset;
 220.555 +                    }
 220.556 +                }
 220.557 +            }
 220.558 +            BaseCalendar cal = gcal;
 220.559 +//            date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ?
 220.560 +//                gcal : (BaseCalendar) CalendarSystem.forName("julian");
 220.561 +            BaseCalendar.Datum cdate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
 220.562 +            // Get the year in local time
 220.563 +            cal.getCalendarDate(date + rawOffset, cdate);
 220.564 +            int year = cdate.getNormalizedYear();
 220.565 +            if (year >= startYear) {
 220.566 +                // Clear time elements for the transition calculations
 220.567 +                cdate.setTimeOfDay(0, 0, 0, 0);
 220.568 +                offset = getOffset(cal, cdate, year, date);
 220.569 +            }
 220.570 +        }
 220.571 +
 220.572 +        if (offsets != null) {
 220.573 +            offsets[0] = rawOffset;
 220.574 +            offsets[1] = offset - rawOffset;
 220.575 +        }
 220.576 +        return offset;
 220.577 +    }
 220.578 +
 220.579 +   /**
 220.580 +     * Returns the difference in milliseconds between local time and
 220.581 +     * UTC, taking into account both the raw offset and the effect of
 220.582 +     * daylight saving, for the specified date and time.  This method
 220.583 +     * assumes that the start and end month are distinct.  It also
 220.584 +     * uses a default {@link GregorianCalendar} object as its
 220.585 +     * underlying calendar, such as for determining leap years.  Do
 220.586 +     * not use the result of this method with a calendar other than a
 220.587 +     * default <code>GregorianCalendar</code>.
 220.588 +     *
 220.589 +     * <p><em>Note:  In general, clients should use
 220.590 +     * <code>Calendar.get(ZONE_OFFSET) + Calendar.get(DST_OFFSET)</code>
 220.591 +     * instead of calling this method.</em>
 220.592 +     *
 220.593 +     * @param era       The era of the given date.
 220.594 +     * @param year      The year in the given date.
 220.595 +     * @param month     The month in the given date. Month is 0-based. e.g.,
 220.596 +     *                  0 for January.
 220.597 +     * @param day       The day-in-month of the given date.
 220.598 +     * @param dayOfWeek The day-of-week of the given date.
 220.599 +     * @param millis    The milliseconds in day in <em>standard</em> local time.
 220.600 +     * @return          The milliseconds to add to UTC to get local time.
 220.601 +     * @exception       IllegalArgumentException the <code>era</code>,
 220.602 +     *                  <code>month</code>, <code>day</code>, <code>dayOfWeek</code>,
 220.603 +     *                  or <code>millis</code> parameters are out of range
 220.604 +     */
 220.605 +    public int getOffset(int era, int year, int month, int day, int dayOfWeek,
 220.606 +                         int millis)
 220.607 +    {
 220.608 +        if (era != GregorianCalendar.AD && era != GregorianCalendar.BC) {
 220.609 +            throw new IllegalArgumentException("Illegal era " + era);
 220.610 +        }
 220.611 +
 220.612 +        int y = year;
 220.613 +        if (era == GregorianCalendar.BC) {
 220.614 +            // adjust y with the GregorianCalendar-style year numbering.
 220.615 +            y = 1 - y;
 220.616 +        }
 220.617 +
 220.618 +        // If the year isn't representable with the 64-bit long
 220.619 +        // integer in milliseconds, convert the year to an
 220.620 +        // equivalent year. This is required to pass some JCK test cases
 220.621 +        // which are actually useless though because the specified years
 220.622 +        // can't be supported by the Java time system.
 220.623 +        if (y >= 292278994) {
 220.624 +            y = 2800 + y % 2800;
 220.625 +        } else if (y <= -292269054) {
 220.626 +            // y %= 28 also produces an equivalent year, but positive
 220.627 +            // year numbers would be convenient to use the UNIX cal
 220.628 +            // command.
 220.629 +            y = (int) (long) y % 28;
 220.630 +        }
 220.631 +
 220.632 +        // convert year to its 1-based month value
 220.633 +        int m = month + 1;
 220.634 +
 220.635 +        // First, calculate time as a Gregorian date.
 220.636 +        BaseCalendar cal = gcal;
 220.637 +        BaseCalendar.Datum cdate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
 220.638 +        cdate.setDate(y, m, day);
 220.639 +        long time = cal.getTime(cdate); // normalize cdate
 220.640 +        time += millis - rawOffset; // UTC time
 220.641 +
 220.642 +        // If the time value represents a time before the default
 220.643 +        // Gregorian cutover, recalculate time using the Julian
 220.644 +        // calendar system. For the Julian calendar system, the
 220.645 +        // normalized year numbering is ..., -2 (BCE 2), -1 (BCE 1),
 220.646 +        // 1, 2 ... which is different from the GregorianCalendar
 220.647 +        // style year numbering (..., -1, 0 (BCE 1), 1, 2, ...).
 220.648 +//        if (time < GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER) {
 220.649 +//            cal = (BaseCalendar) CalendarSystem.forName("julian");
 220.650 +//            cdate = (BaseCalendar.Datum) cal.newCalendarDate(TimeZone.NO_TIMEZONE);
 220.651 +//            cdate.setNormalizedDate(y, m, day);
 220.652 +//            time = cal.getTime(cdate) + millis - rawOffset;
 220.653 +//        }
 220.654 +
 220.655 +        if ((cdate.getNormalizedYear() != y)
 220.656 +            || (cdate.getMonth() != m)
 220.657 +            || (cdate.getDayOfMonth() != day)
 220.658 +            // The validation should be cdate.getDayOfWeek() ==
 220.659 +            // dayOfWeek. However, we don't check dayOfWeek for
 220.660 +            // compatibility.
 220.661 +            || (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY)
 220.662 +            || (millis < 0 || millis >= (24*60*60*1000))) {
 220.663 +            throw new IllegalArgumentException();
 220.664 +        }
 220.665 +
 220.666 +        if (!useDaylight || year < startYear || era != GregorianCalendar.CE) {
 220.667 +            return rawOffset;
 220.668 +        }
 220.669 +
 220.670 +        return getOffset(cal, cdate, y, time);
 220.671 +    }
 220.672 +
 220.673 +    private int getOffset(BaseCalendar cal, BaseCalendar.Datum cdate, int year, long time) {
 220.674 +        synchronized (this) {
 220.675 +            if (cacheStart != 0) {
 220.676 +                if (time >= cacheStart && time < cacheEnd) {
 220.677 +                    return rawOffset + dstSavings;
 220.678 +                }
 220.679 +                if (year == cacheYear) {
 220.680 +                    return rawOffset;
 220.681 +                }
 220.682 +            }
 220.683 +        }
 220.684 +
 220.685 +        long start = getStart(cal, cdate, year);
 220.686 +        long end = getEnd(cal, cdate, year);
 220.687 +        int offset = rawOffset;
 220.688 +        if (start <= end) {
 220.689 +            if (time >= start && time < end) {
 220.690 +                offset += dstSavings;
 220.691 +            }
 220.692 +            synchronized (this) {
 220.693 +                cacheYear = year;
 220.694 +                cacheStart = start;
 220.695 +                cacheEnd = end;
 220.696 +            }
 220.697 +        } else {
 220.698 +            if (time < end) {
 220.699 +                // TODO: support Gregorian cutover. The previous year
 220.700 +                // may be in the other calendar system.
 220.701 +                start = getStart(cal, cdate, year - 1);
 220.702 +                if (time >= start) {
 220.703 +                    offset += dstSavings;
 220.704 +                }
 220.705 +            } else if (time >= start) {
 220.706 +                // TODO: support Gregorian cutover. The next year
 220.707 +                // may be in the other calendar system.
 220.708 +                end = getEnd(cal, cdate, year + 1);
 220.709 +                if (time < end) {
 220.710 +                    offset += dstSavings;
 220.711 +                }
 220.712 +            }
 220.713 +            if (start <= end) {
 220.714 +                synchronized (this) {
 220.715 +                    // The start and end transitions are in multiple years.
 220.716 +                    cacheYear = (long) startYear - 1;
 220.717 +                    cacheStart = start;
 220.718 +                    cacheEnd = end;
 220.719 +                }
 220.720 +            }
 220.721 +        }
 220.722 +        return offset;
 220.723 +    }
 220.724 +
 220.725 +    private long getStart(BaseCalendar cal, BaseCalendar.Datum cdate, int year) {
 220.726 +        int time = startTime;
 220.727 +        if (startTimeMode != UTC_TIME) {
 220.728 +            time -= rawOffset;
 220.729 +        }
 220.730 +        return getTransition(cal, cdate, startMode, year, startMonth, startDay,
 220.731 +                             startDayOfWeek, time);
 220.732 +    }
 220.733 +
 220.734 +    private long getEnd(BaseCalendar cal, BaseCalendar.Datum cdate, int year) {
 220.735 +        int time = endTime;
 220.736 +        if (endTimeMode != UTC_TIME) {
 220.737 +            time -= rawOffset;
 220.738 +        }
 220.739 +        if (endTimeMode == WALL_TIME) {
 220.740 +            time -= dstSavings;
 220.741 +        }
 220.742 +        return getTransition(cal, cdate, endMode, year, endMonth, endDay,
 220.743 +                                        endDayOfWeek, time);
 220.744 +    }
 220.745 +
 220.746 +    private long getTransition(BaseCalendar cal, BaseCalendar.Datum cdate,
 220.747 +                               int mode, int year, int month, int dayOfMonth,
 220.748 +                               int dayOfWeek, int timeOfDay) {
 220.749 +        cdate.setNormalizedYear(year);
 220.750 +        cdate.setMonth(month + 1);
 220.751 +        switch (mode) {
 220.752 +        case DOM_MODE:
 220.753 +            cdate.setDayOfMonth(dayOfMonth);
 220.754 +            break;
 220.755 +
 220.756 +        case DOW_IN_MONTH_MODE:
 220.757 +            cdate.setDayOfMonth(1);
 220.758 +            if (dayOfMonth < 0) {
 220.759 +                cdate.setDayOfMonth(cal.getMonthLength(cdate));
 220.760 +            }
 220.761 +            cdate = (BaseCalendar.Datum) cal.getNthDayOfWeek(dayOfMonth, dayOfWeek, cdate);
 220.762 +            break;
 220.763 +
 220.764 +        case DOW_GE_DOM_MODE:
 220.765 +            cdate.setDayOfMonth(dayOfMonth);
 220.766 +            cdate = (BaseCalendar.Datum) cal.getNthDayOfWeek(1, dayOfWeek, cdate);
 220.767 +            break;
 220.768 +
 220.769 +        case DOW_LE_DOM_MODE:
 220.770 +            cdate.setDayOfMonth(dayOfMonth);
 220.771 +            cdate = (BaseCalendar.Datum) cal.getNthDayOfWeek(-1, dayOfWeek, cdate);
 220.772 +            break;
 220.773 +        }
 220.774 +        return cal.getTime(cdate) + timeOfDay;
 220.775 +    }
 220.776 +
 220.777 +    /**
 220.778 +     * Gets the GMT offset for this time zone.
 220.779 +     * @return the GMT offset value in milliseconds
 220.780 +     * @see #setRawOffset
 220.781 +     */
 220.782 +    public int getRawOffset()
 220.783 +    {
 220.784 +        // The given date will be taken into account while
 220.785 +        // we have the historical time zone data in place.
 220.786 +        return rawOffset;
 220.787 +    }
 220.788 +
 220.789 +    /**
 220.790 +     * Sets the base time zone offset to GMT.
 220.791 +     * This is the offset to add to UTC to get local time.
 220.792 +     * @see #getRawOffset
 220.793 +     */
 220.794 +    public void setRawOffset(int offsetMillis)
 220.795 +    {
 220.796 +        this.rawOffset = offsetMillis;
 220.797 +    }
 220.798 +
 220.799 +    /**
 220.800 +     * Sets the amount of time in milliseconds that the clock is advanced
 220.801 +     * during daylight saving time.
 220.802 +     * @param millisSavedDuringDST the number of milliseconds the time is
 220.803 +     * advanced with respect to standard time when the daylight saving time rules
 220.804 +     * are in effect. A positive number, typically one hour (3600000).
 220.805 +     * @see #getDSTSavings
 220.806 +     * @since 1.2
 220.807 +     */
 220.808 +    public void setDSTSavings(int millisSavedDuringDST) {
 220.809 +        if (millisSavedDuringDST <= 0) {
 220.810 +            throw new IllegalArgumentException("Illegal daylight saving value: "
 220.811 +                                               + millisSavedDuringDST);
 220.812 +        }
 220.813 +        dstSavings = millisSavedDuringDST;
 220.814 +    }
 220.815 +
 220.816 +    /**
 220.817 +     * Returns the amount of time in milliseconds that the clock is
 220.818 +     * advanced during daylight saving time.
 220.819 +     *
 220.820 +     * @return the number of milliseconds the time is advanced with
 220.821 +     * respect to standard time when the daylight saving rules are in
 220.822 +     * effect, or 0 (zero) if this time zone doesn't observe daylight
 220.823 +     * saving time.
 220.824 +     *
 220.825 +     * @see #setDSTSavings
 220.826 +     * @since 1.2
 220.827 +     */
 220.828 +    public int getDSTSavings() {
 220.829 +        return useDaylight ? dstSavings : 0;
 220.830 +    }
 220.831 +
 220.832 +    /**
 220.833 +     * Queries if this time zone uses daylight saving time.
 220.834 +     * @return true if this time zone uses daylight saving time;
 220.835 +     * false otherwise.
 220.836 +     */
 220.837 +    public boolean useDaylightTime()
 220.838 +    {
 220.839 +        return useDaylight;
 220.840 +    }
 220.841 +
 220.842 +    /**
 220.843 +     * Returns {@code true} if this {@code SimpleTimeZone} observes
 220.844 +     * Daylight Saving Time. This method is equivalent to {@link
 220.845 +     * #useDaylightTime()}.
 220.846 +     *
 220.847 +     * @return {@code true} if this {@code SimpleTimeZone} observes
 220.848 +     * Daylight Saving Time; {@code false} otherwise.
 220.849 +     * @since 1.7
 220.850 +     */
 220.851 +    @Override
 220.852 +    public boolean observesDaylightTime() {
 220.853 +        return useDaylightTime();
 220.854 +    }
 220.855 +
 220.856 +    /**
 220.857 +     * Queries if the given date is in daylight saving time.
 220.858 +     * @return true if daylight saving time is in effective at the
 220.859 +     * given date; false otherwise.
 220.860 +     */
 220.861 +    public boolean inDaylightTime(Date date)
 220.862 +    {
 220.863 +        return (getOffset(date.getTime()) != rawOffset);
 220.864 +    }
 220.865 +
 220.866 +    /**
 220.867 +     * Returns a clone of this <code>SimpleTimeZone</code> instance.
 220.868 +     * @return a clone of this instance.
 220.869 +     */
 220.870 +    public Object clone()
 220.871 +    {
 220.872 +        return super.clone();
 220.873 +    }
 220.874 +
 220.875 +    /**
 220.876 +     * Generates the hash code for the SimpleDateFormat object.
 220.877 +     * @return the hash code for this object
 220.878 +     */
 220.879 +    public synchronized int hashCode()
 220.880 +    {
 220.881 +        return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
 220.882 +            endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
 220.883 +    }
 220.884 +
 220.885 +    /**
 220.886 +     * Compares the equality of two <code>SimpleTimeZone</code> objects.
 220.887 +     *
 220.888 +     * @param obj  The <code>SimpleTimeZone</code> object to be compared with.
 220.889 +     * @return     True if the given <code>obj</code> is the same as this
 220.890 +     *             <code>SimpleTimeZone</code> object; false otherwise.
 220.891 +     */
 220.892 +    public boolean equals(Object obj)
 220.893 +    {
 220.894 +        if (this == obj) {
 220.895 +            return true;
 220.896 +        }
 220.897 +        if (!(obj instanceof SimpleTimeZone)) {
 220.898 +            return false;
 220.899 +        }
 220.900 +
 220.901 +        SimpleTimeZone that = (SimpleTimeZone) obj;
 220.902 +
 220.903 +        return getID().equals(that.getID()) &&
 220.904 +            hasSameRules(that);
 220.905 +    }
 220.906 +
 220.907 +    /**
 220.908 +     * Returns <code>true</code> if this zone has the same rules and offset as another zone.
 220.909 +     * @param other the TimeZone object to be compared with
 220.910 +     * @return <code>true</code> if the given zone is a SimpleTimeZone and has the
 220.911 +     * same rules and offset as this one
 220.912 +     * @since 1.2
 220.913 +     */
 220.914 +    public boolean hasSameRules(TimeZone other) {
 220.915 +        if (this == other) {
 220.916 +            return true;
 220.917 +        }
 220.918 +        if (!(other instanceof SimpleTimeZone)) {
 220.919 +            return false;
 220.920 +        }
 220.921 +        SimpleTimeZone that = (SimpleTimeZone) other;
 220.922 +        return rawOffset == that.rawOffset &&
 220.923 +            useDaylight == that.useDaylight &&
 220.924 +            (!useDaylight
 220.925 +             // Only check rules if using DST
 220.926 +             || (dstSavings == that.dstSavings &&
 220.927 +                 startMode == that.startMode &&
 220.928 +                 startMonth == that.startMonth &&
 220.929 +                 startDay == that.startDay &&
 220.930 +                 startDayOfWeek == that.startDayOfWeek &&
 220.931 +                 startTime == that.startTime &&
 220.932 +                 startTimeMode == that.startTimeMode &&
 220.933 +                 endMode == that.endMode &&
 220.934 +                 endMonth == that.endMonth &&
 220.935 +                 endDay == that.endDay &&
 220.936 +                 endDayOfWeek == that.endDayOfWeek &&
 220.937 +                 endTime == that.endTime &&
 220.938 +                 endTimeMode == that.endTimeMode &&
 220.939 +                 startYear == that.startYear));
 220.940 +    }
 220.941 +
 220.942 +    /**
 220.943 +     * Returns a string representation of this time zone.
 220.944 +     * @return a string representation of this time zone.
 220.945 +     */
 220.946 +    public String toString() {
 220.947 +        return getClass().getName() +
 220.948 +            "[id=" + getID() +
 220.949 +            ",offset=" + rawOffset +
 220.950 +            ",dstSavings=" + dstSavings +
 220.951 +            ",useDaylight=" + useDaylight +
 220.952 +            ",startYear=" + startYear +
 220.953 +            ",startMode=" + startMode +
 220.954 +            ",startMonth=" + startMonth +
 220.955 +            ",startDay=" + startDay +
 220.956 +            ",startDayOfWeek=" + startDayOfWeek +
 220.957 +            ",startTime=" + startTime +
 220.958 +            ",startTimeMode=" + startTimeMode +
 220.959 +            ",endMode=" + endMode +
 220.960 +            ",endMonth=" + endMonth +
 220.961 +            ",endDay=" + endDay +
 220.962 +            ",endDayOfWeek=" + endDayOfWeek +
 220.963 +            ",endTime=" + endTime +
 220.964 +            ",endTimeMode=" + endTimeMode + ']';
 220.965 +    }
 220.966 +
 220.967 +    // =======================privates===============================
 220.968 +
 220.969 +    /**
 220.970 +     * The month in which daylight saving time starts.  This value must be
 220.971 +     * between <code>Calendar.JANUARY</code> and
 220.972 +     * <code>Calendar.DECEMBER</code> inclusive.  This value must not equal
 220.973 +     * <code>endMonth</code>.
 220.974 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
 220.975 +     * @serial
 220.976 +     */
 220.977 +    private int startMonth;
 220.978 +
 220.979 +    /**
 220.980 +     * This field has two possible interpretations:
 220.981 +     * <dl>
 220.982 +     * <dt><code>startMode == DOW_IN_MONTH</code></dt>
 220.983 +     * <dd>
 220.984 +     * <code>startDay</code> indicates the day of the month of
 220.985 +     * <code>startMonth</code> on which daylight
 220.986 +     * saving time starts, from 1 to 28, 30, or 31, depending on the
 220.987 +     * <code>startMonth</code>.
 220.988 +     * </dd>
 220.989 +     * <dt><code>startMode != DOW_IN_MONTH</code></dt>
 220.990 +     * <dd>
 220.991 +     * <code>startDay</code> indicates which <code>startDayOfWeek</code> in the
 220.992 +     * month <code>startMonth</code> daylight
 220.993 +     * saving time starts on.  For example, a value of +1 and a
 220.994 +     * <code>startDayOfWeek</code> of <code>Calendar.SUNDAY</code> indicates the
 220.995 +     * first Sunday of <code>startMonth</code>.  Likewise, +2 would indicate the
 220.996 +     * second Sunday, and -1 the last Sunday.  A value of 0 is illegal.
 220.997 +     * </dd>
 220.998 +     * </dl>
 220.999 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1000 +     * @serial
220.1001 +     */
220.1002 +    private int startDay;
220.1003 +
220.1004 +    /**
220.1005 +     * The day of the week on which daylight saving time starts.  This value
220.1006 +     * must be between <code>Calendar.SUNDAY</code> and
220.1007 +     * <code>Calendar.SATURDAY</code> inclusive.
220.1008 +     * <p>If <code>useDaylight</code> is false or
220.1009 +     * <code>startMode == DAY_OF_MONTH</code>, this value is ignored.
220.1010 +     * @serial
220.1011 +     */
220.1012 +    private int startDayOfWeek;
220.1013 +
220.1014 +    /**
220.1015 +     * The time in milliseconds after midnight at which daylight saving
220.1016 +     * time starts.  This value is expressed as wall time, standard time,
220.1017 +     * or UTC time, depending on the setting of <code>startTimeMode</code>.
220.1018 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1019 +     * @serial
220.1020 +     */
220.1021 +    private int startTime;
220.1022 +
220.1023 +    /**
220.1024 +     * The format of startTime, either WALL_TIME, STANDARD_TIME, or UTC_TIME.
220.1025 +     * @serial
220.1026 +     * @since 1.3
220.1027 +     */
220.1028 +    private int startTimeMode;
220.1029 +
220.1030 +    /**
220.1031 +     * The month in which daylight saving time ends.  This value must be
220.1032 +     * between <code>Calendar.JANUARY</code> and
220.1033 +     * <code>Calendar.UNDECIMBER</code>.  This value must not equal
220.1034 +     * <code>startMonth</code>.
220.1035 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1036 +     * @serial
220.1037 +     */
220.1038 +    private int endMonth;
220.1039 +
220.1040 +    /**
220.1041 +     * This field has two possible interpretations:
220.1042 +     * <dl>
220.1043 +     * <dt><code>endMode == DOW_IN_MONTH</code></dt>
220.1044 +     * <dd>
220.1045 +     * <code>endDay</code> indicates the day of the month of
220.1046 +     * <code>endMonth</code> on which daylight
220.1047 +     * saving time ends, from 1 to 28, 30, or 31, depending on the
220.1048 +     * <code>endMonth</code>.
220.1049 +     * </dd>
220.1050 +     * <dt><code>endMode != DOW_IN_MONTH</code></dt>
220.1051 +     * <dd>
220.1052 +     * <code>endDay</code> indicates which <code>endDayOfWeek</code> in th
220.1053 +     * month <code>endMonth</code> daylight
220.1054 +     * saving time ends on.  For example, a value of +1 and a
220.1055 +     * <code>endDayOfWeek</code> of <code>Calendar.SUNDAY</code> indicates the
220.1056 +     * first Sunday of <code>endMonth</code>.  Likewise, +2 would indicate the
220.1057 +     * second Sunday, and -1 the last Sunday.  A value of 0 is illegal.
220.1058 +     * </dd>
220.1059 +     * </dl>
220.1060 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1061 +     * @serial
220.1062 +     */
220.1063 +    private int endDay;
220.1064 +
220.1065 +    /**
220.1066 +     * The day of the week on which daylight saving time ends.  This value
220.1067 +     * must be between <code>Calendar.SUNDAY</code> and
220.1068 +     * <code>Calendar.SATURDAY</code> inclusive.
220.1069 +     * <p>If <code>useDaylight</code> is false or
220.1070 +     * <code>endMode == DAY_OF_MONTH</code>, this value is ignored.
220.1071 +     * @serial
220.1072 +     */
220.1073 +    private int endDayOfWeek;
220.1074 +
220.1075 +    /**
220.1076 +     * The time in milliseconds after midnight at which daylight saving
220.1077 +     * time ends.  This value is expressed as wall time, standard time,
220.1078 +     * or UTC time, depending on the setting of <code>endTimeMode</code>.
220.1079 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1080 +     * @serial
220.1081 +     */
220.1082 +    private int endTime;
220.1083 +
220.1084 +    /**
220.1085 +     * The format of endTime, either <code>WALL_TIME</code>,
220.1086 +     * <code>STANDARD_TIME</code>, or <code>UTC_TIME</code>.
220.1087 +     * @serial
220.1088 +     * @since 1.3
220.1089 +     */
220.1090 +    private int endTimeMode;
220.1091 +
220.1092 +    /**
220.1093 +     * The year in which daylight saving time is first observed.  This is an {@link GregorianCalendar#AD AD}
220.1094 +     * value.  If this value is less than 1 then daylight saving time is observed
220.1095 +     * for all <code>AD</code> years.
220.1096 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1097 +     * @serial
220.1098 +     */
220.1099 +    private int startYear;
220.1100 +
220.1101 +    /**
220.1102 +     * The offset in milliseconds between this zone and GMT.  Negative offsets
220.1103 +     * are to the west of Greenwich.  To obtain local <em>standard</em> time,
220.1104 +     * add the offset to GMT time.  To obtain local wall time it may also be
220.1105 +     * necessary to add <code>dstSavings</code>.
220.1106 +     * @serial
220.1107 +     */
220.1108 +    private int rawOffset;
220.1109 +
220.1110 +    /**
220.1111 +     * A boolean value which is true if and only if this zone uses daylight
220.1112 +     * saving time.  If this value is false, several other fields are ignored.
220.1113 +     * @serial
220.1114 +     */
220.1115 +    private boolean useDaylight=false; // indicate if this time zone uses DST
220.1116 +
220.1117 +    private static final int millisPerHour = 60*60*1000;
220.1118 +    private static final int millisPerDay  = 24*millisPerHour;
220.1119 +
220.1120 +    /**
220.1121 +     * This field was serialized in JDK 1.1, so we have to keep it that way
220.1122 +     * to maintain serialization compatibility. However, there's no need to
220.1123 +     * recreate the array each time we create a new time zone.
220.1124 +     * @serial An array of bytes containing the values {31, 28, 31, 30, 31, 30,
220.1125 +     * 31, 31, 30, 31, 30, 31}.  This is ignored as of the Java 2 platform v1.2, however, it must
220.1126 +     * be streamed out for compatibility with JDK 1.1.
220.1127 +     */
220.1128 +    private final byte monthLength[] = staticMonthLength;
220.1129 +    private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
220.1130 +    private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
220.1131 +
220.1132 +    /**
220.1133 +     * Variables specifying the mode of the start rule.  Takes the following
220.1134 +     * values:
220.1135 +     * <dl>
220.1136 +     * <dt><code>DOM_MODE</code></dt>
220.1137 +     * <dd>
220.1138 +     * Exact day of week; e.g., March 1.
220.1139 +     * </dd>
220.1140 +     * <dt><code>DOW_IN_MONTH_MODE</code></dt>
220.1141 +     * <dd>
220.1142 +     * Day of week in month; e.g., last Sunday in March.
220.1143 +     * </dd>
220.1144 +     * <dt><code>DOW_GE_DOM_MODE</code></dt>
220.1145 +     * <dd>
220.1146 +     * Day of week after day of month; e.g., Sunday on or after March 15.
220.1147 +     * </dd>
220.1148 +     * <dt><code>DOW_LE_DOM_MODE</code></dt>
220.1149 +     * <dd>
220.1150 +     * Day of week before day of month; e.g., Sunday on or before March 15.
220.1151 +     * </dd>
220.1152 +     * </dl>
220.1153 +     * The setting of this field affects the interpretation of the
220.1154 +     * <code>startDay</code> field.
220.1155 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1156 +     * @serial
220.1157 +     * @since 1.1.4
220.1158 +     */
220.1159 +    private int startMode;
220.1160 +
220.1161 +    /**
220.1162 +     * Variables specifying the mode of the end rule.  Takes the following
220.1163 +     * values:
220.1164 +     * <dl>
220.1165 +     * <dt><code>DOM_MODE</code></dt>
220.1166 +     * <dd>
220.1167 +     * Exact day of week; e.g., March 1.
220.1168 +     * </dd>
220.1169 +     * <dt><code>DOW_IN_MONTH_MODE</code></dt>
220.1170 +     * <dd>
220.1171 +     * Day of week in month; e.g., last Sunday in March.
220.1172 +     * </dd>
220.1173 +     * <dt><code>DOW_GE_DOM_MODE</code></dt>
220.1174 +     * <dd>
220.1175 +     * Day of week after day of month; e.g., Sunday on or after March 15.
220.1176 +     * </dd>
220.1177 +     * <dt><code>DOW_LE_DOM_MODE</code></dt>
220.1178 +     * <dd>
220.1179 +     * Day of week before day of month; e.g., Sunday on or before March 15.
220.1180 +     * </dd>
220.1181 +     * </dl>
220.1182 +     * The setting of this field affects the interpretation of the
220.1183 +     * <code>endDay</code> field.
220.1184 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1185 +     * @serial
220.1186 +     * @since 1.1.4
220.1187 +     */
220.1188 +    private int endMode;
220.1189 +
220.1190 +    /**
220.1191 +     * A positive value indicating the amount of time saved during DST in
220.1192 +     * milliseconds.
220.1193 +     * Typically one hour (3600000); sometimes 30 minutes (1800000).
220.1194 +     * <p>If <code>useDaylight</code> is false, this value is ignored.
220.1195 +     * @serial
220.1196 +     * @since 1.1.4
220.1197 +     */
220.1198 +    private int dstSavings;
220.1199 +
220.1200 +    private static final BaseCalendar gcal = new BaseCalendar();//CalendarSystem.getGregorianCalendar();
220.1201 +
220.1202 +    /**
220.1203 +     * Cache values representing a single period of daylight saving
220.1204 +     * time. When the cache values are valid, cacheStart is the start
220.1205 +     * time (inclusive) of daylight saving time and cacheEnd is the
220.1206 +     * end time (exclusive).
220.1207 +     *
220.1208 +     * cacheYear has a year value if both cacheStart and cacheEnd are
220.1209 +     * in the same year. cacheYear is set to startYear - 1 if
220.1210 +     * cacheStart and cacheEnd are in different years. cacheStart is 0
220.1211 +     * if the cache values are void. cacheYear is a long to support
220.1212 +     * Integer.MIN_VALUE - 1 (JCK requirement).
220.1213 +     */
220.1214 +    private transient long cacheYear;
220.1215 +    private transient long cacheStart;
220.1216 +    private transient long cacheEnd;
220.1217 +
220.1218 +    /**
220.1219 +     * Constants specifying values of startMode and endMode.
220.1220 +     */
220.1221 +    private static final int DOM_MODE          = 1; // Exact day of month, "Mar 1"
220.1222 +    private static final int DOW_IN_MONTH_MODE = 2; // Day of week in month, "lastSun"
220.1223 +    private static final int DOW_GE_DOM_MODE   = 3; // Day of week after day of month, "Sun>=15"
220.1224 +    private static final int DOW_LE_DOM_MODE   = 4; // Day of week before day of month, "Sun<=21"
220.1225 +
220.1226 +    /**
220.1227 +     * Constant for a mode of start or end time specified as wall clock
220.1228 +     * time.  Wall clock time is standard time for the onset rule, and
220.1229 +     * daylight time for the end rule.
220.1230 +     * @since 1.4
220.1231 +     */
220.1232 +    public static final int WALL_TIME = 0; // Zero for backward compatibility
220.1233 +
220.1234 +    /**
220.1235 +     * Constant for a mode of start or end time specified as standard time.
220.1236 +     * @since 1.4
220.1237 +     */
220.1238 +    public static final int STANDARD_TIME = 1;
220.1239 +
220.1240 +    /**
220.1241 +     * Constant for a mode of start or end time specified as UTC. European
220.1242 +     * Union rules are specified as UTC time, for example.
220.1243 +     * @since 1.4
220.1244 +     */
220.1245 +    public static final int UTC_TIME = 2;
220.1246 +
220.1247 +    // Proclaim compatibility with 1.1
220.1248 +    static final long serialVersionUID = -403250971215465050L;
220.1249 +
220.1250 +    // the internal serial version which says which version was written
220.1251 +    // - 0 (default) for version up to JDK 1.1.3
220.1252 +    // - 1 for version from JDK 1.1.4, which includes 3 new fields
220.1253 +    // - 2 for JDK 1.3, which includes 2 new fields
220.1254 +    static final int currentSerialVersion = 2;
220.1255 +
220.1256 +    /**
220.1257 +     * The version of the serialized data on the stream.  Possible values:
220.1258 +     * <dl>
220.1259 +     * <dt><b>0</b> or not present on stream</dt>
220.1260 +     * <dd>
220.1261 +     * JDK 1.1.3 or earlier.
220.1262 +     * </dd>
220.1263 +     * <dt><b>1</b></dt>
220.1264 +     * <dd>
220.1265 +     * JDK 1.1.4 or later.  Includes three new fields: <code>startMode</code>,
220.1266 +     * <code>endMode</code>, and <code>dstSavings</code>.
220.1267 +     * </dd>
220.1268 +     * <dt><b>2</b></dt>
220.1269 +     * <dd>
220.1270 +     * JDK 1.3 or later.  Includes two new fields: <code>startTimeMode</code>
220.1271 +     * and <code>endTimeMode</code>.
220.1272 +     * </dd>
220.1273 +     * </dl>
220.1274 +     * When streaming out this class, the most recent format
220.1275 +     * and the highest allowable <code>serialVersionOnStream</code>
220.1276 +     * is written.
220.1277 +     * @serial
220.1278 +     * @since 1.1.4
220.1279 +     */
220.1280 +    private int serialVersionOnStream = currentSerialVersion;
220.1281 +
220.1282 +    synchronized private void invalidateCache() {
220.1283 +        cacheYear = startYear - 1;
220.1284 +        cacheStart = cacheEnd = 0;
220.1285 +    }
220.1286 +
220.1287 +    //----------------------------------------------------------------------
220.1288 +    // Rule representation
220.1289 +    //
220.1290 +    // We represent the following flavors of rules:
220.1291 +    //       5        the fifth of the month
220.1292 +    //       lastSun  the last Sunday in the month
220.1293 +    //       lastMon  the last Monday in the month
220.1294 +    //       Sun>=8   first Sunday on or after the eighth
220.1295 +    //       Sun<=25  last Sunday on or before the 25th
220.1296 +    // This is further complicated by the fact that we need to remain
220.1297 +    // backward compatible with the 1.1 FCS.  Finally, we need to minimize
220.1298 +    // API changes.  In order to satisfy these requirements, we support
220.1299 +    // three representation systems, and we translate between them.
220.1300 +    //
220.1301 +    // INTERNAL REPRESENTATION
220.1302 +    // This is the format SimpleTimeZone objects take after construction or
220.1303 +    // streaming in is complete.  Rules are represented directly, using an
220.1304 +    // unencoded format.  We will discuss the start rule only below; the end
220.1305 +    // rule is analogous.
220.1306 +    //   startMode      Takes on enumerated values DAY_OF_MONTH,
220.1307 +    //                  DOW_IN_MONTH, DOW_AFTER_DOM, or DOW_BEFORE_DOM.
220.1308 +    //   startDay       The day of the month, or for DOW_IN_MONTH mode, a
220.1309 +    //                  value indicating which DOW, such as +1 for first,
220.1310 +    //                  +2 for second, -1 for last, etc.
220.1311 +    //   startDayOfWeek The day of the week.  Ignored for DAY_OF_MONTH.
220.1312 +    //
220.1313 +    // ENCODED REPRESENTATION
220.1314 +    // This is the format accepted by the constructor and by setStartRule()
220.1315 +    // and setEndRule().  It uses various combinations of positive, negative,
220.1316 +    // and zero values to encode the different rules.  This representation
220.1317 +    // allows us to specify all the different rule flavors without altering
220.1318 +    // the API.
220.1319 +    //   MODE              startMonth    startDay    startDayOfWeek
220.1320 +    //   DOW_IN_MONTH_MODE >=0           !=0         >0
220.1321 +    //   DOM_MODE          >=0           >0          ==0
220.1322 +    //   DOW_GE_DOM_MODE   >=0           >0          <0
220.1323 +    //   DOW_LE_DOM_MODE   >=0           <0          <0
220.1324 +    //   (no DST)          don't care    ==0         don't care
220.1325 +    //
220.1326 +    // STREAMED REPRESENTATION
220.1327 +    // We must retain binary compatibility with the 1.1 FCS.  The 1.1 code only
220.1328 +    // handles DOW_IN_MONTH_MODE and non-DST mode, the latter indicated by the
220.1329 +    // flag useDaylight.  When we stream an object out, we translate into an
220.1330 +    // approximate DOW_IN_MONTH_MODE representation so the object can be parsed
220.1331 +    // and used by 1.1 code.  Following that, we write out the full
220.1332 +    // representation separately so that contemporary code can recognize and
220.1333 +    // parse it.  The full representation is written in a "packed" format,
220.1334 +    // consisting of a version number, a length, and an array of bytes.  Future
220.1335 +    // versions of this class may specify different versions.  If they wish to
220.1336 +    // include additional data, they should do so by storing them after the
220.1337 +    // packed representation below.
220.1338 +    //----------------------------------------------------------------------
220.1339 +
220.1340 +    /**
220.1341 +     * Given a set of encoded rules in startDay and startDayOfMonth, decode
220.1342 +     * them and set the startMode appropriately.  Do the same for endDay and
220.1343 +     * endDayOfMonth.  Upon entry, the day of week variables may be zero or
220.1344 +     * negative, in order to indicate special modes.  The day of month
220.1345 +     * variables may also be negative.  Upon exit, the mode variables will be
220.1346 +     * set, and the day of week and day of month variables will be positive.
220.1347 +     * This method also recognizes a startDay or endDay of zero as indicating
220.1348 +     * no DST.
220.1349 +     */
220.1350 +    private void decodeRules()
220.1351 +    {
220.1352 +        decodeStartRule();
220.1353 +        decodeEndRule();
220.1354 +    }
220.1355 +
220.1356 +    /**
220.1357 +     * Decode the start rule and validate the parameters.  The parameters are
220.1358 +     * expected to be in encoded form, which represents the various rule modes
220.1359 +     * by negating or zeroing certain values.  Representation formats are:
220.1360 +     * <p>
220.1361 +     * <pre>
220.1362 +     *            DOW_IN_MONTH  DOM    DOW>=DOM  DOW<=DOM  no DST
220.1363 +     *            ------------  -----  --------  --------  ----------
220.1364 +     * month       0..11        same    same      same     don't care
220.1365 +     * day        -5..5         1..31   1..31    -1..-31   0
220.1366 +     * dayOfWeek   1..7         0      -1..-7    -1..-7    don't care
220.1367 +     * time        0..ONEDAY    same    same      same     don't care
220.1368 +     * </pre>
220.1369 +     * The range for month does not include UNDECIMBER since this class is
220.1370 +     * really specific to GregorianCalendar, which does not use that month.
220.1371 +     * The range for time includes ONEDAY (vs. ending at ONEDAY-1) because the
220.1372 +     * end rule is an exclusive limit point.  That is, the range of times that
220.1373 +     * are in DST include those >= the start and < the end.  For this reason,
220.1374 +     * it should be possible to specify an end of ONEDAY in order to include the
220.1375 +     * entire day.  Although this is equivalent to time 0 of the following day,
220.1376 +     * it's not always possible to specify that, for example, on December 31.
220.1377 +     * While arguably the start range should still be 0..ONEDAY-1, we keep
220.1378 +     * the start and end ranges the same for consistency.
220.1379 +     */
220.1380 +    private void decodeStartRule() {
220.1381 +        useDaylight = (startDay != 0) && (endDay != 0);
220.1382 +        if (startDay != 0) {
220.1383 +            if (startMonth < Calendar.JANUARY || startMonth > Calendar.DECEMBER) {
220.1384 +                throw new IllegalArgumentException(
220.1385 +                        "Illegal start month " + startMonth);
220.1386 +            }
220.1387 +            if (startTime < 0 || startTime > millisPerDay) {
220.1388 +                throw new IllegalArgumentException(
220.1389 +                        "Illegal start time " + startTime);
220.1390 +            }
220.1391 +            if (startDayOfWeek == 0) {
220.1392 +                startMode = DOM_MODE;
220.1393 +            } else {
220.1394 +                if (startDayOfWeek > 0) {
220.1395 +                    startMode = DOW_IN_MONTH_MODE;
220.1396 +                } else {
220.1397 +                    startDayOfWeek = -startDayOfWeek;
220.1398 +                    if (startDay > 0) {
220.1399 +                        startMode = DOW_GE_DOM_MODE;
220.1400 +                    } else {
220.1401 +                        startDay = -startDay;
220.1402 +                        startMode = DOW_LE_DOM_MODE;
220.1403 +                    }
220.1404 +                }
220.1405 +                if (startDayOfWeek > Calendar.SATURDAY) {
220.1406 +                    throw new IllegalArgumentException(
220.1407 +                           "Illegal start day of week " + startDayOfWeek);
220.1408 +                }
220.1409 +            }
220.1410 +            if (startMode == DOW_IN_MONTH_MODE) {
220.1411 +                if (startDay < -5 || startDay > 5) {
220.1412 +                    throw new IllegalArgumentException(
220.1413 +                            "Illegal start day of week in month " + startDay);
220.1414 +                }
220.1415 +            } else if (startDay < 1 || startDay > staticMonthLength[startMonth]) {
220.1416 +                throw new IllegalArgumentException(
220.1417 +                        "Illegal start day " + startDay);
220.1418 +            }
220.1419 +        }
220.1420 +    }
220.1421 +
220.1422 +    /**
220.1423 +     * Decode the end rule and validate the parameters.  This method is exactly
220.1424 +     * analogous to decodeStartRule().
220.1425 +     * @see decodeStartRule
220.1426 +     */
220.1427 +    private void decodeEndRule() {
220.1428 +        useDaylight = (startDay != 0) && (endDay != 0);
220.1429 +        if (endDay != 0) {
220.1430 +            if (endMonth < Calendar.JANUARY || endMonth > Calendar.DECEMBER) {
220.1431 +                throw new IllegalArgumentException(
220.1432 +                        "Illegal end month " + endMonth);
220.1433 +            }
220.1434 +            if (endTime < 0 || endTime > millisPerDay) {
220.1435 +                throw new IllegalArgumentException(
220.1436 +                        "Illegal end time " + endTime);
220.1437 +            }
220.1438 +            if (endDayOfWeek == 0) {
220.1439 +                endMode = DOM_MODE;
220.1440 +            } else {
220.1441 +                if (endDayOfWeek > 0) {
220.1442 +                    endMode = DOW_IN_MONTH_MODE;
220.1443 +                } else {
220.1444 +                    endDayOfWeek = -endDayOfWeek;
220.1445 +                    if (endDay > 0) {
220.1446 +                        endMode = DOW_GE_DOM_MODE;
220.1447 +                    } else {
220.1448 +                        endDay = -endDay;
220.1449 +                        endMode = DOW_LE_DOM_MODE;
220.1450 +                    }
220.1451 +                }
220.1452 +                if (endDayOfWeek > Calendar.SATURDAY) {
220.1453 +                    throw new IllegalArgumentException(
220.1454 +                           "Illegal end day of week " + endDayOfWeek);
220.1455 +                }
220.1456 +            }
220.1457 +            if (endMode == DOW_IN_MONTH_MODE) {
220.1458 +                if (endDay < -5 || endDay > 5) {
220.1459 +                    throw new IllegalArgumentException(
220.1460 +                            "Illegal end day of week in month " + endDay);
220.1461 +                }
220.1462 +            } else if (endDay < 1 || endDay > staticMonthLength[endMonth]) {
220.1463 +                throw new IllegalArgumentException(
220.1464 +                        "Illegal end day " + endDay);
220.1465 +            }
220.1466 +        }
220.1467 +    }
220.1468 +
220.1469 +    /**
220.1470 +     * Make rules compatible to 1.1 FCS code.  Since 1.1 FCS code only understands
220.1471 +     * day-of-week-in-month rules, we must modify other modes of rules to their
220.1472 +     * approximate equivalent in 1.1 FCS terms.  This method is used when streaming
220.1473 +     * out objects of this class.  After it is called, the rules will be modified,
220.1474 +     * with a possible loss of information.  startMode and endMode will NOT be
220.1475 +     * altered, even though semantically they should be set to DOW_IN_MONTH_MODE,
220.1476 +     * since the rule modification is only intended to be temporary.
220.1477 +     */
220.1478 +    private void makeRulesCompatible()
220.1479 +    {
220.1480 +        switch (startMode) {
220.1481 +        case DOM_MODE:
220.1482 +            startDay = 1 + (startDay / 7);
220.1483 +            startDayOfWeek = Calendar.SUNDAY;
220.1484 +            break;
220.1485 +
220.1486 +        case DOW_GE_DOM_MODE:
220.1487 +            // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
220.1488 +            // that is, Sun>=1 == firstSun.
220.1489 +            if (startDay != 1) {
220.1490 +                startDay = 1 + (startDay / 7);
220.1491 +            }
220.1492 +            break;
220.1493 +
220.1494 +        case DOW_LE_DOM_MODE:
220.1495 +            if (startDay >= 30) {
220.1496 +                startDay = -1;
220.1497 +            } else {
220.1498 +                startDay = 1 + (startDay / 7);
220.1499 +            }
220.1500 +            break;
220.1501 +        }
220.1502 +
220.1503 +        switch (endMode) {
220.1504 +        case DOM_MODE:
220.1505 +            endDay = 1 + (endDay / 7);
220.1506 +            endDayOfWeek = Calendar.SUNDAY;
220.1507 +            break;
220.1508 +
220.1509 +        case DOW_GE_DOM_MODE:
220.1510 +            // A day-of-month of 1 is equivalent to DOW_IN_MONTH_MODE
220.1511 +            // that is, Sun>=1 == firstSun.
220.1512 +            if (endDay != 1) {
220.1513 +                endDay = 1 + (endDay / 7);
220.1514 +            }
220.1515 +            break;
220.1516 +
220.1517 +        case DOW_LE_DOM_MODE:
220.1518 +            if (endDay >= 30) {
220.1519 +                endDay = -1;
220.1520 +            } else {
220.1521 +                endDay = 1 + (endDay / 7);
220.1522 +            }
220.1523 +            break;
220.1524 +        }
220.1525 +
220.1526 +        /*
220.1527 +         * Adjust the start and end times to wall time.  This works perfectly
220.1528 +         * well unless it pushes into the next or previous day.  If that
220.1529 +         * happens, we attempt to adjust the day rule somewhat crudely.  The day
220.1530 +         * rules have been forced into DOW_IN_MONTH mode already, so we change
220.1531 +         * the day of week to move forward or back by a day.  It's possible to
220.1532 +         * make a more refined adjustment of the original rules first, but in
220.1533 +         * most cases this extra effort will go to waste once we adjust the day
220.1534 +         * rules anyway.
220.1535 +         */
220.1536 +        switch (startTimeMode) {
220.1537 +        case UTC_TIME:
220.1538 +            startTime += rawOffset;
220.1539 +            break;
220.1540 +        }
220.1541 +        while (startTime < 0) {
220.1542 +            startTime += millisPerDay;
220.1543 +            startDayOfWeek = 1 + ((startDayOfWeek+5) % 7); // Back 1 day
220.1544 +        }
220.1545 +        while (startTime >= millisPerDay) {
220.1546 +            startTime -= millisPerDay;
220.1547 +            startDayOfWeek = 1 + (startDayOfWeek % 7); // Forward 1 day
220.1548 +        }
220.1549 +
220.1550 +        switch (endTimeMode) {
220.1551 +        case UTC_TIME:
220.1552 +            endTime += rawOffset + dstSavings;
220.1553 +            break;
220.1554 +        case STANDARD_TIME:
220.1555 +            endTime += dstSavings;
220.1556 +        }
220.1557 +        while (endTime < 0) {
220.1558 +            endTime += millisPerDay;
220.1559 +            endDayOfWeek = 1 + ((endDayOfWeek+5) % 7); // Back 1 day
220.1560 +        }
220.1561 +        while (endTime >= millisPerDay) {
220.1562 +            endTime -= millisPerDay;
220.1563 +            endDayOfWeek = 1 + (endDayOfWeek % 7); // Forward 1 day
220.1564 +        }
220.1565 +    }
220.1566 +
220.1567 +    /**
220.1568 +     * Pack the start and end rules into an array of bytes.  Only pack
220.1569 +     * data which is not preserved by makeRulesCompatible.
220.1570 +     */
220.1571 +    private byte[] packRules()
220.1572 +    {
220.1573 +        byte[] rules = new byte[6];
220.1574 +        rules[0] = (byte)startDay;
220.1575 +        rules[1] = (byte)startDayOfWeek;
220.1576 +        rules[2] = (byte)endDay;
220.1577 +        rules[3] = (byte)endDayOfWeek;
220.1578 +
220.1579 +        // As of serial version 2, include time modes
220.1580 +        rules[4] = (byte)startTimeMode;
220.1581 +        rules[5] = (byte)endTimeMode;
220.1582 +
220.1583 +        return rules;
220.1584 +    }
220.1585 +
220.1586 +    /**
220.1587 +     * Given an array of bytes produced by packRules, interpret them
220.1588 +     * as the start and end rules.
220.1589 +     */
220.1590 +    private void unpackRules(byte[] rules)
220.1591 +    {
220.1592 +        startDay       = rules[0];
220.1593 +        startDayOfWeek = rules[1];
220.1594 +        endDay         = rules[2];
220.1595 +        endDayOfWeek   = rules[3];
220.1596 +
220.1597 +        // As of serial version 2, include time modes
220.1598 +        if (rules.length >= 6) {
220.1599 +            startTimeMode = rules[4];
220.1600 +            endTimeMode   = rules[5];
220.1601 +        }
220.1602 +    }
220.1603 +
220.1604 +    /**
220.1605 +     * Pack the start and end times into an array of bytes.  This is required
220.1606 +     * as of serial version 2.
220.1607 +     */
220.1608 +    private int[] packTimes() {
220.1609 +        int[] times = new int[2];
220.1610 +        times[0] = startTime;
220.1611 +        times[1] = endTime;
220.1612 +        return times;
220.1613 +    }
220.1614 +
220.1615 +    /**
220.1616 +     * Unpack the start and end times from an array of bytes.  This is required
220.1617 +     * as of serial version 2.
220.1618 +     */
220.1619 +    private void unpackTimes(int[] times) {
220.1620 +        startTime = times[0];
220.1621 +        endTime = times[1];
220.1622 +    }
220.1623 +
220.1624 +    /**
220.1625 +     * Save the state of this object to a stream (i.e., serialize it).
220.1626 +     *
220.1627 +     * @serialData We write out two formats, a JDK 1.1 compatible format, using
220.1628 +     * <code>DOW_IN_MONTH_MODE</code> rules, in the required section, followed
220.1629 +     * by the full rules, in packed format, in the optional section.  The
220.1630 +     * optional section will be ignored by JDK 1.1 code upon stream in.
220.1631 +     * <p> Contents of the optional section: The length of a byte array is
220.1632 +     * emitted (int); this is 4 as of this release. The byte array of the given
220.1633 +     * length is emitted. The contents of the byte array are the true values of
220.1634 +     * the fields <code>startDay</code>, <code>startDayOfWeek</code>,
220.1635 +     * <code>endDay</code>, and <code>endDayOfWeek</code>.  The values of these
220.1636 +     * fields in the required section are approximate values suited to the rule
220.1637 +     * mode <code>DOW_IN_MONTH_MODE</code>, which is the only mode recognized by
220.1638 +     * JDK 1.1.
220.1639 +     */
220.1640 +    private void writeObject(ObjectOutputStream stream)
220.1641 +         throws IOException
220.1642 +    {
220.1643 +        // Construct a binary rule
220.1644 +        byte[] rules = packRules();
220.1645 +        int[] times = packTimes();
220.1646 +
220.1647 +        // Convert to 1.1 FCS rules.  This step may cause us to lose information.
220.1648 +        makeRulesCompatible();
220.1649 +
220.1650 +        // Write out the 1.1 FCS rules
220.1651 +        stream.defaultWriteObject();
220.1652 +
220.1653 +        // Write out the binary rules in the optional data area of the stream.
220.1654 +        stream.writeInt(rules.length);
220.1655 +        stream.write(rules);
220.1656 +        stream.writeObject(times);
220.1657 +
220.1658 +        // Recover the original rules.  This recovers the information lost
220.1659 +        // by makeRulesCompatible.
220.1660 +        unpackRules(rules);
220.1661 +        unpackTimes(times);
220.1662 +    }
220.1663 +
220.1664 +    /**
220.1665 +     * Reconstitute this object from a stream (i.e., deserialize it).
220.1666 +     *
220.1667 +     * We handle both JDK 1.1
220.1668 +     * binary formats and full formats with a packed byte array.
220.1669 +     */
220.1670 +    private void readObject(ObjectInputStream stream)
220.1671 +         throws IOException, ClassNotFoundException
220.1672 +    {
220.1673 +        stream.defaultReadObject();
220.1674 +
220.1675 +        if (serialVersionOnStream < 1) {
220.1676 +            // Fix a bug in the 1.1 SimpleTimeZone code -- namely,
220.1677 +            // startDayOfWeek and endDayOfWeek were usually uninitialized.  We can't do
220.1678 +            // too much, so we assume SUNDAY, which actually works most of the time.
220.1679 +            if (startDayOfWeek == 0) {
220.1680 +                startDayOfWeek = Calendar.SUNDAY;
220.1681 +            }
220.1682 +            if (endDayOfWeek == 0) {
220.1683 +                endDayOfWeek = Calendar.SUNDAY;
220.1684 +            }
220.1685 +
220.1686 +            // The variables dstSavings, startMode, and endMode are post-1.1, so they
220.1687 +            // won't be present if we're reading from a 1.1 stream.  Fix them up.
220.1688 +            startMode = endMode = DOW_IN_MONTH_MODE;
220.1689 +            dstSavings = millisPerHour;
220.1690 +        } else {
220.1691 +            // For 1.1.4, in addition to the 3 new instance variables, we also
220.1692 +            // store the actual rules (which have not be made compatible with 1.1)
220.1693 +            // in the optional area.  Read them in here and parse them.
220.1694 +            int length = stream.readInt();
220.1695 +            byte[] rules = new byte[length];
220.1696 +            stream.readFully(rules);
220.1697 +            unpackRules(rules);
220.1698 +        }
220.1699 +
220.1700 +        if (serialVersionOnStream >= 2) {
220.1701 +            int[] times = (int[]) stream.readObject();
220.1702 +            unpackTimes(times);
220.1703 +        }
220.1704 +
220.1705 +        serialVersionOnStream = currentSerialVersion;
220.1706 +    }
220.1707 +    
220.1708 +    static final class GregorianCalendar {
220.1709 +        public static final int BC = 0;
220.1710 +
220.1711 +        /**
220.1712 +         * Value of the {@link #ERA} field indicating the period before the
220.1713 +         * common era, the same value as {@link #BC}.
220.1714 +         *
220.1715 +         * @see #CE
220.1716 +         */
220.1717 +        static final int BCE = 0;
220.1718 +
220.1719 +        /**
220.1720 +         * Value of the <code>ERA</code> field indicating the common era (Anno
220.1721 +         * Domini), also known as CE. The sequence of years at the transition
220.1722 +         * from <code>BC</code> to <code>AD</code> is ..., 2 BC, 1 BC, 1 AD, 2
220.1723 +         * AD,...
220.1724 +         *
220.1725 +         * @see #ERA
220.1726 +         */
220.1727 +        public static final int AD = 1;
220.1728 +
220.1729 +        // The default value of gregorianCutover.
220.1730 +        static final long DEFAULT_GREGORIAN_CUTOVER = -12219292800000L;
220.1731 +        /**
220.1732 +         * Value of the {@link #ERA} field indicating
220.1733 +         * the common era, the same value as {@link #AD}.
220.1734 +         *
220.1735 +         * @see #BCE
220.1736 +         */
220.1737 +        static final int CE = 1;
220.1738 +        
220.1739 +    }
220.1740 +}
   221.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   221.2 +++ b/rt/emul/compact/src/main/java/java/util/TimeZone.java	Wed Apr 30 15:04:10 2014 +0200
   221.3 @@ -0,0 +1,715 @@
   221.4 +/*
   221.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   221.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   221.7 + *
   221.8 + * This code is free software; you can redistribute it and/or modify it
   221.9 + * under the terms of the GNU General Public License version 2 only, as
  221.10 + * published by the Free Software Foundation.  Oracle designates this
  221.11 + * particular file as subject to the "Classpath" exception as provided
  221.12 + * by Oracle in the LICENSE file that accompanied this code.
  221.13 + *
  221.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  221.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  221.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  221.17 + * version 2 for more details (a copy is included in the LICENSE file that
  221.18 + * accompanied this code).
  221.19 + *
  221.20 + * You should have received a copy of the GNU General Public License version
  221.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  221.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  221.23 + *
  221.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  221.25 + * or visit www.oracle.com if you need additional information or have any
  221.26 + * questions.
  221.27 + */
  221.28 +
  221.29 +/*
  221.30 + * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  221.31 + * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  221.32 + *
  221.33 + *   The original version of this source code and documentation is copyrighted
  221.34 + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  221.35 + * materials are provided under terms of a License Agreement between Taligent
  221.36 + * and Sun. This technology is protected by multiple US and International
  221.37 + * patents. This notice and attribution to Taligent may not be removed.
  221.38 + *   Taligent is a registered trademark of Taligent, Inc.
  221.39 + *
  221.40 + */
  221.41 +
  221.42 +package java.util;
  221.43 +
  221.44 +import java.io.Serializable;
  221.45 +import java.lang.ref.SoftReference;
  221.46 +import java.security.AccessController;
  221.47 +import java.security.PrivilegedAction;
  221.48 +import java.util.concurrent.ConcurrentHashMap;
  221.49 +
  221.50 +/**
  221.51 + * <code>TimeZone</code> represents a time zone offset, and also figures out daylight
  221.52 + * savings.
  221.53 + *
  221.54 + * <p>
  221.55 + * Typically, you get a <code>TimeZone</code> using <code>getDefault</code>
  221.56 + * which creates a <code>TimeZone</code> based on the time zone where the program
  221.57 + * is running. For example, for a program running in Japan, <code>getDefault</code>
  221.58 + * creates a <code>TimeZone</code> object based on Japanese Standard Time.
  221.59 + *
  221.60 + * <p>
  221.61 + * You can also get a <code>TimeZone</code> using <code>getTimeZone</code>
  221.62 + * along with a time zone ID. For instance, the time zone ID for the
  221.63 + * U.S. Pacific Time zone is "America/Los_Angeles". So, you can get a
  221.64 + * U.S. Pacific Time <code>TimeZone</code> object with:
  221.65 + * <blockquote><pre>
  221.66 + * TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
  221.67 + * </pre></blockquote>
  221.68 + * You can use the <code>getAvailableIDs</code> method to iterate through
  221.69 + * all the supported time zone IDs. You can then choose a
  221.70 + * supported ID to get a <code>TimeZone</code>.
  221.71 + * If the time zone you want is not represented by one of the
  221.72 + * supported IDs, then a custom time zone ID can be specified to
  221.73 + * produce a TimeZone. The syntax of a custom time zone ID is:
  221.74 + *
  221.75 + * <blockquote><pre>
  221.76 + * <a name="CustomID"><i>CustomID:</i></a>
  221.77 + *         <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
  221.78 + *         <code>GMT</code> <i>Sign</i> <i>Hours</i> <i>Minutes</i>
  221.79 + *         <code>GMT</code> <i>Sign</i> <i>Hours</i>
  221.80 + * <i>Sign:</i> one of
  221.81 + *         <code>+ -</code>
  221.82 + * <i>Hours:</i>
  221.83 + *         <i>Digit</i>
  221.84 + *         <i>Digit</i> <i>Digit</i>
  221.85 + * <i>Minutes:</i>
  221.86 + *         <i>Digit</i> <i>Digit</i>
  221.87 + * <i>Digit:</i> one of
  221.88 + *         <code>0 1 2 3 4 5 6 7 8 9</code>
  221.89 + * </pre></blockquote>
  221.90 + *
  221.91 + * <i>Hours</i> must be between 0 to 23 and <i>Minutes</i> must be
  221.92 + * between 00 to 59.  For example, "GMT+10" and "GMT+0010" mean ten
  221.93 + * hours and ten minutes ahead of GMT, respectively.
  221.94 + * <p>
  221.95 + * The format is locale independent and digits must be taken from the
  221.96 + * Basic Latin block of the Unicode standard. No daylight saving time
  221.97 + * transition schedule can be specified with a custom time zone ID. If
  221.98 + * the specified string doesn't match the syntax, <code>"GMT"</code>
  221.99 + * is used.
 221.100 + * <p>
 221.101 + * When creating a <code>TimeZone</code>, the specified custom time
 221.102 + * zone ID is normalized in the following syntax:
 221.103 + * <blockquote><pre>
 221.104 + * <a name="NormalizedCustomID"><i>NormalizedCustomID:</i></a>
 221.105 + *         <code>GMT</code> <i>Sign</i> <i>TwoDigitHours</i> <code>:</code> <i>Minutes</i>
 221.106 + * <i>Sign:</i> one of
 221.107 + *         <code>+ -</code>
 221.108 + * <i>TwoDigitHours:</i>
 221.109 + *         <i>Digit</i> <i>Digit</i>
 221.110 + * <i>Minutes:</i>
 221.111 + *         <i>Digit</i> <i>Digit</i>
 221.112 + * <i>Digit:</i> one of
 221.113 + *         <code>0 1 2 3 4 5 6 7 8 9</code>
 221.114 + * </pre></blockquote>
 221.115 + * For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
 221.116 + *
 221.117 + * <h4>Three-letter time zone IDs</h4>
 221.118 + *
 221.119 + * For compatibility with JDK 1.1.x, some other three-letter time zone IDs
 221.120 + * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
 221.121 + * use is deprecated</strong> because the same abbreviation is often used
 221.122 + * for multiple time zones (for example, "CST" could be U.S. "Central Standard
 221.123 + * Time" and "China Standard Time"), and the Java platform can then only
 221.124 + * recognize one of them.
 221.125 + *
 221.126 + *
 221.127 + * @see          Calendar
 221.128 + * @see          GregorianCalendar
 221.129 + * @see          SimpleTimeZone
 221.130 + * @author       Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
 221.131 + * @since        JDK1.1
 221.132 + */
 221.133 +abstract public class TimeZone implements Serializable, Cloneable {
 221.134 +    /**
 221.135 +     * Sole constructor.  (For invocation by subclass constructors, typically
 221.136 +     * implicit.)
 221.137 +     */
 221.138 +    public TimeZone() {
 221.139 +    }
 221.140 +
 221.141 +    /**
 221.142 +     * A style specifier for <code>getDisplayName()</code> indicating
 221.143 +     * a short name, such as "PST."
 221.144 +     * @see #LONG
 221.145 +     * @since 1.2
 221.146 +     */
 221.147 +    public static final int SHORT = 0;
 221.148 +
 221.149 +    /**
 221.150 +     * A style specifier for <code>getDisplayName()</code> indicating
 221.151 +     * a long name, such as "Pacific Standard Time."
 221.152 +     * @see #SHORT
 221.153 +     * @since 1.2
 221.154 +     */
 221.155 +    public static final int LONG  = 1;
 221.156 +
 221.157 +    // Constants used internally; unit is milliseconds
 221.158 +    private static final int ONE_MINUTE = 60*1000;
 221.159 +    private static final int ONE_HOUR   = 60*ONE_MINUTE;
 221.160 +    private static final int ONE_DAY    = 24*ONE_HOUR;
 221.161 +
 221.162 +    // Proclaim serialization compatibility with JDK 1.1
 221.163 +    static final long serialVersionUID = 3581463369166924961L;
 221.164 +
 221.165 +    /**
 221.166 +     * Gets the time zone offset, for current date, modified in case of
 221.167 +     * daylight savings. This is the offset to add to UTC to get local time.
 221.168 +     * <p>
 221.169 +     * This method returns a historically correct offset if an
 221.170 +     * underlying <code>TimeZone</code> implementation subclass
 221.171 +     * supports historical Daylight Saving Time schedule and GMT
 221.172 +     * offset changes.
 221.173 +     *
 221.174 +     * @param era the era of the given date.
 221.175 +     * @param year the year in the given date.
 221.176 +     * @param month the month in the given date.
 221.177 +     * Month is 0-based. e.g., 0 for January.
 221.178 +     * @param day the day-in-month of the given date.
 221.179 +     * @param dayOfWeek the day-of-week of the given date.
 221.180 +     * @param milliseconds the milliseconds in day in <em>standard</em>
 221.181 +     * local time.
 221.182 +     *
 221.183 +     * @return the offset in milliseconds to add to GMT to get local time.
 221.184 +     *
 221.185 +     * @see Calendar#ZONE_OFFSET
 221.186 +     * @see Calendar#DST_OFFSET
 221.187 +     */
 221.188 +    public abstract int getOffset(int era, int year, int month, int day,
 221.189 +                                  int dayOfWeek, int milliseconds);
 221.190 +
 221.191 +    /**
 221.192 +     * Returns the offset of this time zone from UTC at the specified
 221.193 +     * date. If Daylight Saving Time is in effect at the specified
 221.194 +     * date, the offset value is adjusted with the amount of daylight
 221.195 +     * saving.
 221.196 +     * <p>
 221.197 +     * This method returns a historically correct offset value if an
 221.198 +     * underlying TimeZone implementation subclass supports historical
 221.199 +     * Daylight Saving Time schedule and GMT offset changes.
 221.200 +     *
 221.201 +     * @param date the date represented in milliseconds since January 1, 1970 00:00:00 GMT
 221.202 +     * @return the amount of time in milliseconds to add to UTC to get local time.
 221.203 +     *
 221.204 +     * @see Calendar#ZONE_OFFSET
 221.205 +     * @see Calendar#DST_OFFSET
 221.206 +     * @since 1.4
 221.207 +     */
 221.208 +    public int getOffset(long date) {
 221.209 +        if (inDaylightTime(new Date(date))) {
 221.210 +            return getRawOffset() + getDSTSavings();
 221.211 +        }
 221.212 +        return getRawOffset();
 221.213 +    }
 221.214 +
 221.215 +    /**
 221.216 +     * Gets the raw GMT offset and the amount of daylight saving of this
 221.217 +     * time zone at the given time.
 221.218 +     * @param date the milliseconds (since January 1, 1970,
 221.219 +     * 00:00:00.000 GMT) at which the time zone offset and daylight
 221.220 +     * saving amount are found
 221.221 +     * @param offset an array of int where the raw GMT offset
 221.222 +     * (offset[0]) and daylight saving amount (offset[1]) are stored,
 221.223 +     * or null if those values are not needed. The method assumes that
 221.224 +     * the length of the given array is two or larger.
 221.225 +     * @return the total amount of the raw GMT offset and daylight
 221.226 +     * saving at the specified date.
 221.227 +     *
 221.228 +     * @see Calendar#ZONE_OFFSET
 221.229 +     * @see Calendar#DST_OFFSET
 221.230 +     */
 221.231 +    int getOffsets(long date, int[] offsets) {
 221.232 +        int rawoffset = getRawOffset();
 221.233 +        int dstoffset = 0;
 221.234 +        if (inDaylightTime(new Date(date))) {
 221.235 +            dstoffset = getDSTSavings();
 221.236 +        }
 221.237 +        if (offsets != null) {
 221.238 +            offsets[0] = rawoffset;
 221.239 +            offsets[1] = dstoffset;
 221.240 +        }
 221.241 +        return rawoffset + dstoffset;
 221.242 +    }
 221.243 +
 221.244 +    /**
 221.245 +     * Sets the base time zone offset to GMT.
 221.246 +     * This is the offset to add to UTC to get local time.
 221.247 +     * <p>
 221.248 +     * If an underlying <code>TimeZone</code> implementation subclass
 221.249 +     * supports historical GMT offset changes, the specified GMT
 221.250 +     * offset is set as the latest GMT offset and the difference from
 221.251 +     * the known latest GMT offset value is used to adjust all
 221.252 +     * historical GMT offset values.
 221.253 +     *
 221.254 +     * @param offsetMillis the given base time zone offset to GMT.
 221.255 +     */
 221.256 +    abstract public void setRawOffset(int offsetMillis);
 221.257 +
 221.258 +    /**
 221.259 +     * Returns the amount of time in milliseconds to add to UTC to get
 221.260 +     * standard time in this time zone. Because this value is not
 221.261 +     * affected by daylight saving time, it is called <I>raw
 221.262 +     * offset</I>.
 221.263 +     * <p>
 221.264 +     * If an underlying <code>TimeZone</code> implementation subclass
 221.265 +     * supports historical GMT offset changes, the method returns the
 221.266 +     * raw offset value of the current date. In Honolulu, for example,
 221.267 +     * its raw offset changed from GMT-10:30 to GMT-10:00 in 1947, and
 221.268 +     * this method always returns -36000000 milliseconds (i.e., -10
 221.269 +     * hours).
 221.270 +     *
 221.271 +     * @return the amount of raw offset time in milliseconds to add to UTC.
 221.272 +     * @see Calendar#ZONE_OFFSET
 221.273 +     */
 221.274 +    public abstract int getRawOffset();
 221.275 +
 221.276 +    /**
 221.277 +     * Gets the ID of this time zone.
 221.278 +     * @return the ID of this time zone.
 221.279 +     */
 221.280 +    public String getID()
 221.281 +    {
 221.282 +        return ID;
 221.283 +    }
 221.284 +
 221.285 +    /**
 221.286 +     * Sets the time zone ID. This does not change any other data in
 221.287 +     * the time zone object.
 221.288 +     * @param ID the new time zone ID.
 221.289 +     */
 221.290 +    public void setID(String ID)
 221.291 +    {
 221.292 +        if (ID == null) {
 221.293 +            throw new NullPointerException();
 221.294 +        }
 221.295 +        this.ID = ID;
 221.296 +    }
 221.297 +
 221.298 +    /**
 221.299 +     * Returns a long standard time name of this {@code TimeZone} suitable for
 221.300 +     * presentation to the user in the default locale.
 221.301 +     *
 221.302 +     * <p>This method is equivalent to:
 221.303 +     * <pre><blockquote>
 221.304 +     * getDisplayName(false, {@link #LONG},
 221.305 +     *                Locale.getDefault({@link Locale.Category#DISPLAY}))
 221.306 +     * </blockquote></pre>
 221.307 +     *
 221.308 +     * @return the human-readable name of this time zone in the default locale.
 221.309 +     * @since 1.2
 221.310 +     * @see #getDisplayName(boolean, int, Locale)
 221.311 +     * @see Locale#getDefault(Locale.Category)
 221.312 +     * @see Locale.Category
 221.313 +     */
 221.314 +    public final String getDisplayName() {
 221.315 +        return getDisplayName(false, LONG,
 221.316 +                              Locale.getDefault(Locale.Category.DISPLAY));
 221.317 +    }
 221.318 +
 221.319 +    /**
 221.320 +     * Returns a long standard time name of this {@code TimeZone} suitable for
 221.321 +     * presentation to the user in the specified {@code locale}.
 221.322 +     *
 221.323 +     * <p>This method is equivalent to:
 221.324 +     * <pre><blockquote>
 221.325 +     * getDisplayName(false, {@link #LONG}, locale)
 221.326 +     * </blockquote></pre>
 221.327 +     *
 221.328 +     * @param locale the locale in which to supply the display name.
 221.329 +     * @return the human-readable name of this time zone in the given locale.
 221.330 +     * @exception NullPointerException if {@code locale} is {@code null}.
 221.331 +     * @since 1.2
 221.332 +     * @see #getDisplayName(boolean, int, Locale)
 221.333 +     */
 221.334 +    public final String getDisplayName(Locale locale) {
 221.335 +        return getDisplayName(false, LONG, locale);
 221.336 +    }
 221.337 +
 221.338 +    /**
 221.339 +     * Returns a name in the specified {@code style} of this {@code TimeZone}
 221.340 +     * suitable for presentation to the user in the default locale. If the
 221.341 +     * specified {@code daylight} is {@code true}, a Daylight Saving Time name
 221.342 +     * is returned (even if this {@code TimeZone} doesn't observe Daylight Saving
 221.343 +     * Time). Otherwise, a Standard Time name is returned.
 221.344 +     *
 221.345 +     * <p>This method is equivalent to:
 221.346 +     * <pre><blockquote>
 221.347 +     * getDisplayName(daylight, style,
 221.348 +     *                Locale.getDefault({@link Locale.Category#DISPLAY}))
 221.349 +     * </blockquote></pre>
 221.350 +     *
 221.351 +     * @param daylight {@code true} specifying a Daylight Saving Time name, or
 221.352 +     *                 {@code false} specifying a Standard Time name
 221.353 +     * @param style either {@link #LONG} or {@link #SHORT}
 221.354 +     * @return the human-readable name of this time zone in the default locale.
 221.355 +     * @exception IllegalArgumentException if {@code style} is invalid.
 221.356 +     * @since 1.2
 221.357 +     * @see #getDisplayName(boolean, int, Locale)
 221.358 +     * @see Locale#getDefault(Locale.Category)
 221.359 +     * @see Locale.Category
 221.360 +     * @see java.text.DateFormatSymbols#getZoneStrings()
 221.361 +     */
 221.362 +    public final String getDisplayName(boolean daylight, int style) {
 221.363 +        return getDisplayName(daylight, style,
 221.364 +                              Locale.getDefault(Locale.Category.DISPLAY));
 221.365 +    }
 221.366 +
 221.367 +    /**
 221.368 +     * Returns a name in the specified {@code style} of this {@code TimeZone}
 221.369 +     * suitable for presentation to the user in the specified {@code
 221.370 +     * locale}. If the specified {@code daylight} is {@code true}, a Daylight
 221.371 +     * Saving Time name is returned (even if this {@code TimeZone} doesn't
 221.372 +     * observe Daylight Saving Time). Otherwise, a Standard Time name is
 221.373 +     * returned.
 221.374 +     *
 221.375 +     * <p>When looking up a time zone name, the {@linkplain
 221.376 +     * ResourceBundle.Control#getCandidateLocales(String,Locale) default
 221.377 +     * <code>Locale</code> search path of <code>ResourceBundle</code>} derived
 221.378 +     * from the specified {@code locale} is used. (No {@linkplain
 221.379 +     * ResourceBundle.Control#getFallbackLocale(String,Locale) fallback
 221.380 +     * <code>Locale</code>} search is performed.) If a time zone name in any
 221.381 +     * {@code Locale} of the search path, including {@link Locale#ROOT}, is
 221.382 +     * found, the name is returned. Otherwise, a string in the
 221.383 +     * <a href="#NormalizedCustomID">normalized custom ID format</a> is returned.
 221.384 +     *
 221.385 +     * @param daylight {@code true} specifying a Daylight Saving Time name, or
 221.386 +     *                 {@code false} specifying a Standard Time name
 221.387 +     * @param style either {@link #LONG} or {@link #SHORT}
 221.388 +     * @param locale   the locale in which to supply the display name.
 221.389 +     * @return the human-readable name of this time zone in the given locale.
 221.390 +     * @exception IllegalArgumentException if {@code style} is invalid.
 221.391 +     * @exception NullPointerException if {@code locale} is {@code null}.
 221.392 +     * @since 1.2
 221.393 +     * @see java.text.DateFormatSymbols#getZoneStrings()
 221.394 +     */
 221.395 +    public String getDisplayName(boolean daylight, int style, Locale locale) {
 221.396 +        if (style != SHORT && style != LONG) {
 221.397 +            throw new IllegalArgumentException("Illegal style: " + style);
 221.398 +        }
 221.399 +
 221.400 +        String id = getID();
 221.401 +        String[] names = getDisplayNames(id, locale);
 221.402 +        if (names == null) {
 221.403 +            if (id.startsWith("GMT")) {
 221.404 +                char sign = id.charAt(3);
 221.405 +                if (sign == '+' || sign == '-') {
 221.406 +                    return id;
 221.407 +                }
 221.408 +            }
 221.409 +            int offset = getRawOffset();
 221.410 +            if (daylight) {
 221.411 +                offset += getDSTSavings();
 221.412 +            }
 221.413 +          //  return ZoneInfoFile.toCustomID(offset);
 221.414 +        }
 221.415 +
 221.416 +        int index = daylight ? 3 : 1;
 221.417 +        if (style == SHORT) {
 221.418 +            index++;
 221.419 +        }
 221.420 +        return names[index];
 221.421 +    }
 221.422 +
 221.423 +    private static class DisplayNames {
 221.424 +        // Cache for managing display names per timezone per locale
 221.425 +        // The structure is:
 221.426 +        //   Map(key=id, value=SoftReference(Map(key=locale, value=displaynames)))
 221.427 +        private static final Map<String, SoftReference<Map<Locale, String[]>>> CACHE =
 221.428 +            new ConcurrentHashMap<String, SoftReference<Map<Locale, String[]>>>();
 221.429 +    }
 221.430 +
 221.431 +    private static final String[] getDisplayNames(String id, Locale locale) {
 221.432 +        Map<String, SoftReference<Map<Locale, String[]>>> displayNames = DisplayNames.CACHE;
 221.433 +
 221.434 +        SoftReference<Map<Locale, String[]>> ref = displayNames.get(id);
 221.435 +        if (ref != null) {
 221.436 +            Map<Locale, String[]> perLocale = ref.get();
 221.437 +            if (perLocale != null) {
 221.438 +                String[] names = perLocale.get(locale);
 221.439 +                if (names != null) {
 221.440 +                    return names;
 221.441 +                }
 221.442 +                names = null; // TimeZoneNameUtility.retrieveDisplayNames(id, locale);
 221.443 +                if (names != null) {
 221.444 +                    perLocale.put(locale, names);
 221.445 +                }
 221.446 +                return names;
 221.447 +            }
 221.448 +        }
 221.449 +
 221.450 +        String[] names = null; // TimeZoneNameUtility.retrieveDisplayNames(id, locale);
 221.451 +        if (names != null) {
 221.452 +            Map<Locale, String[]> perLocale = new ConcurrentHashMap<Locale, String[]>();
 221.453 +            perLocale.put(locale, names);
 221.454 +            ref = new SoftReference<Map<Locale, String[]>>(perLocale);
 221.455 +            displayNames.put(id, ref);
 221.456 +        }
 221.457 +        return names;
 221.458 +    }
 221.459 +
 221.460 +    /**
 221.461 +     * Returns the amount of time to be added to local standard time
 221.462 +     * to get local wall clock time.
 221.463 +     *
 221.464 +     * <p>The default implementation returns 3600000 milliseconds
 221.465 +     * (i.e., one hour) if a call to {@link #useDaylightTime()}
 221.466 +     * returns {@code true}. Otherwise, 0 (zero) is returned.
 221.467 +     *
 221.468 +     * <p>If an underlying {@code TimeZone} implementation subclass
 221.469 +     * supports historical and future Daylight Saving Time schedule
 221.470 +     * changes, this method returns the amount of saving time of the
 221.471 +     * last known Daylight Saving Time rule that can be a future
 221.472 +     * prediction.
 221.473 +     *
 221.474 +     * <p>If the amount of saving time at any given time stamp is
 221.475 +     * required, construct a {@link Calendar} with this {@code
 221.476 +     * TimeZone} and the time stamp, and call {@link Calendar#get(int)
 221.477 +     * Calendar.get}{@code (}{@link Calendar#DST_OFFSET}{@code )}.
 221.478 +     *
 221.479 +     * @return the amount of saving time in milliseconds
 221.480 +     * @since 1.4
 221.481 +     * @see #inDaylightTime(Date)
 221.482 +     * @see #getOffset(long)
 221.483 +     * @see #getOffset(int,int,int,int,int,int)
 221.484 +     * @see Calendar#ZONE_OFFSET
 221.485 +     */
 221.486 +    public int getDSTSavings() {
 221.487 +        if (useDaylightTime()) {
 221.488 +            return 3600000;
 221.489 +        }
 221.490 +        return 0;
 221.491 +    }
 221.492 +
 221.493 +    /**
 221.494 +     * Queries if this {@code TimeZone} uses Daylight Saving Time.
 221.495 +     *
 221.496 +     * <p>If an underlying {@code TimeZone} implementation subclass
 221.497 +     * supports historical and future Daylight Saving Time schedule
 221.498 +     * changes, this method refers to the last known Daylight Saving Time
 221.499 +     * rule that can be a future prediction and may not be the same as
 221.500 +     * the current rule. Consider calling {@link #observesDaylightTime()}
 221.501 +     * if the current rule should also be taken into account.
 221.502 +     *
 221.503 +     * @return {@code true} if this {@code TimeZone} uses Daylight Saving Time,
 221.504 +     *         {@code false}, otherwise.
 221.505 +     * @see #inDaylightTime(Date)
 221.506 +     * @see Calendar#DST_OFFSET
 221.507 +     */
 221.508 +    public abstract boolean useDaylightTime();
 221.509 +
 221.510 +    /**
 221.511 +     * Returns {@code true} if this {@code TimeZone} is currently in
 221.512 +     * Daylight Saving Time, or if a transition from Standard Time to
 221.513 +     * Daylight Saving Time occurs at any future time.
 221.514 +     *
 221.515 +     * <p>The default implementation returns {@code true} if
 221.516 +     * {@code useDaylightTime()} or {@code inDaylightTime(new Date())}
 221.517 +     * returns {@code true}.
 221.518 +     *
 221.519 +     * @return {@code true} if this {@code TimeZone} is currently in
 221.520 +     * Daylight Saving Time, or if a transition from Standard Time to
 221.521 +     * Daylight Saving Time occurs at any future time; {@code false}
 221.522 +     * otherwise.
 221.523 +     * @since 1.7
 221.524 +     * @see #useDaylightTime()
 221.525 +     * @see #inDaylightTime(Date)
 221.526 +     * @see Calendar#DST_OFFSET
 221.527 +     */
 221.528 +    public boolean observesDaylightTime() {
 221.529 +        return useDaylightTime() || inDaylightTime(new Date());
 221.530 +    }
 221.531 +
 221.532 +    /**
 221.533 +     * Queries if the given {@code date} is in Daylight Saving Time in
 221.534 +     * this time zone.
 221.535 +     *
 221.536 +     * @param date the given Date.
 221.537 +     * @return {@code true} if the given date is in Daylight Saving Time,
 221.538 +     *         {@code false}, otherwise.
 221.539 +     */
 221.540 +    abstract public boolean inDaylightTime(Date date);
 221.541 +
 221.542 +    /**
 221.543 +     * Gets the <code>TimeZone</code> for the given ID.
 221.544 +     *
 221.545 +     * @param ID the ID for a <code>TimeZone</code>, either an abbreviation
 221.546 +     * such as "PST", a full name such as "America/Los_Angeles", or a custom
 221.547 +     * ID such as "GMT-8:00". Note that the support of abbreviations is
 221.548 +     * for JDK 1.1.x compatibility only and full names should be used.
 221.549 +     *
 221.550 +     * @return the specified <code>TimeZone</code>, or the GMT zone if the given ID
 221.551 +     * cannot be understood.
 221.552 +     */
 221.553 +    public static synchronized TimeZone getTimeZone(String ID) {
 221.554 +        return getTimeZone(ID, true);
 221.555 +    }
 221.556 +
 221.557 +    private static TimeZone getTimeZone(String ID, boolean fallback) {
 221.558 +//        TimeZone tz = ZoneInfo.getTimeZone(ID);
 221.559 +//        if (tz == null) {
 221.560 +//            tz = parseCustomTimeZone(ID);
 221.561 +//            if (tz == null && fallback) {
 221.562 +//                tz = new ZoneInfo(GMT_ID, 0);
 221.563 +//            }
 221.564 +//        }
 221.565 +//        return tz;
 221.566 +        return TimeZone.NO_TIMEZONE;
 221.567 +    }
 221.568 +
 221.569 +    /**
 221.570 +     * Gets the available IDs according to the given time zone offset in milliseconds.
 221.571 +     *
 221.572 +     * @param rawOffset the given time zone GMT offset in milliseconds.
 221.573 +     * @return an array of IDs, where the time zone for that ID has
 221.574 +     * the specified GMT offset. For example, "America/Phoenix" and "America/Denver"
 221.575 +     * both have GMT-07:00, but differ in daylight saving behavior.
 221.576 +     * @see #getRawOffset()
 221.577 +     */
 221.578 +    public static synchronized String[] getAvailableIDs(int rawOffset) {
 221.579 +        return new String[0];//ZoneInfo.getAvailableIDs(rawOffset);
 221.580 +    }
 221.581 +
 221.582 +    /**
 221.583 +     * Gets all the available IDs supported.
 221.584 +     * @return an array of IDs.
 221.585 +     */
 221.586 +    public static synchronized String[] getAvailableIDs() {
 221.587 +        return new String[0];//return ZoneInfo.getAvailableIDs();
 221.588 +    }
 221.589 +
 221.590 +    /**
 221.591 +     * Gets the platform defined TimeZone ID.
 221.592 +     **/
 221.593 +    private static native String getSystemTimeZoneID(String javaHome,
 221.594 +                                                     String country);
 221.595 +
 221.596 +    /**
 221.597 +     * Gets the custom time zone ID based on the GMT offset of the
 221.598 +     * platform. (e.g., "GMT+08:00")
 221.599 +     */
 221.600 +    private static native String getSystemGMTOffsetID();
 221.601 +
 221.602 +    /**
 221.603 +     * Gets the default <code>TimeZone</code> for this host.
 221.604 +     * The source of the default <code>TimeZone</code>
 221.605 +     * may vary with implementation.
 221.606 +     * @return a default <code>TimeZone</code>.
 221.607 +     * @see #setDefault
 221.608 +     */
 221.609 +    public static TimeZone getDefault() {
 221.610 +        return (TimeZone) getDefaultRef().clone();
 221.611 +    }
 221.612 +
 221.613 +    /**
 221.614 +     * Returns the reference to the default TimeZone object. This
 221.615 +     * method doesn't create a clone.
 221.616 +     */
 221.617 +    static TimeZone getDefaultRef() {
 221.618 +        TimeZone defaultZone = null;//defaultZoneTL.get();
 221.619 +        if (defaultZone == null) {
 221.620 +            defaultZone = defaultTimeZone;
 221.621 +            if (defaultZone == null) {
 221.622 +                // Need to initialize the default time zone.
 221.623 +                defaultZone = TimeZone.NO_TIMEZONE;
 221.624 +                assert defaultZone != null;
 221.625 +            }
 221.626 +        }
 221.627 +        // Don't clone here.
 221.628 +        return defaultZone;
 221.629 +    }
 221.630 +
 221.631 +    private static boolean hasPermission() {
 221.632 +        boolean hasPermission = false;
 221.633 +        return hasPermission;
 221.634 +    }
 221.635 +
 221.636 +    /**
 221.637 +     * Sets the <code>TimeZone</code> that is
 221.638 +     * returned by the <code>getDefault</code> method.  If <code>zone</code>
 221.639 +     * is null, reset the default to the value it had originally when the
 221.640 +     * VM first started.
 221.641 +     * @param zone the new default time zone
 221.642 +     * @see #getDefault
 221.643 +     */
 221.644 +    public static void setDefault(TimeZone zone)
 221.645 +    {
 221.646 +        if (hasPermission()) {
 221.647 +            synchronized (TimeZone.class) {
 221.648 +                defaultTimeZone = zone;
 221.649 +              //  defaultZoneTL.set(null);
 221.650 +            }
 221.651 +        } else {
 221.652 +            //defaultZoneTL.set(zone);
 221.653 +        }
 221.654 +    }
 221.655 +
 221.656 +    /**
 221.657 +     * Returns true if this zone has the same rule and offset as another zone.
 221.658 +     * That is, if this zone differs only in ID, if at all.  Returns false
 221.659 +     * if the other zone is null.
 221.660 +     * @param other the <code>TimeZone</code> object to be compared with
 221.661 +     * @return true if the other zone is not null and is the same as this one,
 221.662 +     * with the possible exception of the ID
 221.663 +     * @since 1.2
 221.664 +     */
 221.665 +    public boolean hasSameRules(TimeZone other) {
 221.666 +        return other != null && getRawOffset() == other.getRawOffset() &&
 221.667 +            useDaylightTime() == other.useDaylightTime();
 221.668 +    }
 221.669 +
 221.670 +    /**
 221.671 +     * Creates a copy of this <code>TimeZone</code>.
 221.672 +     *
 221.673 +     * @return a clone of this <code>TimeZone</code>
 221.674 +     */
 221.675 +    public Object clone()
 221.676 +    {
 221.677 +        try {
 221.678 +            TimeZone other = (TimeZone) super.clone();
 221.679 +            other.ID = ID;
 221.680 +            return other;
 221.681 +        } catch (CloneNotSupportedException e) {
 221.682 +            throw new InternalError();
 221.683 +        }
 221.684 +    }
 221.685 +
 221.686 +    /**
 221.687 +     * The null constant as a TimeZone.
 221.688 +     */
 221.689 +    static final TimeZone NO_TIMEZONE = null;
 221.690 +
 221.691 +    // =======================privates===============================
 221.692 +
 221.693 +    /**
 221.694 +     * The string identifier of this <code>TimeZone</code>.  This is a
 221.695 +     * programmatic identifier used internally to look up <code>TimeZone</code>
 221.696 +     * objects from the system table and also to map them to their localized
 221.697 +     * display names.  <code>ID</code> values are unique in the system
 221.698 +     * table but may not be for dynamically created zones.
 221.699 +     * @serial
 221.700 +     */
 221.701 +    private String           ID;
 221.702 +    private static volatile TimeZone defaultTimeZone;
 221.703 +
 221.704 +    static final String         GMT_ID        = "GMT";
 221.705 +    private static final int    GMT_ID_LENGTH = 3;
 221.706 +
 221.707 +    /**
 221.708 +     * Parses a custom time zone identifier and returns a corresponding zone.
 221.709 +     * This method doesn't support the RFC 822 time zone format. (e.g., +hhmm)
 221.710 +     *
 221.711 +     * @param id a string of the <a href="#CustomID">custom ID form</a>.
 221.712 +     * @return a newly created TimeZone with the given offset and
 221.713 +     * no daylight saving time, or null if the id cannot be parsed.
 221.714 +     */
 221.715 +    private static final TimeZone parseCustomTimeZone(String id) {
 221.716 +        return null;
 221.717 +    }
 221.718 +}
   222.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   222.2 +++ b/rt/emul/compact/src/main/java/java/util/Timer.java	Wed Apr 30 15:04:10 2014 +0200
   222.3 @@ -0,0 +1,731 @@
   222.4 +/*
   222.5 + * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
   222.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   222.7 + *
   222.8 + * This code is free software; you can redistribute it and/or modify it
   222.9 + * under the terms of the GNU General Public License version 2 only, as
  222.10 + * published by the Free Software Foundation.  Oracle designates this
  222.11 + * particular file as subject to the "Classpath" exception as provided
  222.12 + * by Oracle in the LICENSE file that accompanied this code.
  222.13 + *
  222.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  222.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  222.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  222.17 + * version 2 for more details (a copy is included in the LICENSE file that
  222.18 + * accompanied this code).
  222.19 + *
  222.20 + * You should have received a copy of the GNU General Public License version
  222.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  222.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  222.23 + *
  222.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  222.25 + * or visit www.oracle.com if you need additional information or have any
  222.26 + * questions.
  222.27 + */
  222.28 +
  222.29 +package java.util;
  222.30 +import java.util.Date;
  222.31 +import java.util.concurrent.atomic.AtomicInteger;
  222.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  222.33 +
  222.34 +/**
  222.35 + * A facility for threads to schedule tasks for future execution in a
  222.36 + * background thread.  Tasks may be scheduled for one-time execution, or for
  222.37 + * repeated execution at regular intervals.
  222.38 + *
  222.39 + * <p>Corresponding to each <tt>Timer</tt> object is a single background
  222.40 + * thread that is used to execute all of the timer's tasks, sequentially.
  222.41 + * Timer tasks should complete quickly.  If a timer task takes excessive time
  222.42 + * to complete, it "hogs" the timer's task execution thread.  This can, in
  222.43 + * turn, delay the execution of subsequent tasks, which may "bunch up" and
  222.44 + * execute in rapid succession when (and if) the offending task finally
  222.45 + * completes.
  222.46 + *
  222.47 + * <p>After the last live reference to a <tt>Timer</tt> object goes away
  222.48 + * <i>and</i> all outstanding tasks have completed execution, the timer's task
  222.49 + * execution thread terminates gracefully (and becomes subject to garbage
  222.50 + * collection).  However, this can take arbitrarily long to occur.  By
  222.51 + * default, the task execution thread does not run as a <i>daemon thread</i>,
  222.52 + * so it is capable of keeping an application from terminating.  If a caller
  222.53 + * wants to terminate a timer's task execution thread rapidly, the caller
  222.54 + * should invoke the timer's <tt>cancel</tt> method.
  222.55 + *
  222.56 + * <p>If the timer's task execution thread terminates unexpectedly, for
  222.57 + * example, because its <tt>stop</tt> method is invoked, any further
  222.58 + * attempt to schedule a task on the timer will result in an
  222.59 + * <tt>IllegalStateException</tt>, as if the timer's <tt>cancel</tt>
  222.60 + * method had been invoked.
  222.61 + *
  222.62 + * <p>This class is thread-safe: multiple threads can share a single
  222.63 + * <tt>Timer</tt> object without the need for external synchronization.
  222.64 + *
  222.65 + * <p>This class does <i>not</i> offer real-time guarantees: it schedules
  222.66 + * tasks using the <tt>Object.wait(long)</tt> method.
  222.67 + *
  222.68 + * <p>Java 5.0 introduced the {@code java.util.concurrent} package and
  222.69 + * one of the concurrency utilities therein is the {@link
  222.70 + * java.util.concurrent.ScheduledThreadPoolExecutor
  222.71 + * ScheduledThreadPoolExecutor} which is a thread pool for repeatedly
  222.72 + * executing tasks at a given rate or delay.  It is effectively a more
  222.73 + * versatile replacement for the {@code Timer}/{@code TimerTask}
  222.74 + * combination, as it allows multiple service threads, accepts various
  222.75 + * time units, and doesn't require subclassing {@code TimerTask} (just
  222.76 + * implement {@code Runnable}).  Configuring {@code
  222.77 + * ScheduledThreadPoolExecutor} with one thread makes it equivalent to
  222.78 + * {@code Timer}.
  222.79 + *
  222.80 + * <p>Implementation note: This class scales to large numbers of concurrently
  222.81 + * scheduled tasks (thousands should present no problem).  Internally,
  222.82 + * it uses a binary heap to represent its task queue, so the cost to schedule
  222.83 + * a task is O(log n), where n is the number of concurrently scheduled tasks.
  222.84 + *
  222.85 + * <p>Implementation note: All constructors start a timer thread.
  222.86 + *
  222.87 + * @author  Josh Bloch
  222.88 + * @see     TimerTask
  222.89 + * @see     Object#wait(long)
  222.90 + * @since   1.3
  222.91 + */
  222.92 +
  222.93 +public class Timer {
  222.94 +    /**
  222.95 +     * The timer task queue.  This data structure is shared with the timer
  222.96 +     * thread.  The timer produces tasks, via its various schedule calls,
  222.97 +     * and the timer thread consumes, executing timer tasks as appropriate,
  222.98 +     * and removing them from the queue when they're obsolete.
  222.99 +     */
 222.100 +    private final TaskQueue queue = new TaskQueue();
 222.101 +
 222.102 +    /**
 222.103 +     * The timer thread.
 222.104 +     */
 222.105 +    private final TimerThread thread = new TimerThread(queue);
 222.106 +
 222.107 +    /**
 222.108 +     * This object causes the timer's task execution thread to exit
 222.109 +     * gracefully when there are no live references to the Timer object and no
 222.110 +     * tasks in the timer queue.  It is used in preference to a finalizer on
 222.111 +     * Timer as such a finalizer would be susceptible to a subclass's
 222.112 +     * finalizer forgetting to call it.
 222.113 +     */
 222.114 +    private final Object threadReaper = new Object() {
 222.115 +        protected void finalize() throws Throwable {
 222.116 +            synchronized(queue) {
 222.117 +                thread.newTasksMayBeScheduled = false;
 222.118 +                thread.notifyQueue(1); // In case queue is empty.
 222.119 +            }
 222.120 +        }
 222.121 +    };
 222.122 +
 222.123 +    /**
 222.124 +     * This ID is used to generate thread names.
 222.125 +     */
 222.126 +    private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);
 222.127 +    private static int serialNumber() {
 222.128 +        return nextSerialNumber.getAndIncrement();
 222.129 +    }
 222.130 +
 222.131 +    /**
 222.132 +     * Creates a new timer.  The associated thread does <i>not</i>
 222.133 +     * {@linkplain Thread#setDaemon run as a daemon}.
 222.134 +     */
 222.135 +    public Timer() {
 222.136 +        this("Timer-" + serialNumber());
 222.137 +    }
 222.138 +
 222.139 +    /**
 222.140 +     * Creates a new timer whose associated thread may be specified to
 222.141 +     * {@linkplain Thread#setDaemon run as a daemon}.
 222.142 +     * A daemon thread is called for if the timer will be used to
 222.143 +     * schedule repeating "maintenance activities", which must be
 222.144 +     * performed as long as the application is running, but should not
 222.145 +     * prolong the lifetime of the application.
 222.146 +     *
 222.147 +     * @param isDaemon true if the associated thread should run as a daemon.
 222.148 +     */
 222.149 +    public Timer(boolean isDaemon) {
 222.150 +        this("Timer-" + serialNumber(), isDaemon);
 222.151 +    }
 222.152 +
 222.153 +    /**
 222.154 +     * Creates a new timer whose associated thread has the specified name.
 222.155 +     * The associated thread does <i>not</i>
 222.156 +     * {@linkplain Thread#setDaemon run as a daemon}.
 222.157 +     *
 222.158 +     * @param name the name of the associated thread
 222.159 +     * @throws NullPointerException if {@code name} is null
 222.160 +     * @since 1.5
 222.161 +     */
 222.162 +    public Timer(String name) {
 222.163 +    }
 222.164 +
 222.165 +    /**
 222.166 +     * Creates a new timer whose associated thread has the specified name,
 222.167 +     * and may be specified to
 222.168 +     * {@linkplain Thread#setDaemon run as a daemon}.
 222.169 +     *
 222.170 +     * @param name the name of the associated thread
 222.171 +     * @param isDaemon true if the associated thread should run as a daemon
 222.172 +     * @throws NullPointerException if {@code name} is null
 222.173 +     * @since 1.5
 222.174 +     */
 222.175 +    public Timer(String name, boolean isDaemon) {
 222.176 +    }
 222.177 +
 222.178 +    /**
 222.179 +     * Schedules the specified task for execution after the specified delay.
 222.180 +     *
 222.181 +     * @param task  task to be scheduled.
 222.182 +     * @param delay delay in milliseconds before task is to be executed.
 222.183 +     * @throws IllegalArgumentException if <tt>delay</tt> is negative, or
 222.184 +     *         <tt>delay + System.currentTimeMillis()</tt> is negative.
 222.185 +     * @throws IllegalStateException if task was already scheduled or
 222.186 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.187 +     * @throws NullPointerException if {@code task} is null
 222.188 +     */
 222.189 +    public void schedule(TimerTask task, long delay) {
 222.190 +        if (delay < 0)
 222.191 +            throw new IllegalArgumentException("Negative delay.");
 222.192 +        sched(task, System.currentTimeMillis()+delay, 0);
 222.193 +    }
 222.194 +
 222.195 +    /**
 222.196 +     * Schedules the specified task for execution at the specified time.  If
 222.197 +     * the time is in the past, the task is scheduled for immediate execution.
 222.198 +     *
 222.199 +     * @param task task to be scheduled.
 222.200 +     * @param time time at which task is to be executed.
 222.201 +     * @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
 222.202 +     * @throws IllegalStateException if task was already scheduled or
 222.203 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.204 +     * @throws NullPointerException if {@code task} or {@code time} is null
 222.205 +     */
 222.206 +    public void schedule(TimerTask task, Date time) {
 222.207 +        sched(task, time.getTime(), 0);
 222.208 +    }
 222.209 +
 222.210 +    /**
 222.211 +     * Schedules the specified task for repeated <i>fixed-delay execution</i>,
 222.212 +     * beginning after the specified delay.  Subsequent executions take place
 222.213 +     * at approximately regular intervals separated by the specified period.
 222.214 +     *
 222.215 +     * <p>In fixed-delay execution, each execution is scheduled relative to
 222.216 +     * the actual execution time of the previous execution.  If an execution
 222.217 +     * is delayed for any reason (such as garbage collection or other
 222.218 +     * background activity), subsequent executions will be delayed as well.
 222.219 +     * In the long run, the frequency of execution will generally be slightly
 222.220 +     * lower than the reciprocal of the specified period (assuming the system
 222.221 +     * clock underlying <tt>Object.wait(long)</tt> is accurate).
 222.222 +     *
 222.223 +     * <p>Fixed-delay execution is appropriate for recurring activities
 222.224 +     * that require "smoothness."  In other words, it is appropriate for
 222.225 +     * activities where it is more important to keep the frequency accurate
 222.226 +     * in the short run than in the long run.  This includes most animation
 222.227 +     * tasks, such as blinking a cursor at regular intervals.  It also includes
 222.228 +     * tasks wherein regular activity is performed in response to human
 222.229 +     * input, such as automatically repeating a character as long as a key
 222.230 +     * is held down.
 222.231 +     *
 222.232 +     * @param task   task to be scheduled.
 222.233 +     * @param delay  delay in milliseconds before task is to be executed.
 222.234 +     * @param period time in milliseconds between successive task executions.
 222.235 +     * @throws IllegalArgumentException if {@code delay < 0}, or
 222.236 +     *         {@code delay + System.currentTimeMillis() < 0}, or
 222.237 +     *         {@code period <= 0}
 222.238 +     * @throws IllegalStateException if task was already scheduled or
 222.239 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.240 +     * @throws NullPointerException if {@code task} is null
 222.241 +     */
 222.242 +    public void schedule(TimerTask task, long delay, long period) {
 222.243 +        if (delay < 0)
 222.244 +            throw new IllegalArgumentException("Negative delay.");
 222.245 +        if (period <= 0)
 222.246 +            throw new IllegalArgumentException("Non-positive period.");
 222.247 +        sched(task, System.currentTimeMillis()+delay, -period);
 222.248 +    }
 222.249 +
 222.250 +    /**
 222.251 +     * Schedules the specified task for repeated <i>fixed-delay execution</i>,
 222.252 +     * beginning at the specified time. Subsequent executions take place at
 222.253 +     * approximately regular intervals, separated by the specified period.
 222.254 +     *
 222.255 +     * <p>In fixed-delay execution, each execution is scheduled relative to
 222.256 +     * the actual execution time of the previous execution.  If an execution
 222.257 +     * is delayed for any reason (such as garbage collection or other
 222.258 +     * background activity), subsequent executions will be delayed as well.
 222.259 +     * In the long run, the frequency of execution will generally be slightly
 222.260 +     * lower than the reciprocal of the specified period (assuming the system
 222.261 +     * clock underlying <tt>Object.wait(long)</tt> is accurate).  As a
 222.262 +     * consequence of the above, if the scheduled first time is in the past,
 222.263 +     * it is scheduled for immediate execution.
 222.264 +     *
 222.265 +     * <p>Fixed-delay execution is appropriate for recurring activities
 222.266 +     * that require "smoothness."  In other words, it is appropriate for
 222.267 +     * activities where it is more important to keep the frequency accurate
 222.268 +     * in the short run than in the long run.  This includes most animation
 222.269 +     * tasks, such as blinking a cursor at regular intervals.  It also includes
 222.270 +     * tasks wherein regular activity is performed in response to human
 222.271 +     * input, such as automatically repeating a character as long as a key
 222.272 +     * is held down.
 222.273 +     *
 222.274 +     * @param task   task to be scheduled.
 222.275 +     * @param firstTime First time at which task is to be executed.
 222.276 +     * @param period time in milliseconds between successive task executions.
 222.277 +     * @throws IllegalArgumentException if {@code firstTime.getTime() < 0}, or
 222.278 +     *         {@code period <= 0}
 222.279 +     * @throws IllegalStateException if task was already scheduled or
 222.280 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.281 +     * @throws NullPointerException if {@code task} or {@code firstTime} is null
 222.282 +     */
 222.283 +    public void schedule(TimerTask task, Date firstTime, long period) {
 222.284 +        if (period <= 0)
 222.285 +            throw new IllegalArgumentException("Non-positive period.");
 222.286 +        sched(task, firstTime.getTime(), -period);
 222.287 +    }
 222.288 +
 222.289 +    /**
 222.290 +     * Schedules the specified task for repeated <i>fixed-rate execution</i>,
 222.291 +     * beginning after the specified delay.  Subsequent executions take place
 222.292 +     * at approximately regular intervals, separated by the specified period.
 222.293 +     *
 222.294 +     * <p>In fixed-rate execution, each execution is scheduled relative to the
 222.295 +     * scheduled execution time of the initial execution.  If an execution is
 222.296 +     * delayed for any reason (such as garbage collection or other background
 222.297 +     * activity), two or more executions will occur in rapid succession to
 222.298 +     * "catch up."  In the long run, the frequency of execution will be
 222.299 +     * exactly the reciprocal of the specified period (assuming the system
 222.300 +     * clock underlying <tt>Object.wait(long)</tt> is accurate).
 222.301 +     *
 222.302 +     * <p>Fixed-rate execution is appropriate for recurring activities that
 222.303 +     * are sensitive to <i>absolute</i> time, such as ringing a chime every
 222.304 +     * hour on the hour, or running scheduled maintenance every day at a
 222.305 +     * particular time.  It is also appropriate for recurring activities
 222.306 +     * where the total time to perform a fixed number of executions is
 222.307 +     * important, such as a countdown timer that ticks once every second for
 222.308 +     * ten seconds.  Finally, fixed-rate execution is appropriate for
 222.309 +     * scheduling multiple repeating timer tasks that must remain synchronized
 222.310 +     * with respect to one another.
 222.311 +     *
 222.312 +     * @param task   task to be scheduled.
 222.313 +     * @param delay  delay in milliseconds before task is to be executed.
 222.314 +     * @param period time in milliseconds between successive task executions.
 222.315 +     * @throws IllegalArgumentException if {@code delay < 0}, or
 222.316 +     *         {@code delay + System.currentTimeMillis() < 0}, or
 222.317 +     *         {@code period <= 0}
 222.318 +     * @throws IllegalStateException if task was already scheduled or
 222.319 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.320 +     * @throws NullPointerException if {@code task} is null
 222.321 +     */
 222.322 +    public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
 222.323 +        if (delay < 0)
 222.324 +            throw new IllegalArgumentException("Negative delay.");
 222.325 +        if (period <= 0)
 222.326 +            throw new IllegalArgumentException("Non-positive period.");
 222.327 +        sched(task, System.currentTimeMillis()+delay, period);
 222.328 +    }
 222.329 +
 222.330 +    /**
 222.331 +     * Schedules the specified task for repeated <i>fixed-rate execution</i>,
 222.332 +     * beginning at the specified time. Subsequent executions take place at
 222.333 +     * approximately regular intervals, separated by the specified period.
 222.334 +     *
 222.335 +     * <p>In fixed-rate execution, each execution is scheduled relative to the
 222.336 +     * scheduled execution time of the initial execution.  If an execution is
 222.337 +     * delayed for any reason (such as garbage collection or other background
 222.338 +     * activity), two or more executions will occur in rapid succession to
 222.339 +     * "catch up."  In the long run, the frequency of execution will be
 222.340 +     * exactly the reciprocal of the specified period (assuming the system
 222.341 +     * clock underlying <tt>Object.wait(long)</tt> is accurate).  As a
 222.342 +     * consequence of the above, if the scheduled first time is in the past,
 222.343 +     * then any "missed" executions will be scheduled for immediate "catch up"
 222.344 +     * execution.
 222.345 +     *
 222.346 +     * <p>Fixed-rate execution is appropriate for recurring activities that
 222.347 +     * are sensitive to <i>absolute</i> time, such as ringing a chime every
 222.348 +     * hour on the hour, or running scheduled maintenance every day at a
 222.349 +     * particular time.  It is also appropriate for recurring activities
 222.350 +     * where the total time to perform a fixed number of executions is
 222.351 +     * important, such as a countdown timer that ticks once every second for
 222.352 +     * ten seconds.  Finally, fixed-rate execution is appropriate for
 222.353 +     * scheduling multiple repeating timer tasks that must remain synchronized
 222.354 +     * with respect to one another.
 222.355 +     *
 222.356 +     * @param task   task to be scheduled.
 222.357 +     * @param firstTime First time at which task is to be executed.
 222.358 +     * @param period time in milliseconds between successive task executions.
 222.359 +     * @throws IllegalArgumentException if {@code firstTime.getTime() < 0} or
 222.360 +     *         {@code period <= 0}
 222.361 +     * @throws IllegalStateException if task was already scheduled or
 222.362 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.363 +     * @throws NullPointerException if {@code task} or {@code firstTime} is null
 222.364 +     */
 222.365 +    public void scheduleAtFixedRate(TimerTask task, Date firstTime,
 222.366 +                                    long period) {
 222.367 +        if (period <= 0)
 222.368 +            throw new IllegalArgumentException("Non-positive period.");
 222.369 +        sched(task, firstTime.getTime(), period);
 222.370 +    }
 222.371 +
 222.372 +    /**
 222.373 +     * Schedule the specified timer task for execution at the specified
 222.374 +     * time with the specified period, in milliseconds.  If period is
 222.375 +     * positive, the task is scheduled for repeated execution; if period is
 222.376 +     * zero, the task is scheduled for one-time execution. Time is specified
 222.377 +     * in Date.getTime() format.  This method checks timer state, task state,
 222.378 +     * and initial execution time, but not period.
 222.379 +     *
 222.380 +     * @throws IllegalArgumentException if <tt>time</tt> is negative.
 222.381 +     * @throws IllegalStateException if task was already scheduled or
 222.382 +     *         cancelled, timer was cancelled, or timer thread terminated.
 222.383 +     * @throws NullPointerException if {@code task} is null
 222.384 +     */
 222.385 +    private void sched(TimerTask task, long time, long period) {
 222.386 +        if (time < 0)
 222.387 +            throw new IllegalArgumentException("Illegal execution time.");
 222.388 +
 222.389 +        // Constrain value of period sufficiently to prevent numeric
 222.390 +        // overflow while still being effectively infinitely large.
 222.391 +        if (Math.abs(period) > (Long.MAX_VALUE >> 1))
 222.392 +            period >>= 1;
 222.393 +
 222.394 +        synchronized(queue) {
 222.395 +            if (!thread.newTasksMayBeScheduled)
 222.396 +                throw new IllegalStateException("Timer already cancelled.");
 222.397 +
 222.398 +            synchronized(task.lock) {
 222.399 +                if (task.state != TimerTask.VIRGIN)
 222.400 +                    throw new IllegalStateException(
 222.401 +                        "Task already scheduled or cancelled");
 222.402 +                task.nextExecutionTime = time;
 222.403 +                task.period = period;
 222.404 +                task.state = TimerTask.SCHEDULED;
 222.405 +            }
 222.406 +
 222.407 +            queue.add(task);
 222.408 +            if (queue.getMin() == task)
 222.409 +                thread.notifyQueue(1);
 222.410 +        }
 222.411 +    }
 222.412 +
 222.413 +    /**
 222.414 +     * Terminates this timer, discarding any currently scheduled tasks.
 222.415 +     * Does not interfere with a currently executing task (if it exists).
 222.416 +     * Once a timer has been terminated, its execution thread terminates
 222.417 +     * gracefully, and no more tasks may be scheduled on it.
 222.418 +     *
 222.419 +     * <p>Note that calling this method from within the run method of a
 222.420 +     * timer task that was invoked by this timer absolutely guarantees that
 222.421 +     * the ongoing task execution is the last task execution that will ever
 222.422 +     * be performed by this timer.
 222.423 +     *
 222.424 +     * <p>This method may be called repeatedly; the second and subsequent
 222.425 +     * calls have no effect.
 222.426 +     */
 222.427 +    public void cancel() {
 222.428 +        synchronized(queue) {
 222.429 +            thread.newTasksMayBeScheduled = false;
 222.430 +            queue.clear();
 222.431 +            thread.notifyQueue(1);  // In case queue was already empty.
 222.432 +        }
 222.433 +    }
 222.434 +    
 222.435 +    /**
 222.436 +     * Removes all cancelled tasks from this timer's task queue.  <i>Calling
 222.437 +     * this method has no effect on the behavior of the timer</i>, but
 222.438 +     * eliminates the references to the cancelled tasks from the queue.
 222.439 +     * If there are no external references to these tasks, they become
 222.440 +     * eligible for garbage collection.
 222.441 +     *
 222.442 +     * <p>Most programs will have no need to call this method.
 222.443 +     * It is designed for use by the rare application that cancels a large
 222.444 +     * number of tasks.  Calling this method trades time for space: the
 222.445 +     * runtime of the method may be proportional to n + c log n, where n
 222.446 +     * is the number of tasks in the queue and c is the number of cancelled
 222.447 +     * tasks.
 222.448 +     *
 222.449 +     * <p>Note that it is permissible to call this method from within a
 222.450 +     * a task scheduled on this timer.
 222.451 +     *
 222.452 +     * @return the number of tasks removed from the queue.
 222.453 +     * @since 1.5
 222.454 +     */
 222.455 +     public int purge() {
 222.456 +         int result = 0;
 222.457 +
 222.458 +         synchronized(queue) {
 222.459 +             for (int i = queue.size(); i > 0; i--) {
 222.460 +                 if (queue.get(i).state == TimerTask.CANCELLED) {
 222.461 +                     queue.quickRemove(i);
 222.462 +                     result++;
 222.463 +                 }
 222.464 +             }
 222.465 +
 222.466 +             if (result != 0)
 222.467 +                 queue.heapify();
 222.468 +         }
 222.469 +
 222.470 +         return result;
 222.471 +     }
 222.472 +}
 222.473 +
 222.474 +/**
 222.475 + * This "helper class" implements the timer's task execution thread, which
 222.476 + * waits for tasks on the timer queue, executions them when they fire,
 222.477 + * reschedules repeating tasks, and removes cancelled tasks and spent
 222.478 + * non-repeating tasks from the queue.
 222.479 + */
 222.480 +class TimerThread implements Runnable {
 222.481 +    /**
 222.482 +     * This flag is set to false by the reaper to inform us that there
 222.483 +     * are no more live references to our Timer object.  Once this flag
 222.484 +     * is true and there are no more tasks in our queue, there is no
 222.485 +     * work left for us to do, so we terminate gracefully.  Note that
 222.486 +     * this field is protected by queue's monitor!
 222.487 +     */
 222.488 +    boolean newTasksMayBeScheduled = true;
 222.489 +
 222.490 +    /**
 222.491 +     * Our Timer's queue.  We store this reference in preference to
 222.492 +     * a reference to the Timer so the reference graph remains acyclic.
 222.493 +     * Otherwise, the Timer would never be garbage-collected and this
 222.494 +     * thread would never go away.
 222.495 +     */
 222.496 +    private TaskQueue queue;
 222.497 +
 222.498 +    TimerThread(TaskQueue queue) {
 222.499 +        this.queue = queue;
 222.500 +    }
 222.501 +
 222.502 +    void notifyQueue(int delay) {
 222.503 +        if (delay < 1) {
 222.504 +            delay = 1;
 222.505 +        }
 222.506 +        setTimeout(delay, this);
 222.507 +    }
 222.508 +    
 222.509 +    @JavaScriptBody(args = { "delay", "r" }, body = "window.setTimeout(function() { r.run__V(); }, delay);")
 222.510 +    private static native void setTimeout(int delay, Runnable r);
 222.511 +    
 222.512 +    public void run() {
 222.513 +        mainLoop(1);
 222.514 +//        try {
 222.515 +//            mainLoop(0);
 222.516 +//        } finally {
 222.517 +//            // Someone killed this Thread, behave as if Timer cancelled
 222.518 +//            synchronized(queue) {
 222.519 +//                newTasksMayBeScheduled = false;
 222.520 +//                queue.clear();  // Eliminate obsolete references
 222.521 +//            }
 222.522 +//        }
 222.523 +    }
 222.524 +
 222.525 +    /**
 222.526 +     * The main timer loop.  (See class comment.)
 222.527 +     */
 222.528 +    private void mainLoop(int inc) {
 222.529 +        for (int i = 0; i < 1; i += inc) {
 222.530 +            try {
 222.531 +                TimerTask task;
 222.532 +                boolean taskFired;
 222.533 +                synchronized(queue) {
 222.534 +                    // Wait for queue to become non-empty
 222.535 +                    while (queue.isEmpty() && newTasksMayBeScheduled)
 222.536 +                        break;
 222.537 +                    if (queue.isEmpty())
 222.538 +                        break; // Queue is empty and will forever remain; die
 222.539 +
 222.540 +                    // Queue nonempty; look at first evt and do the right thing
 222.541 +                    long currentTime, executionTime;
 222.542 +                    task = queue.getMin();
 222.543 +                    synchronized(task.lock) {
 222.544 +                        if (task.state == TimerTask.CANCELLED) {
 222.545 +                            queue.removeMin();
 222.546 +                            continue;  // No action required, poll queue again
 222.547 +                        }
 222.548 +                        currentTime = System.currentTimeMillis();
 222.549 +                        executionTime = task.nextExecutionTime;
 222.550 +                        if (taskFired = (executionTime<=currentTime)) {
 222.551 +                            if (task.period == 0) { // Non-repeating, remove
 222.552 +                                queue.removeMin();
 222.553 +                                task.state = TimerTask.EXECUTED;
 222.554 +                            } else { // Repeating task, reschedule
 222.555 +                                queue.rescheduleMin(
 222.556 +                                  task.period<0 ? currentTime   - task.period
 222.557 +                                                : executionTime + task.period);
 222.558 +                            }
 222.559 +                        }
 222.560 +                    }
 222.561 +                    if (!taskFired) {
 222.562 +                        // Task hasn't yet fired; wait
 222.563 +                        notifyQueue((int)(executionTime - currentTime));
 222.564 +                        return;
 222.565 +                    }
 222.566 +                }
 222.567 +                if (taskFired)  // Task fired; run it, holding no locks
 222.568 +                    task.run();
 222.569 +            } catch(Exception e) {
 222.570 +                e.printStackTrace();
 222.571 +            }
 222.572 +        }
 222.573 +    }
 222.574 +}
 222.575 +
 222.576 +/**
 222.577 + * This class represents a timer task queue: a priority queue of TimerTasks,
 222.578 + * ordered on nextExecutionTime.  Each Timer object has one of these, which it
 222.579 + * shares with its TimerThread.  Internally this class uses a heap, which
 222.580 + * offers log(n) performance for the add, removeMin and rescheduleMin
 222.581 + * operations, and constant time performance for the getMin operation.
 222.582 + */
 222.583 +class TaskQueue {
 222.584 +    /**
 222.585 +     * Priority queue represented as a balanced binary heap: the two children
 222.586 +     * of queue[n] are queue[2*n] and queue[2*n+1].  The priority queue is
 222.587 +     * ordered on the nextExecutionTime field: The TimerTask with the lowest
 222.588 +     * nextExecutionTime is in queue[1] (assuming the queue is nonempty).  For
 222.589 +     * each node n in the heap, and each descendant of n, d,
 222.590 +     * n.nextExecutionTime <= d.nextExecutionTime.
 222.591 +     */
 222.592 +    private TimerTask[] queue = new TimerTask[128];
 222.593 +
 222.594 +    /**
 222.595 +     * The number of tasks in the priority queue.  (The tasks are stored in
 222.596 +     * queue[1] up to queue[size]).
 222.597 +     */
 222.598 +    private int size = 0;
 222.599 +
 222.600 +    /**
 222.601 +     * Returns the number of tasks currently on the queue.
 222.602 +     */
 222.603 +    int size() {
 222.604 +        return size;
 222.605 +    }
 222.606 +
 222.607 +    /**
 222.608 +     * Adds a new task to the priority queue.
 222.609 +     */
 222.610 +    void add(TimerTask task) {
 222.611 +        // Grow backing store if necessary
 222.612 +        if (size + 1 == queue.length)
 222.613 +            queue = Arrays.copyOf(queue, 2*queue.length);
 222.614 +
 222.615 +        queue[++size] = task;
 222.616 +        fixUp(size);
 222.617 +    }
 222.618 +
 222.619 +    /**
 222.620 +     * Return the "head task" of the priority queue.  (The head task is an
 222.621 +     * task with the lowest nextExecutionTime.)
 222.622 +     */
 222.623 +    TimerTask getMin() {
 222.624 +        return queue[1];
 222.625 +    }
 222.626 +
 222.627 +    /**
 222.628 +     * Return the ith task in the priority queue, where i ranges from 1 (the
 222.629 +     * head task, which is returned by getMin) to the number of tasks on the
 222.630 +     * queue, inclusive.
 222.631 +     */
 222.632 +    TimerTask get(int i) {
 222.633 +        return queue[i];
 222.634 +    }
 222.635 +
 222.636 +    /**
 222.637 +     * Remove the head task from the priority queue.
 222.638 +     */
 222.639 +    void removeMin() {
 222.640 +        queue[1] = queue[size];
 222.641 +        queue[size--] = null;  // Drop extra reference to prevent memory leak
 222.642 +        fixDown(1);
 222.643 +    }
 222.644 +
 222.645 +    /**
 222.646 +     * Removes the ith element from queue without regard for maintaining
 222.647 +     * the heap invariant.  Recall that queue is one-based, so
 222.648 +     * 1 <= i <= size.
 222.649 +     */
 222.650 +    void quickRemove(int i) {
 222.651 +        assert i <= size;
 222.652 +
 222.653 +        queue[i] = queue[size];
 222.654 +        queue[size--] = null;  // Drop extra ref to prevent memory leak
 222.655 +    }
 222.656 +
 222.657 +    /**
 222.658 +     * Sets the nextExecutionTime associated with the head task to the
 222.659 +     * specified value, and adjusts priority queue accordingly.
 222.660 +     */
 222.661 +    void rescheduleMin(long newTime) {
 222.662 +        queue[1].nextExecutionTime = newTime;
 222.663 +        fixDown(1);
 222.664 +    }
 222.665 +
 222.666 +    /**
 222.667 +     * Returns true if the priority queue contains no elements.
 222.668 +     */
 222.669 +    boolean isEmpty() {
 222.670 +        return size==0;
 222.671 +    }
 222.672 +
 222.673 +    /**
 222.674 +     * Removes all elements from the priority queue.
 222.675 +     */
 222.676 +    void clear() {
 222.677 +        // Null out task references to prevent memory leak
 222.678 +        for (int i=1; i<=size; i++)
 222.679 +            queue[i] = null;
 222.680 +
 222.681 +        size = 0;
 222.682 +    }
 222.683 +
 222.684 +    /**
 222.685 +     * Establishes the heap invariant (described above) assuming the heap
 222.686 +     * satisfies the invariant except possibly for the leaf-node indexed by k
 222.687 +     * (which may have a nextExecutionTime less than its parent's).
 222.688 +     *
 222.689 +     * This method functions by "promoting" queue[k] up the hierarchy
 222.690 +     * (by swapping it with its parent) repeatedly until queue[k]'s
 222.691 +     * nextExecutionTime is greater than or equal to that of its parent.
 222.692 +     */
 222.693 +    private void fixUp(int k) {
 222.694 +        while (k > 1) {
 222.695 +            int j = k >> 1;
 222.696 +            if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)
 222.697 +                break;
 222.698 +            TimerTask tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
 222.699 +            k = j;
 222.700 +        }
 222.701 +    }
 222.702 +
 222.703 +    /**
 222.704 +     * Establishes the heap invariant (described above) in the subtree
 222.705 +     * rooted at k, which is assumed to satisfy the heap invariant except
 222.706 +     * possibly for node k itself (which may have a nextExecutionTime greater
 222.707 +     * than its children's).
 222.708 +     *
 222.709 +     * This method functions by "demoting" queue[k] down the hierarchy
 222.710 +     * (by swapping it with its smaller child) repeatedly until queue[k]'s
 222.711 +     * nextExecutionTime is less than or equal to those of its children.
 222.712 +     */
 222.713 +    private void fixDown(int k) {
 222.714 +        int j;
 222.715 +        while ((j = k << 1) <= size && j > 0) {
 222.716 +            if (j < size &&
 222.717 +                queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)
 222.718 +                j++; // j indexes smallest kid
 222.719 +            if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)
 222.720 +                break;
 222.721 +            TimerTask tmp = queue[j];  queue[j] = queue[k]; queue[k] = tmp;
 222.722 +            k = j;
 222.723 +        }
 222.724 +    }
 222.725 +
 222.726 +    /**
 222.727 +     * Establishes the heap invariant (described above) in the entire tree,
 222.728 +     * assuming nothing about the order of the elements prior to the call.
 222.729 +     */
 222.730 +    void heapify() {
 222.731 +        for (int i = size/2; i >= 1; i--)
 222.732 +            fixDown(i);
 222.733 +    }
 222.734 +}
   223.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   223.2 +++ b/rt/emul/compact/src/main/java/java/util/TimerTask.java	Wed Apr 30 15:04:10 2014 +0200
   223.3 @@ -0,0 +1,158 @@
   223.4 +/*
   223.5 + * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
   223.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   223.7 + *
   223.8 + * This code is free software; you can redistribute it and/or modify it
   223.9 + * under the terms of the GNU General Public License version 2 only, as
  223.10 + * published by the Free Software Foundation.  Oracle designates this
  223.11 + * particular file as subject to the "Classpath" exception as provided
  223.12 + * by Oracle in the LICENSE file that accompanied this code.
  223.13 + *
  223.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  223.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  223.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  223.17 + * version 2 for more details (a copy is included in the LICENSE file that
  223.18 + * accompanied this code).
  223.19 + *
  223.20 + * You should have received a copy of the GNU General Public License version
  223.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  223.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  223.23 + *
  223.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  223.25 + * or visit www.oracle.com if you need additional information or have any
  223.26 + * questions.
  223.27 + */
  223.28 +
  223.29 +package java.util;
  223.30 +
  223.31 +/**
  223.32 + * A task that can be scheduled for one-time or repeated execution by a Timer.
  223.33 + *
  223.34 + * @author  Josh Bloch
  223.35 + * @see     Timer
  223.36 + * @since   1.3
  223.37 + */
  223.38 +
  223.39 +public abstract class TimerTask implements Runnable {
  223.40 +    /**
  223.41 +     * This object is used to control access to the TimerTask internals.
  223.42 +     */
  223.43 +    final Object lock = new Object();
  223.44 +
  223.45 +    /**
  223.46 +     * The state of this task, chosen from the constants below.
  223.47 +     */
  223.48 +    int state = VIRGIN;
  223.49 +
  223.50 +    /**
  223.51 +     * This task has not yet been scheduled.
  223.52 +     */
  223.53 +    static final int VIRGIN = 0;
  223.54 +
  223.55 +    /**
  223.56 +     * This task is scheduled for execution.  If it is a non-repeating task,
  223.57 +     * it has not yet been executed.
  223.58 +     */
  223.59 +    static final int SCHEDULED   = 1;
  223.60 +
  223.61 +    /**
  223.62 +     * This non-repeating task has already executed (or is currently
  223.63 +     * executing) and has not been cancelled.
  223.64 +     */
  223.65 +    static final int EXECUTED    = 2;
  223.66 +
  223.67 +    /**
  223.68 +     * This task has been cancelled (with a call to TimerTask.cancel).
  223.69 +     */
  223.70 +    static final int CANCELLED   = 3;
  223.71 +
  223.72 +    /**
  223.73 +     * Next execution time for this task in the format returned by
  223.74 +     * System.currentTimeMillis, assuming this task is scheduled for execution.
  223.75 +     * For repeating tasks, this field is updated prior to each task execution.
  223.76 +     */
  223.77 +    long nextExecutionTime;
  223.78 +
  223.79 +    /**
  223.80 +     * Period in milliseconds for repeating tasks.  A positive value indicates
  223.81 +     * fixed-rate execution.  A negative value indicates fixed-delay execution.
  223.82 +     * A value of 0 indicates a non-repeating task.
  223.83 +     */
  223.84 +    long period = 0;
  223.85 +
  223.86 +    /**
  223.87 +     * Creates a new timer task.
  223.88 +     */
  223.89 +    protected TimerTask() {
  223.90 +    }
  223.91 +
  223.92 +    /**
  223.93 +     * The action to be performed by this timer task.
  223.94 +     */
  223.95 +    public abstract void run();
  223.96 +
  223.97 +    /**
  223.98 +     * Cancels this timer task.  If the task has been scheduled for one-time
  223.99 +     * execution and has not yet run, or has not yet been scheduled, it will
 223.100 +     * never run.  If the task has been scheduled for repeated execution, it
 223.101 +     * will never run again.  (If the task is running when this call occurs,
 223.102 +     * the task will run to completion, but will never run again.)
 223.103 +     *
 223.104 +     * <p>Note that calling this method from within the <tt>run</tt> method of
 223.105 +     * a repeating timer task absolutely guarantees that the timer task will
 223.106 +     * not run again.
 223.107 +     *
 223.108 +     * <p>This method may be called repeatedly; the second and subsequent
 223.109 +     * calls have no effect.
 223.110 +     *
 223.111 +     * @return true if this task is scheduled for one-time execution and has
 223.112 +     *         not yet run, or this task is scheduled for repeated execution.
 223.113 +     *         Returns false if the task was scheduled for one-time execution
 223.114 +     *         and has already run, or if the task was never scheduled, or if
 223.115 +     *         the task was already cancelled.  (Loosely speaking, this method
 223.116 +     *         returns <tt>true</tt> if it prevents one or more scheduled
 223.117 +     *         executions from taking place.)
 223.118 +     */
 223.119 +    public boolean cancel() {
 223.120 +        synchronized(lock) {
 223.121 +            boolean result = (state == SCHEDULED);
 223.122 +            state = CANCELLED;
 223.123 +            return result;
 223.124 +        }
 223.125 +    }
 223.126 +
 223.127 +    /**
 223.128 +     * Returns the <i>scheduled</i> execution time of the most recent
 223.129 +     * <i>actual</i> execution of this task.  (If this method is invoked
 223.130 +     * while task execution is in progress, the return value is the scheduled
 223.131 +     * execution time of the ongoing task execution.)
 223.132 +     *
 223.133 +     * <p>This method is typically invoked from within a task's run method, to
 223.134 +     * determine whether the current execution of the task is sufficiently
 223.135 +     * timely to warrant performing the scheduled activity:
 223.136 +     * <pre>
 223.137 +     *   public void run() {
 223.138 +     *       if (System.currentTimeMillis() - scheduledExecutionTime() >=
 223.139 +     *           MAX_TARDINESS)
 223.140 +     *               return;  // Too late; skip this execution.
 223.141 +     *       // Perform the task
 223.142 +     *   }
 223.143 +     * </pre>
 223.144 +     * This method is typically <i>not</i> used in conjunction with
 223.145 +     * <i>fixed-delay execution</i> repeating tasks, as their scheduled
 223.146 +     * execution times are allowed to drift over time, and so are not terribly
 223.147 +     * significant.
 223.148 +     *
 223.149 +     * @return the time at which the most recent execution of this task was
 223.150 +     *         scheduled to occur, in the format returned by Date.getTime().
 223.151 +     *         The return value is undefined if the task has yet to commence
 223.152 +     *         its first execution.
 223.153 +     * @see Date#getTime()
 223.154 +     */
 223.155 +    public long scheduledExecutionTime() {
 223.156 +        synchronized(lock) {
 223.157 +            return (period < 0 ? nextExecutionTime + period
 223.158 +                               : nextExecutionTime - period);
 223.159 +        }
 223.160 +    }
 223.161 +}
   224.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   224.2 +++ b/rt/emul/compact/src/main/java/java/util/TreeMap.java	Wed Apr 30 15:04:10 2014 +0200
   224.3 @@ -0,0 +1,2442 @@
   224.4 +/*
   224.5 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   224.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   224.7 + *
   224.8 + * This code is free software; you can redistribute it and/or modify it
   224.9 + * under the terms of the GNU General Public License version 2 only, as
  224.10 + * published by the Free Software Foundation.  Oracle designates this
  224.11 + * particular file as subject to the "Classpath" exception as provided
  224.12 + * by Oracle in the LICENSE file that accompanied this code.
  224.13 + *
  224.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  224.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  224.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  224.17 + * version 2 for more details (a copy is included in the LICENSE file that
  224.18 + * accompanied this code).
  224.19 + *
  224.20 + * You should have received a copy of the GNU General Public License version
  224.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  224.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  224.23 + *
  224.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  224.25 + * or visit www.oracle.com if you need additional information or have any
  224.26 + * questions.
  224.27 + */
  224.28 +
  224.29 +package java.util;
  224.30 +
  224.31 +/**
  224.32 + * A Red-Black tree based {@link NavigableMap} implementation.
  224.33 + * The map is sorted according to the {@linkplain Comparable natural
  224.34 + * ordering} of its keys, or by a {@link Comparator} provided at map
  224.35 + * creation time, depending on which constructor is used.
  224.36 + *
  224.37 + * <p>This implementation provides guaranteed log(n) time cost for the
  224.38 + * {@code containsKey}, {@code get}, {@code put} and {@code remove}
  224.39 + * operations.  Algorithms are adaptations of those in Cormen, Leiserson, and
  224.40 + * Rivest's <em>Introduction to Algorithms</em>.
  224.41 + *
  224.42 + * <p>Note that the ordering maintained by a tree map, like any sorted map, and
  224.43 + * whether or not an explicit comparator is provided, must be <em>consistent
  224.44 + * with {@code equals}</em> if this sorted map is to correctly implement the
  224.45 + * {@code Map} interface.  (See {@code Comparable} or {@code Comparator} for a
  224.46 + * precise definition of <em>consistent with equals</em>.)  This is so because
  224.47 + * the {@code Map} interface is defined in terms of the {@code equals}
  224.48 + * operation, but a sorted map performs all key comparisons using its {@code
  224.49 + * compareTo} (or {@code compare}) method, so two keys that are deemed equal by
  224.50 + * this method are, from the standpoint of the sorted map, equal.  The behavior
  224.51 + * of a sorted map <em>is</em> well-defined even if its ordering is
  224.52 + * inconsistent with {@code equals}; it just fails to obey the general contract
  224.53 + * of the {@code Map} interface.
  224.54 + *
  224.55 + * <p><strong>Note that this implementation is not synchronized.</strong>
  224.56 + * If multiple threads access a map concurrently, and at least one of the
  224.57 + * threads modifies the map structurally, it <em>must</em> be synchronized
  224.58 + * externally.  (A structural modification is any operation that adds or
  224.59 + * deletes one or more mappings; merely changing the value associated
  224.60 + * with an existing key is not a structural modification.)  This is
  224.61 + * typically accomplished by synchronizing on some object that naturally
  224.62 + * encapsulates the map.
  224.63 + * If no such object exists, the map should be "wrapped" using the
  224.64 + * {@link Collections#synchronizedSortedMap Collections.synchronizedSortedMap}
  224.65 + * method.  This is best done at creation time, to prevent accidental
  224.66 + * unsynchronized access to the map: <pre>
  224.67 + *   SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));</pre>
  224.68 + *
  224.69 + * <p>The iterators returned by the {@code iterator} method of the collections
  224.70 + * returned by all of this class's "collection view methods" are
  224.71 + * <em>fail-fast</em>: if the map is structurally modified at any time after
  224.72 + * the iterator is created, in any way except through the iterator's own
  224.73 + * {@code remove} method, the iterator will throw a {@link
  224.74 + * ConcurrentModificationException}.  Thus, in the face of concurrent
  224.75 + * modification, the iterator fails quickly and cleanly, rather than risking
  224.76 + * arbitrary, non-deterministic behavior at an undetermined time in the future.
  224.77 + *
  224.78 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  224.79 + * as it is, generally speaking, impossible to make any hard guarantees in the
  224.80 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
  224.81 + * throw {@code ConcurrentModificationException} on a best-effort basis.
  224.82 + * Therefore, it would be wrong to write a program that depended on this
  224.83 + * exception for its correctness:   <em>the fail-fast behavior of iterators
  224.84 + * should be used only to detect bugs.</em>
  224.85 + *
  224.86 + * <p>All {@code Map.Entry} pairs returned by methods in this class
  224.87 + * and its views represent snapshots of mappings at the time they were
  224.88 + * produced. They do <strong>not</strong> support the {@code Entry.setValue}
  224.89 + * method. (Note however that it is possible to change mappings in the
  224.90 + * associated map using {@code put}.)
  224.91 + *
  224.92 + * <p>This class is a member of the
  224.93 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  224.94 + * Java Collections Framework</a>.
  224.95 + *
  224.96 + * @param <K> the type of keys maintained by this map
  224.97 + * @param <V> the type of mapped values
  224.98 + *
  224.99 + * @author  Josh Bloch and Doug Lea
 224.100 + * @see Map
 224.101 + * @see HashMap
 224.102 + * @see Hashtable
 224.103 + * @see Comparable
 224.104 + * @see Comparator
 224.105 + * @see Collection
 224.106 + * @since 1.2
 224.107 + */
 224.108 +
 224.109 +public class TreeMap<K,V>
 224.110 +    extends AbstractMap<K,V>
 224.111 +    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
 224.112 +{
 224.113 +    /**
 224.114 +     * The comparator used to maintain order in this tree map, or
 224.115 +     * null if it uses the natural ordering of its keys.
 224.116 +     *
 224.117 +     * @serial
 224.118 +     */
 224.119 +    private final Comparator<? super K> comparator;
 224.120 +
 224.121 +    private transient Entry<K,V> root = null;
 224.122 +
 224.123 +    /**
 224.124 +     * The number of entries in the tree
 224.125 +     */
 224.126 +    private transient int size = 0;
 224.127 +
 224.128 +    /**
 224.129 +     * The number of structural modifications to the tree.
 224.130 +     */
 224.131 +    private transient int modCount = 0;
 224.132 +
 224.133 +    /**
 224.134 +     * Constructs a new, empty tree map, using the natural ordering of its
 224.135 +     * keys.  All keys inserted into the map must implement the {@link
 224.136 +     * Comparable} interface.  Furthermore, all such keys must be
 224.137 +     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
 224.138 +     * a {@code ClassCastException} for any keys {@code k1} and
 224.139 +     * {@code k2} in the map.  If the user attempts to put a key into the
 224.140 +     * map that violates this constraint (for example, the user attempts to
 224.141 +     * put a string key into a map whose keys are integers), the
 224.142 +     * {@code put(Object key, Object value)} call will throw a
 224.143 +     * {@code ClassCastException}.
 224.144 +     */
 224.145 +    public TreeMap() {
 224.146 +        comparator = null;
 224.147 +    }
 224.148 +
 224.149 +    /**
 224.150 +     * Constructs a new, empty tree map, ordered according to the given
 224.151 +     * comparator.  All keys inserted into the map must be <em>mutually
 224.152 +     * comparable</em> by the given comparator: {@code comparator.compare(k1,
 224.153 +     * k2)} must not throw a {@code ClassCastException} for any keys
 224.154 +     * {@code k1} and {@code k2} in the map.  If the user attempts to put
 224.155 +     * a key into the map that violates this constraint, the {@code put(Object
 224.156 +     * key, Object value)} call will throw a
 224.157 +     * {@code ClassCastException}.
 224.158 +     *
 224.159 +     * @param comparator the comparator that will be used to order this map.
 224.160 +     *        If {@code null}, the {@linkplain Comparable natural
 224.161 +     *        ordering} of the keys will be used.
 224.162 +     */
 224.163 +    public TreeMap(Comparator<? super K> comparator) {
 224.164 +        this.comparator = comparator;
 224.165 +    }
 224.166 +
 224.167 +    /**
 224.168 +     * Constructs a new tree map containing the same mappings as the given
 224.169 +     * map, ordered according to the <em>natural ordering</em> of its keys.
 224.170 +     * All keys inserted into the new map must implement the {@link
 224.171 +     * Comparable} interface.  Furthermore, all such keys must be
 224.172 +     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
 224.173 +     * a {@code ClassCastException} for any keys {@code k1} and
 224.174 +     * {@code k2} in the map.  This method runs in n*log(n) time.
 224.175 +     *
 224.176 +     * @param  m the map whose mappings are to be placed in this map
 224.177 +     * @throws ClassCastException if the keys in m are not {@link Comparable},
 224.178 +     *         or are not mutually comparable
 224.179 +     * @throws NullPointerException if the specified map is null
 224.180 +     */
 224.181 +    public TreeMap(Map<? extends K, ? extends V> m) {
 224.182 +        comparator = null;
 224.183 +        putAll(m);
 224.184 +    }
 224.185 +
 224.186 +    /**
 224.187 +     * Constructs a new tree map containing the same mappings and
 224.188 +     * using the same ordering as the specified sorted map.  This
 224.189 +     * method runs in linear time.
 224.190 +     *
 224.191 +     * @param  m the sorted map whose mappings are to be placed in this map,
 224.192 +     *         and whose comparator is to be used to sort this map
 224.193 +     * @throws NullPointerException if the specified map is null
 224.194 +     */
 224.195 +    public TreeMap(SortedMap<K, ? extends V> m) {
 224.196 +        comparator = m.comparator();
 224.197 +        try {
 224.198 +            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
 224.199 +        } catch (java.io.IOException cannotHappen) {
 224.200 +        } catch (ClassNotFoundException cannotHappen) {
 224.201 +        }
 224.202 +    }
 224.203 +
 224.204 +
 224.205 +    // Query Operations
 224.206 +
 224.207 +    /**
 224.208 +     * Returns the number of key-value mappings in this map.
 224.209 +     *
 224.210 +     * @return the number of key-value mappings in this map
 224.211 +     */
 224.212 +    public int size() {
 224.213 +        return size;
 224.214 +    }
 224.215 +
 224.216 +    /**
 224.217 +     * Returns {@code true} if this map contains a mapping for the specified
 224.218 +     * key.
 224.219 +     *
 224.220 +     * @param key key whose presence in this map is to be tested
 224.221 +     * @return {@code true} if this map contains a mapping for the
 224.222 +     *         specified key
 224.223 +     * @throws ClassCastException if the specified key cannot be compared
 224.224 +     *         with the keys currently in the map
 224.225 +     * @throws NullPointerException if the specified key is null
 224.226 +     *         and this map uses natural ordering, or its comparator
 224.227 +     *         does not permit null keys
 224.228 +     */
 224.229 +    public boolean containsKey(Object key) {
 224.230 +        return getEntry(key) != null;
 224.231 +    }
 224.232 +
 224.233 +    /**
 224.234 +     * Returns {@code true} if this map maps one or more keys to the
 224.235 +     * specified value.  More formally, returns {@code true} if and only if
 224.236 +     * this map contains at least one mapping to a value {@code v} such
 224.237 +     * that {@code (value==null ? v==null : value.equals(v))}.  This
 224.238 +     * operation will probably require time linear in the map size for
 224.239 +     * most implementations.
 224.240 +     *
 224.241 +     * @param value value whose presence in this map is to be tested
 224.242 +     * @return {@code true} if a mapping to {@code value} exists;
 224.243 +     *         {@code false} otherwise
 224.244 +     * @since 1.2
 224.245 +     */
 224.246 +    public boolean containsValue(Object value) {
 224.247 +        for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
 224.248 +            if (valEquals(value, e.value))
 224.249 +                return true;
 224.250 +        return false;
 224.251 +    }
 224.252 +
 224.253 +    /**
 224.254 +     * Returns the value to which the specified key is mapped,
 224.255 +     * or {@code null} if this map contains no mapping for the key.
 224.256 +     *
 224.257 +     * <p>More formally, if this map contains a mapping from a key
 224.258 +     * {@code k} to a value {@code v} such that {@code key} compares
 224.259 +     * equal to {@code k} according to the map's ordering, then this
 224.260 +     * method returns {@code v}; otherwise it returns {@code null}.
 224.261 +     * (There can be at most one such mapping.)
 224.262 +     *
 224.263 +     * <p>A return value of {@code null} does not <em>necessarily</em>
 224.264 +     * indicate that the map contains no mapping for the key; it's also
 224.265 +     * possible that the map explicitly maps the key to {@code null}.
 224.266 +     * The {@link #containsKey containsKey} operation may be used to
 224.267 +     * distinguish these two cases.
 224.268 +     *
 224.269 +     * @throws ClassCastException if the specified key cannot be compared
 224.270 +     *         with the keys currently in the map
 224.271 +     * @throws NullPointerException if the specified key is null
 224.272 +     *         and this map uses natural ordering, or its comparator
 224.273 +     *         does not permit null keys
 224.274 +     */
 224.275 +    public V get(Object key) {
 224.276 +        Entry<K,V> p = getEntry(key);
 224.277 +        return (p==null ? null : p.value);
 224.278 +    }
 224.279 +
 224.280 +    public Comparator<? super K> comparator() {
 224.281 +        return comparator;
 224.282 +    }
 224.283 +
 224.284 +    /**
 224.285 +     * @throws NoSuchElementException {@inheritDoc}
 224.286 +     */
 224.287 +    public K firstKey() {
 224.288 +        return key(getFirstEntry());
 224.289 +    }
 224.290 +
 224.291 +    /**
 224.292 +     * @throws NoSuchElementException {@inheritDoc}
 224.293 +     */
 224.294 +    public K lastKey() {
 224.295 +        return key(getLastEntry());
 224.296 +    }
 224.297 +
 224.298 +    /**
 224.299 +     * Copies all of the mappings from the specified map to this map.
 224.300 +     * These mappings replace any mappings that this map had for any
 224.301 +     * of the keys currently in the specified map.
 224.302 +     *
 224.303 +     * @param  map mappings to be stored in this map
 224.304 +     * @throws ClassCastException if the class of a key or value in
 224.305 +     *         the specified map prevents it from being stored in this map
 224.306 +     * @throws NullPointerException if the specified map is null or
 224.307 +     *         the specified map contains a null key and this map does not
 224.308 +     *         permit null keys
 224.309 +     */
 224.310 +    public void putAll(Map<? extends K, ? extends V> map) {
 224.311 +        int mapSize = map.size();
 224.312 +        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
 224.313 +            Comparator c = ((SortedMap)map).comparator();
 224.314 +            if (c == comparator || (c != null && c.equals(comparator))) {
 224.315 +                ++modCount;
 224.316 +                try {
 224.317 +                    buildFromSorted(mapSize, map.entrySet().iterator(),
 224.318 +                                    null, null);
 224.319 +                } catch (java.io.IOException cannotHappen) {
 224.320 +                } catch (ClassNotFoundException cannotHappen) {
 224.321 +                }
 224.322 +                return;
 224.323 +            }
 224.324 +        }
 224.325 +        super.putAll(map);
 224.326 +    }
 224.327 +
 224.328 +    /**
 224.329 +     * Returns this map's entry for the given key, or {@code null} if the map
 224.330 +     * does not contain an entry for the key.
 224.331 +     *
 224.332 +     * @return this map's entry for the given key, or {@code null} if the map
 224.333 +     *         does not contain an entry for the key
 224.334 +     * @throws ClassCastException if the specified key cannot be compared
 224.335 +     *         with the keys currently in the map
 224.336 +     * @throws NullPointerException if the specified key is null
 224.337 +     *         and this map uses natural ordering, or its comparator
 224.338 +     *         does not permit null keys
 224.339 +     */
 224.340 +    final Entry<K,V> getEntry(Object key) {
 224.341 +        // Offload comparator-based version for sake of performance
 224.342 +        if (comparator != null)
 224.343 +            return getEntryUsingComparator(key);
 224.344 +        if (key == null)
 224.345 +            throw new NullPointerException();
 224.346 +        Comparable<? super K> k = (Comparable<? super K>) key;
 224.347 +        Entry<K,V> p = root;
 224.348 +        while (p != null) {
 224.349 +            int cmp = k.compareTo(p.key);
 224.350 +            if (cmp < 0)
 224.351 +                p = p.left;
 224.352 +            else if (cmp > 0)
 224.353 +                p = p.right;
 224.354 +            else
 224.355 +                return p;
 224.356 +        }
 224.357 +        return null;
 224.358 +    }
 224.359 +
 224.360 +    /**
 224.361 +     * Version of getEntry using comparator. Split off from getEntry
 224.362 +     * for performance. (This is not worth doing for most methods,
 224.363 +     * that are less dependent on comparator performance, but is
 224.364 +     * worthwhile here.)
 224.365 +     */
 224.366 +    final Entry<K,V> getEntryUsingComparator(Object key) {
 224.367 +        K k = (K) key;
 224.368 +        Comparator<? super K> cpr = comparator;
 224.369 +        if (cpr != null) {
 224.370 +            Entry<K,V> p = root;
 224.371 +            while (p != null) {
 224.372 +                int cmp = cpr.compare(k, p.key);
 224.373 +                if (cmp < 0)
 224.374 +                    p = p.left;
 224.375 +                else if (cmp > 0)
 224.376 +                    p = p.right;
 224.377 +                else
 224.378 +                    return p;
 224.379 +            }
 224.380 +        }
 224.381 +        return null;
 224.382 +    }
 224.383 +
 224.384 +    /**
 224.385 +     * Gets the entry corresponding to the specified key; if no such entry
 224.386 +     * exists, returns the entry for the least key greater than the specified
 224.387 +     * key; if no such entry exists (i.e., the greatest key in the Tree is less
 224.388 +     * than the specified key), returns {@code null}.
 224.389 +     */
 224.390 +    final Entry<K,V> getCeilingEntry(K key) {
 224.391 +        Entry<K,V> p = root;
 224.392 +        while (p != null) {
 224.393 +            int cmp = compare(key, p.key);
 224.394 +            if (cmp < 0) {
 224.395 +                if (p.left != null)
 224.396 +                    p = p.left;
 224.397 +                else
 224.398 +                    return p;
 224.399 +            } else if (cmp > 0) {
 224.400 +                if (p.right != null) {
 224.401 +                    p = p.right;
 224.402 +                } else {
 224.403 +                    Entry<K,V> parent = p.parent;
 224.404 +                    Entry<K,V> ch = p;
 224.405 +                    while (parent != null && ch == parent.right) {
 224.406 +                        ch = parent;
 224.407 +                        parent = parent.parent;
 224.408 +                    }
 224.409 +                    return parent;
 224.410 +                }
 224.411 +            } else
 224.412 +                return p;
 224.413 +        }
 224.414 +        return null;
 224.415 +    }
 224.416 +
 224.417 +    /**
 224.418 +     * Gets the entry corresponding to the specified key; if no such entry
 224.419 +     * exists, returns the entry for the greatest key less than the specified
 224.420 +     * key; if no such entry exists, returns {@code null}.
 224.421 +     */
 224.422 +    final Entry<K,V> getFloorEntry(K key) {
 224.423 +        Entry<K,V> p = root;
 224.424 +        while (p != null) {
 224.425 +            int cmp = compare(key, p.key);
 224.426 +            if (cmp > 0) {
 224.427 +                if (p.right != null)
 224.428 +                    p = p.right;
 224.429 +                else
 224.430 +                    return p;
 224.431 +            } else if (cmp < 0) {
 224.432 +                if (p.left != null) {
 224.433 +                    p = p.left;
 224.434 +                } else {
 224.435 +                    Entry<K,V> parent = p.parent;
 224.436 +                    Entry<K,V> ch = p;
 224.437 +                    while (parent != null && ch == parent.left) {
 224.438 +                        ch = parent;
 224.439 +                        parent = parent.parent;
 224.440 +                    }
 224.441 +                    return parent;
 224.442 +                }
 224.443 +            } else
 224.444 +                return p;
 224.445 +
 224.446 +        }
 224.447 +        return null;
 224.448 +    }
 224.449 +
 224.450 +    /**
 224.451 +     * Gets the entry for the least key greater than the specified
 224.452 +     * key; if no such entry exists, returns the entry for the least
 224.453 +     * key greater than the specified key; if no such entry exists
 224.454 +     * returns {@code null}.
 224.455 +     */
 224.456 +    final Entry<K,V> getHigherEntry(K key) {
 224.457 +        Entry<K,V> p = root;
 224.458 +        while (p != null) {
 224.459 +            int cmp = compare(key, p.key);
 224.460 +            if (cmp < 0) {
 224.461 +                if (p.left != null)
 224.462 +                    p = p.left;
 224.463 +                else
 224.464 +                    return p;
 224.465 +            } else {
 224.466 +                if (p.right != null) {
 224.467 +                    p = p.right;
 224.468 +                } else {
 224.469 +                    Entry<K,V> parent = p.parent;
 224.470 +                    Entry<K,V> ch = p;
 224.471 +                    while (parent != null && ch == parent.right) {
 224.472 +                        ch = parent;
 224.473 +                        parent = parent.parent;
 224.474 +                    }
 224.475 +                    return parent;
 224.476 +                }
 224.477 +            }
 224.478 +        }
 224.479 +        return null;
 224.480 +    }
 224.481 +
 224.482 +    /**
 224.483 +     * Returns the entry for the greatest key less than the specified key; if
 224.484 +     * no such entry exists (i.e., the least key in the Tree is greater than
 224.485 +     * the specified key), returns {@code null}.
 224.486 +     */
 224.487 +    final Entry<K,V> getLowerEntry(K key) {
 224.488 +        Entry<K,V> p = root;
 224.489 +        while (p != null) {
 224.490 +            int cmp = compare(key, p.key);
 224.491 +            if (cmp > 0) {
 224.492 +                if (p.right != null)
 224.493 +                    p = p.right;
 224.494 +                else
 224.495 +                    return p;
 224.496 +            } else {
 224.497 +                if (p.left != null) {
 224.498 +                    p = p.left;
 224.499 +                } else {
 224.500 +                    Entry<K,V> parent = p.parent;
 224.501 +                    Entry<K,V> ch = p;
 224.502 +                    while (parent != null && ch == parent.left) {
 224.503 +                        ch = parent;
 224.504 +                        parent = parent.parent;
 224.505 +                    }
 224.506 +                    return parent;
 224.507 +                }
 224.508 +            }
 224.509 +        }
 224.510 +        return null;
 224.511 +    }
 224.512 +
 224.513 +    /**
 224.514 +     * Associates the specified value with the specified key in this map.
 224.515 +     * If the map previously contained a mapping for the key, the old
 224.516 +     * value is replaced.
 224.517 +     *
 224.518 +     * @param key key with which the specified value is to be associated
 224.519 +     * @param value value to be associated with the specified key
 224.520 +     *
 224.521 +     * @return the previous value associated with {@code key}, or
 224.522 +     *         {@code null} if there was no mapping for {@code key}.
 224.523 +     *         (A {@code null} return can also indicate that the map
 224.524 +     *         previously associated {@code null} with {@code key}.)
 224.525 +     * @throws ClassCastException if the specified key cannot be compared
 224.526 +     *         with the keys currently in the map
 224.527 +     * @throws NullPointerException if the specified key is null
 224.528 +     *         and this map uses natural ordering, or its comparator
 224.529 +     *         does not permit null keys
 224.530 +     */
 224.531 +    public V put(K key, V value) {
 224.532 +        Entry<K,V> t = root;
 224.533 +        if (t == null) {
 224.534 +            compare(key, key); // type (and possibly null) check
 224.535 +
 224.536 +            root = new Entry<>(key, value, null);
 224.537 +            size = 1;
 224.538 +            modCount++;
 224.539 +            return null;
 224.540 +        }
 224.541 +        int cmp;
 224.542 +        Entry<K,V> parent;
 224.543 +        // split comparator and comparable paths
 224.544 +        Comparator<? super K> cpr = comparator;
 224.545 +        if (cpr != null) {
 224.546 +            do {
 224.547 +                parent = t;
 224.548 +                cmp = cpr.compare(key, t.key);
 224.549 +                if (cmp < 0)
 224.550 +                    t = t.left;
 224.551 +                else if (cmp > 0)
 224.552 +                    t = t.right;
 224.553 +                else
 224.554 +                    return t.setValue(value);
 224.555 +            } while (t != null);
 224.556 +        }
 224.557 +        else {
 224.558 +            if (key == null)
 224.559 +                throw new NullPointerException();
 224.560 +            Comparable<? super K> k = (Comparable<? super K>) key;
 224.561 +            do {
 224.562 +                parent = t;
 224.563 +                cmp = k.compareTo(t.key);
 224.564 +                if (cmp < 0)
 224.565 +                    t = t.left;
 224.566 +                else if (cmp > 0)
 224.567 +                    t = t.right;
 224.568 +                else
 224.569 +                    return t.setValue(value);
 224.570 +            } while (t != null);
 224.571 +        }
 224.572 +        Entry<K,V> e = new Entry<>(key, value, parent);
 224.573 +        if (cmp < 0)
 224.574 +            parent.left = e;
 224.575 +        else
 224.576 +            parent.right = e;
 224.577 +        fixAfterInsertion(e);
 224.578 +        size++;
 224.579 +        modCount++;
 224.580 +        return null;
 224.581 +    }
 224.582 +
 224.583 +    /**
 224.584 +     * Removes the mapping for this key from this TreeMap if present.
 224.585 +     *
 224.586 +     * @param  key key for which mapping should be removed
 224.587 +     * @return the previous value associated with {@code key}, or
 224.588 +     *         {@code null} if there was no mapping for {@code key}.
 224.589 +     *         (A {@code null} return can also indicate that the map
 224.590 +     *         previously associated {@code null} with {@code key}.)
 224.591 +     * @throws ClassCastException if the specified key cannot be compared
 224.592 +     *         with the keys currently in the map
 224.593 +     * @throws NullPointerException if the specified key is null
 224.594 +     *         and this map uses natural ordering, or its comparator
 224.595 +     *         does not permit null keys
 224.596 +     */
 224.597 +    public V remove(Object key) {
 224.598 +        Entry<K,V> p = getEntry(key);
 224.599 +        if (p == null)
 224.600 +            return null;
 224.601 +
 224.602 +        V oldValue = p.value;
 224.603 +        deleteEntry(p);
 224.604 +        return oldValue;
 224.605 +    }
 224.606 +
 224.607 +    /**
 224.608 +     * Removes all of the mappings from this map.
 224.609 +     * The map will be empty after this call returns.
 224.610 +     */
 224.611 +    public void clear() {
 224.612 +        modCount++;
 224.613 +        size = 0;
 224.614 +        root = null;
 224.615 +    }
 224.616 +
 224.617 +    /**
 224.618 +     * Returns a shallow copy of this {@code TreeMap} instance. (The keys and
 224.619 +     * values themselves are not cloned.)
 224.620 +     *
 224.621 +     * @return a shallow copy of this map
 224.622 +     */
 224.623 +    public Object clone() {
 224.624 +        TreeMap<K,V> clone = null;
 224.625 +        try {
 224.626 +            clone = (TreeMap<K,V>) super.clone();
 224.627 +        } catch (CloneNotSupportedException e) {
 224.628 +            throw new InternalError();
 224.629 +        }
 224.630 +
 224.631 +        // Put clone into "virgin" state (except for comparator)
 224.632 +        clone.root = null;
 224.633 +        clone.size = 0;
 224.634 +        clone.modCount = 0;
 224.635 +        clone.entrySet = null;
 224.636 +        clone.navigableKeySet = null;
 224.637 +        clone.descendingMap = null;
 224.638 +
 224.639 +        // Initialize clone with our mappings
 224.640 +        try {
 224.641 +            clone.buildFromSorted(size, entrySet().iterator(), null, null);
 224.642 +        } catch (java.io.IOException cannotHappen) {
 224.643 +        } catch (ClassNotFoundException cannotHappen) {
 224.644 +        }
 224.645 +
 224.646 +        return clone;
 224.647 +    }
 224.648 +
 224.649 +    // NavigableMap API methods
 224.650 +
 224.651 +    /**
 224.652 +     * @since 1.6
 224.653 +     */
 224.654 +    public Map.Entry<K,V> firstEntry() {
 224.655 +        return exportEntry(getFirstEntry());
 224.656 +    }
 224.657 +
 224.658 +    /**
 224.659 +     * @since 1.6
 224.660 +     */
 224.661 +    public Map.Entry<K,V> lastEntry() {
 224.662 +        return exportEntry(getLastEntry());
 224.663 +    }
 224.664 +
 224.665 +    /**
 224.666 +     * @since 1.6
 224.667 +     */
 224.668 +    public Map.Entry<K,V> pollFirstEntry() {
 224.669 +        Entry<K,V> p = getFirstEntry();
 224.670 +        Map.Entry<K,V> result = exportEntry(p);
 224.671 +        if (p != null)
 224.672 +            deleteEntry(p);
 224.673 +        return result;
 224.674 +    }
 224.675 +
 224.676 +    /**
 224.677 +     * @since 1.6
 224.678 +     */
 224.679 +    public Map.Entry<K,V> pollLastEntry() {
 224.680 +        Entry<K,V> p = getLastEntry();
 224.681 +        Map.Entry<K,V> result = exportEntry(p);
 224.682 +        if (p != null)
 224.683 +            deleteEntry(p);
 224.684 +        return result;
 224.685 +    }
 224.686 +
 224.687 +    /**
 224.688 +     * @throws ClassCastException {@inheritDoc}
 224.689 +     * @throws NullPointerException if the specified key is null
 224.690 +     *         and this map uses natural ordering, or its comparator
 224.691 +     *         does not permit null keys
 224.692 +     * @since 1.6
 224.693 +     */
 224.694 +    public Map.Entry<K,V> lowerEntry(K key) {
 224.695 +        return exportEntry(getLowerEntry(key));
 224.696 +    }
 224.697 +
 224.698 +    /**
 224.699 +     * @throws ClassCastException {@inheritDoc}
 224.700 +     * @throws NullPointerException if the specified key is null
 224.701 +     *         and this map uses natural ordering, or its comparator
 224.702 +     *         does not permit null keys
 224.703 +     * @since 1.6
 224.704 +     */
 224.705 +    public K lowerKey(K key) {
 224.706 +        return keyOrNull(getLowerEntry(key));
 224.707 +    }
 224.708 +
 224.709 +    /**
 224.710 +     * @throws ClassCastException {@inheritDoc}
 224.711 +     * @throws NullPointerException if the specified key is null
 224.712 +     *         and this map uses natural ordering, or its comparator
 224.713 +     *         does not permit null keys
 224.714 +     * @since 1.6
 224.715 +     */
 224.716 +    public Map.Entry<K,V> floorEntry(K key) {
 224.717 +        return exportEntry(getFloorEntry(key));
 224.718 +    }
 224.719 +
 224.720 +    /**
 224.721 +     * @throws ClassCastException {@inheritDoc}
 224.722 +     * @throws NullPointerException if the specified key is null
 224.723 +     *         and this map uses natural ordering, or its comparator
 224.724 +     *         does not permit null keys
 224.725 +     * @since 1.6
 224.726 +     */
 224.727 +    public K floorKey(K key) {
 224.728 +        return keyOrNull(getFloorEntry(key));
 224.729 +    }
 224.730 +
 224.731 +    /**
 224.732 +     * @throws ClassCastException {@inheritDoc}
 224.733 +     * @throws NullPointerException if the specified key is null
 224.734 +     *         and this map uses natural ordering, or its comparator
 224.735 +     *         does not permit null keys
 224.736 +     * @since 1.6
 224.737 +     */
 224.738 +    public Map.Entry<K,V> ceilingEntry(K key) {
 224.739 +        return exportEntry(getCeilingEntry(key));
 224.740 +    }
 224.741 +
 224.742 +    /**
 224.743 +     * @throws ClassCastException {@inheritDoc}
 224.744 +     * @throws NullPointerException if the specified key is null
 224.745 +     *         and this map uses natural ordering, or its comparator
 224.746 +     *         does not permit null keys
 224.747 +     * @since 1.6
 224.748 +     */
 224.749 +    public K ceilingKey(K key) {
 224.750 +        return keyOrNull(getCeilingEntry(key));
 224.751 +    }
 224.752 +
 224.753 +    /**
 224.754 +     * @throws ClassCastException {@inheritDoc}
 224.755 +     * @throws NullPointerException if the specified key is null
 224.756 +     *         and this map uses natural ordering, or its comparator
 224.757 +     *         does not permit null keys
 224.758 +     * @since 1.6
 224.759 +     */
 224.760 +    public Map.Entry<K,V> higherEntry(K key) {
 224.761 +        return exportEntry(getHigherEntry(key));
 224.762 +    }
 224.763 +
 224.764 +    /**
 224.765 +     * @throws ClassCastException {@inheritDoc}
 224.766 +     * @throws NullPointerException if the specified key is null
 224.767 +     *         and this map uses natural ordering, or its comparator
 224.768 +     *         does not permit null keys
 224.769 +     * @since 1.6
 224.770 +     */
 224.771 +    public K higherKey(K key) {
 224.772 +        return keyOrNull(getHigherEntry(key));
 224.773 +    }
 224.774 +
 224.775 +    // Views
 224.776 +
 224.777 +    /**
 224.778 +     * Fields initialized to contain an instance of the entry set view
 224.779 +     * the first time this view is requested.  Views are stateless, so
 224.780 +     * there's no reason to create more than one.
 224.781 +     */
 224.782 +    private transient EntrySet entrySet = null;
 224.783 +    private transient KeySet<K> navigableKeySet = null;
 224.784 +    private transient NavigableMap<K,V> descendingMap = null;
 224.785 +
 224.786 +    /**
 224.787 +     * Returns a {@link Set} view of the keys contained in this map.
 224.788 +     * The set's iterator returns the keys in ascending order.
 224.789 +     * The set is backed by the map, so changes to the map are
 224.790 +     * reflected in the set, and vice-versa.  If the map is modified
 224.791 +     * while an iteration over the set is in progress (except through
 224.792 +     * the iterator's own {@code remove} operation), the results of
 224.793 +     * the iteration are undefined.  The set supports element removal,
 224.794 +     * which removes the corresponding mapping from the map, via the
 224.795 +     * {@code Iterator.remove}, {@code Set.remove},
 224.796 +     * {@code removeAll}, {@code retainAll}, and {@code clear}
 224.797 +     * operations.  It does not support the {@code add} or {@code addAll}
 224.798 +     * operations.
 224.799 +     */
 224.800 +    public Set<K> keySet() {
 224.801 +        return navigableKeySet();
 224.802 +    }
 224.803 +
 224.804 +    /**
 224.805 +     * @since 1.6
 224.806 +     */
 224.807 +    public NavigableSet<K> navigableKeySet() {
 224.808 +        KeySet<K> nks = navigableKeySet;
 224.809 +        return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
 224.810 +    }
 224.811 +
 224.812 +    /**
 224.813 +     * @since 1.6
 224.814 +     */
 224.815 +    public NavigableSet<K> descendingKeySet() {
 224.816 +        return descendingMap().navigableKeySet();
 224.817 +    }
 224.818 +
 224.819 +    /**
 224.820 +     * Returns a {@link Collection} view of the values contained in this map.
 224.821 +     * The collection's iterator returns the values in ascending order
 224.822 +     * of the corresponding keys.
 224.823 +     * The collection is backed by the map, so changes to the map are
 224.824 +     * reflected in the collection, and vice-versa.  If the map is
 224.825 +     * modified while an iteration over the collection is in progress
 224.826 +     * (except through the iterator's own {@code remove} operation),
 224.827 +     * the results of the iteration are undefined.  The collection
 224.828 +     * supports element removal, which removes the corresponding
 224.829 +     * mapping from the map, via the {@code Iterator.remove},
 224.830 +     * {@code Collection.remove}, {@code removeAll},
 224.831 +     * {@code retainAll} and {@code clear} operations.  It does not
 224.832 +     * support the {@code add} or {@code addAll} operations.
 224.833 +     */
 224.834 +    public Collection<V> values() {
 224.835 +        Collection<V> vs = values;
 224.836 +        return (vs != null) ? vs : (values = new Values());
 224.837 +    }
 224.838 +
 224.839 +    /**
 224.840 +     * Returns a {@link Set} view of the mappings contained in this map.
 224.841 +     * The set's iterator returns the entries in ascending key order.
 224.842 +     * The set is backed by the map, so changes to the map are
 224.843 +     * reflected in the set, and vice-versa.  If the map is modified
 224.844 +     * while an iteration over the set is in progress (except through
 224.845 +     * the iterator's own {@code remove} operation, or through the
 224.846 +     * {@code setValue} operation on a map entry returned by the
 224.847 +     * iterator) the results of the iteration are undefined.  The set
 224.848 +     * supports element removal, which removes the corresponding
 224.849 +     * mapping from the map, via the {@code Iterator.remove},
 224.850 +     * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
 224.851 +     * {@code clear} operations.  It does not support the
 224.852 +     * {@code add} or {@code addAll} operations.
 224.853 +     */
 224.854 +    public Set<Map.Entry<K,V>> entrySet() {
 224.855 +        EntrySet es = entrySet;
 224.856 +        return (es != null) ? es : (entrySet = new EntrySet());
 224.857 +    }
 224.858 +
 224.859 +    /**
 224.860 +     * @since 1.6
 224.861 +     */
 224.862 +    public NavigableMap<K, V> descendingMap() {
 224.863 +        NavigableMap<K, V> km = descendingMap;
 224.864 +        return (km != null) ? km :
 224.865 +            (descendingMap = new DescendingSubMap(this,
 224.866 +                                                  true, null, true,
 224.867 +                                                  true, null, true));
 224.868 +    }
 224.869 +
 224.870 +    /**
 224.871 +     * @throws ClassCastException       {@inheritDoc}
 224.872 +     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
 224.873 +     *         null and this map uses natural ordering, or its comparator
 224.874 +     *         does not permit null keys
 224.875 +     * @throws IllegalArgumentException {@inheritDoc}
 224.876 +     * @since 1.6
 224.877 +     */
 224.878 +    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
 224.879 +                                    K toKey,   boolean toInclusive) {
 224.880 +        return new AscendingSubMap(this,
 224.881 +                                   false, fromKey, fromInclusive,
 224.882 +                                   false, toKey,   toInclusive);
 224.883 +    }
 224.884 +
 224.885 +    /**
 224.886 +     * @throws ClassCastException       {@inheritDoc}
 224.887 +     * @throws NullPointerException if {@code toKey} is null
 224.888 +     *         and this map uses natural ordering, or its comparator
 224.889 +     *         does not permit null keys
 224.890 +     * @throws IllegalArgumentException {@inheritDoc}
 224.891 +     * @since 1.6
 224.892 +     */
 224.893 +    public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
 224.894 +        return new AscendingSubMap(this,
 224.895 +                                   true,  null,  true,
 224.896 +                                   false, toKey, inclusive);
 224.897 +    }
 224.898 +
 224.899 +    /**
 224.900 +     * @throws ClassCastException       {@inheritDoc}
 224.901 +     * @throws NullPointerException if {@code fromKey} is null
 224.902 +     *         and this map uses natural ordering, or its comparator
 224.903 +     *         does not permit null keys
 224.904 +     * @throws IllegalArgumentException {@inheritDoc}
 224.905 +     * @since 1.6
 224.906 +     */
 224.907 +    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
 224.908 +        return new AscendingSubMap(this,
 224.909 +                                   false, fromKey, inclusive,
 224.910 +                                   true,  null,    true);
 224.911 +    }
 224.912 +
 224.913 +    /**
 224.914 +     * @throws ClassCastException       {@inheritDoc}
 224.915 +     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
 224.916 +     *         null and this map uses natural ordering, or its comparator
 224.917 +     *         does not permit null keys
 224.918 +     * @throws IllegalArgumentException {@inheritDoc}
 224.919 +     */
 224.920 +    public SortedMap<K,V> subMap(K fromKey, K toKey) {
 224.921 +        return subMap(fromKey, true, toKey, false);
 224.922 +    }
 224.923 +
 224.924 +    /**
 224.925 +     * @throws ClassCastException       {@inheritDoc}
 224.926 +     * @throws NullPointerException if {@code toKey} is null
 224.927 +     *         and this map uses natural ordering, or its comparator
 224.928 +     *         does not permit null keys
 224.929 +     * @throws IllegalArgumentException {@inheritDoc}
 224.930 +     */
 224.931 +    public SortedMap<K,V> headMap(K toKey) {
 224.932 +        return headMap(toKey, false);
 224.933 +    }
 224.934 +
 224.935 +    /**
 224.936 +     * @throws ClassCastException       {@inheritDoc}
 224.937 +     * @throws NullPointerException if {@code fromKey} is null
 224.938 +     *         and this map uses natural ordering, or its comparator
 224.939 +     *         does not permit null keys
 224.940 +     * @throws IllegalArgumentException {@inheritDoc}
 224.941 +     */
 224.942 +    public SortedMap<K,V> tailMap(K fromKey) {
 224.943 +        return tailMap(fromKey, true);
 224.944 +    }
 224.945 +
 224.946 +    // View class support
 224.947 +
 224.948 +    class Values extends AbstractCollection<V> {
 224.949 +        public Iterator<V> iterator() {
 224.950 +            return new ValueIterator(getFirstEntry());
 224.951 +        }
 224.952 +
 224.953 +        public int size() {
 224.954 +            return TreeMap.this.size();
 224.955 +        }
 224.956 +
 224.957 +        public boolean contains(Object o) {
 224.958 +            return TreeMap.this.containsValue(o);
 224.959 +        }
 224.960 +
 224.961 +        public boolean remove(Object o) {
 224.962 +            for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) {
 224.963 +                if (valEquals(e.getValue(), o)) {
 224.964 +                    deleteEntry(e);
 224.965 +                    return true;
 224.966 +                }
 224.967 +            }
 224.968 +            return false;
 224.969 +        }
 224.970 +
 224.971 +        public void clear() {
 224.972 +            TreeMap.this.clear();
 224.973 +        }
 224.974 +    }
 224.975 +
 224.976 +    class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 224.977 +        public Iterator<Map.Entry<K,V>> iterator() {
 224.978 +            return new EntryIterator(getFirstEntry());
 224.979 +        }
 224.980 +
 224.981 +        public boolean contains(Object o) {
 224.982 +            if (!(o instanceof Map.Entry))
 224.983 +                return false;
 224.984 +            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 224.985 +            V value = entry.getValue();
 224.986 +            Entry<K,V> p = getEntry(entry.getKey());
 224.987 +            return p != null && valEquals(p.getValue(), value);
 224.988 +        }
 224.989 +
 224.990 +        public boolean remove(Object o) {
 224.991 +            if (!(o instanceof Map.Entry))
 224.992 +                return false;
 224.993 +            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 224.994 +            V value = entry.getValue();
 224.995 +            Entry<K,V> p = getEntry(entry.getKey());
 224.996 +            if (p != null && valEquals(p.getValue(), value)) {
 224.997 +                deleteEntry(p);
 224.998 +                return true;
 224.999 +            }
224.1000 +            return false;
224.1001 +        }
224.1002 +
224.1003 +        public int size() {
224.1004 +            return TreeMap.this.size();
224.1005 +        }
224.1006 +
224.1007 +        public void clear() {
224.1008 +            TreeMap.this.clear();
224.1009 +        }
224.1010 +    }
224.1011 +
224.1012 +    /*
224.1013 +     * Unlike Values and EntrySet, the KeySet class is static,
224.1014 +     * delegating to a NavigableMap to allow use by SubMaps, which
224.1015 +     * outweighs the ugliness of needing type-tests for the following
224.1016 +     * Iterator methods that are defined appropriately in main versus
224.1017 +     * submap classes.
224.1018 +     */
224.1019 +
224.1020 +    Iterator<K> keyIterator() {
224.1021 +        return new KeyIterator(getFirstEntry());
224.1022 +    }
224.1023 +
224.1024 +    Iterator<K> descendingKeyIterator() {
224.1025 +        return new DescendingKeyIterator(getLastEntry());
224.1026 +    }
224.1027 +
224.1028 +    static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
224.1029 +        private final NavigableMap<E, Object> m;
224.1030 +        KeySet(NavigableMap<E,Object> map) { m = map; }
224.1031 +
224.1032 +        public Iterator<E> iterator() {
224.1033 +            if (m instanceof TreeMap)
224.1034 +                return ((TreeMap<E,Object>)m).keyIterator();
224.1035 +            else
224.1036 +                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator());
224.1037 +        }
224.1038 +
224.1039 +        public Iterator<E> descendingIterator() {
224.1040 +            if (m instanceof TreeMap)
224.1041 +                return ((TreeMap<E,Object>)m).descendingKeyIterator();
224.1042 +            else
224.1043 +                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator());
224.1044 +        }
224.1045 +
224.1046 +        public int size() { return m.size(); }
224.1047 +        public boolean isEmpty() { return m.isEmpty(); }
224.1048 +        public boolean contains(Object o) { return m.containsKey(o); }
224.1049 +        public void clear() { m.clear(); }
224.1050 +        public E lower(E e) { return m.lowerKey(e); }
224.1051 +        public E floor(E e) { return m.floorKey(e); }
224.1052 +        public E ceiling(E e) { return m.ceilingKey(e); }
224.1053 +        public E higher(E e) { return m.higherKey(e); }
224.1054 +        public E first() { return m.firstKey(); }
224.1055 +        public E last() { return m.lastKey(); }
224.1056 +        public Comparator<? super E> comparator() { return m.comparator(); }
224.1057 +        public E pollFirst() {
224.1058 +            Map.Entry<E,Object> e = m.pollFirstEntry();
224.1059 +            return (e == null) ? null : e.getKey();
224.1060 +        }
224.1061 +        public E pollLast() {
224.1062 +            Map.Entry<E,Object> e = m.pollLastEntry();
224.1063 +            return (e == null) ? null : e.getKey();
224.1064 +        }
224.1065 +        public boolean remove(Object o) {
224.1066 +            int oldSize = size();
224.1067 +            m.remove(o);
224.1068 +            return size() != oldSize;
224.1069 +        }
224.1070 +        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
224.1071 +                                      E toElement,   boolean toInclusive) {
224.1072 +            return new KeySet<>(m.subMap(fromElement, fromInclusive,
224.1073 +                                          toElement,   toInclusive));
224.1074 +        }
224.1075 +        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
224.1076 +            return new KeySet<>(m.headMap(toElement, inclusive));
224.1077 +        }
224.1078 +        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
224.1079 +            return new KeySet<>(m.tailMap(fromElement, inclusive));
224.1080 +        }
224.1081 +        public SortedSet<E> subSet(E fromElement, E toElement) {
224.1082 +            return subSet(fromElement, true, toElement, false);
224.1083 +        }
224.1084 +        public SortedSet<E> headSet(E toElement) {
224.1085 +            return headSet(toElement, false);
224.1086 +        }
224.1087 +        public SortedSet<E> tailSet(E fromElement) {
224.1088 +            return tailSet(fromElement, true);
224.1089 +        }
224.1090 +        public NavigableSet<E> descendingSet() {
224.1091 +            return new KeySet(m.descendingMap());
224.1092 +        }
224.1093 +    }
224.1094 +
224.1095 +    /**
224.1096 +     * Base class for TreeMap Iterators
224.1097 +     */
224.1098 +    abstract class PrivateEntryIterator<T> implements Iterator<T> {
224.1099 +        Entry<K,V> next;
224.1100 +        Entry<K,V> lastReturned;
224.1101 +        int expectedModCount;
224.1102 +
224.1103 +        PrivateEntryIterator(Entry<K,V> first) {
224.1104 +            expectedModCount = modCount;
224.1105 +            lastReturned = null;
224.1106 +            next = first;
224.1107 +        }
224.1108 +
224.1109 +        public final boolean hasNext() {
224.1110 +            return next != null;
224.1111 +        }
224.1112 +
224.1113 +        final Entry<K,V> nextEntry() {
224.1114 +            Entry<K,V> e = next;
224.1115 +            if (e == null)
224.1116 +                throw new NoSuchElementException();
224.1117 +            if (modCount != expectedModCount)
224.1118 +                throw new ConcurrentModificationException();
224.1119 +            next = successor(e);
224.1120 +            lastReturned = e;
224.1121 +            return e;
224.1122 +        }
224.1123 +
224.1124 +        final Entry<K,V> prevEntry() {
224.1125 +            Entry<K,V> e = next;
224.1126 +            if (e == null)
224.1127 +                throw new NoSuchElementException();
224.1128 +            if (modCount != expectedModCount)
224.1129 +                throw new ConcurrentModificationException();
224.1130 +            next = predecessor(e);
224.1131 +            lastReturned = e;
224.1132 +            return e;
224.1133 +        }
224.1134 +
224.1135 +        public void remove() {
224.1136 +            if (lastReturned == null)
224.1137 +                throw new IllegalStateException();
224.1138 +            if (modCount != expectedModCount)
224.1139 +                throw new ConcurrentModificationException();
224.1140 +            // deleted entries are replaced by their successors
224.1141 +            if (lastReturned.left != null && lastReturned.right != null)
224.1142 +                next = lastReturned;
224.1143 +            deleteEntry(lastReturned);
224.1144 +            expectedModCount = modCount;
224.1145 +            lastReturned = null;
224.1146 +        }
224.1147 +    }
224.1148 +
224.1149 +    final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> {
224.1150 +        EntryIterator(Entry<K,V> first) {
224.1151 +            super(first);
224.1152 +        }
224.1153 +        public Map.Entry<K,V> next() {
224.1154 +            return nextEntry();
224.1155 +        }
224.1156 +    }
224.1157 +
224.1158 +    final class ValueIterator extends PrivateEntryIterator<V> {
224.1159 +        ValueIterator(Entry<K,V> first) {
224.1160 +            super(first);
224.1161 +        }
224.1162 +        public V next() {
224.1163 +            return nextEntry().value;
224.1164 +        }
224.1165 +    }
224.1166 +
224.1167 +    final class KeyIterator extends PrivateEntryIterator<K> {
224.1168 +        KeyIterator(Entry<K,V> first) {
224.1169 +            super(first);
224.1170 +        }
224.1171 +        public K next() {
224.1172 +            return nextEntry().key;
224.1173 +        }
224.1174 +    }
224.1175 +
224.1176 +    final class DescendingKeyIterator extends PrivateEntryIterator<K> {
224.1177 +        DescendingKeyIterator(Entry<K,V> first) {
224.1178 +            super(first);
224.1179 +        }
224.1180 +        public K next() {
224.1181 +            return prevEntry().key;
224.1182 +        }
224.1183 +    }
224.1184 +
224.1185 +    // Little utilities
224.1186 +
224.1187 +    /**
224.1188 +     * Compares two keys using the correct comparison method for this TreeMap.
224.1189 +     */
224.1190 +    final int compare(Object k1, Object k2) {
224.1191 +        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
224.1192 +            : comparator.compare((K)k1, (K)k2);
224.1193 +    }
224.1194 +
224.1195 +    /**
224.1196 +     * Test two values for equality.  Differs from o1.equals(o2) only in
224.1197 +     * that it copes with {@code null} o1 properly.
224.1198 +     */
224.1199 +    static final boolean valEquals(Object o1, Object o2) {
224.1200 +        return (o1==null ? o2==null : o1.equals(o2));
224.1201 +    }
224.1202 +
224.1203 +    /**
224.1204 +     * Return SimpleImmutableEntry for entry, or null if null
224.1205 +     */
224.1206 +    static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
224.1207 +        return (e == null) ? null :
224.1208 +            new AbstractMap.SimpleImmutableEntry<>(e);
224.1209 +    }
224.1210 +
224.1211 +    /**
224.1212 +     * Return key for entry, or null if null
224.1213 +     */
224.1214 +    static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
224.1215 +        return (e == null) ? null : e.key;
224.1216 +    }
224.1217 +
224.1218 +    /**
224.1219 +     * Returns the key corresponding to the specified Entry.
224.1220 +     * @throws NoSuchElementException if the Entry is null
224.1221 +     */
224.1222 +    static <K> K key(Entry<K,?> e) {
224.1223 +        if (e==null)
224.1224 +            throw new NoSuchElementException();
224.1225 +        return e.key;
224.1226 +    }
224.1227 +
224.1228 +
224.1229 +    // SubMaps
224.1230 +
224.1231 +    /**
224.1232 +     * Dummy value serving as unmatchable fence key for unbounded
224.1233 +     * SubMapIterators
224.1234 +     */
224.1235 +    private static final Object UNBOUNDED = new Object();
224.1236 +
224.1237 +    /**
224.1238 +     * @serial include
224.1239 +     */
224.1240 +    abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V>
224.1241 +        implements NavigableMap<K,V>, java.io.Serializable {
224.1242 +        /**
224.1243 +         * The backing map.
224.1244 +         */
224.1245 +        final TreeMap<K,V> m;
224.1246 +
224.1247 +        /**
224.1248 +         * Endpoints are represented as triples (fromStart, lo,
224.1249 +         * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is
224.1250 +         * true, then the low (absolute) bound is the start of the
224.1251 +         * backing map, and the other values are ignored. Otherwise,
224.1252 +         * if loInclusive is true, lo is the inclusive bound, else lo
224.1253 +         * is the exclusive bound. Similarly for the upper bound.
224.1254 +         */
224.1255 +        final K lo, hi;
224.1256 +        final boolean fromStart, toEnd;
224.1257 +        final boolean loInclusive, hiInclusive;
224.1258 +
224.1259 +        NavigableSubMap(TreeMap<K,V> m,
224.1260 +                        boolean fromStart, K lo, boolean loInclusive,
224.1261 +                        boolean toEnd,     K hi, boolean hiInclusive) {
224.1262 +            if (!fromStart && !toEnd) {
224.1263 +                if (m.compare(lo, hi) > 0)
224.1264 +                    throw new IllegalArgumentException("fromKey > toKey");
224.1265 +            } else {
224.1266 +                if (!fromStart) // type check
224.1267 +                    m.compare(lo, lo);
224.1268 +                if (!toEnd)
224.1269 +                    m.compare(hi, hi);
224.1270 +            }
224.1271 +
224.1272 +            this.m = m;
224.1273 +            this.fromStart = fromStart;
224.1274 +            this.lo = lo;
224.1275 +            this.loInclusive = loInclusive;
224.1276 +            this.toEnd = toEnd;
224.1277 +            this.hi = hi;
224.1278 +            this.hiInclusive = hiInclusive;
224.1279 +        }
224.1280 +
224.1281 +        // internal utilities
224.1282 +
224.1283 +        final boolean tooLow(Object key) {
224.1284 +            if (!fromStart) {
224.1285 +                int c = m.compare(key, lo);
224.1286 +                if (c < 0 || (c == 0 && !loInclusive))
224.1287 +                    return true;
224.1288 +            }
224.1289 +            return false;
224.1290 +        }
224.1291 +
224.1292 +        final boolean tooHigh(Object key) {
224.1293 +            if (!toEnd) {
224.1294 +                int c = m.compare(key, hi);
224.1295 +                if (c > 0 || (c == 0 && !hiInclusive))
224.1296 +                    return true;
224.1297 +            }
224.1298 +            return false;
224.1299 +        }
224.1300 +
224.1301 +        final boolean inRange(Object key) {
224.1302 +            return !tooLow(key) && !tooHigh(key);
224.1303 +        }
224.1304 +
224.1305 +        final boolean inClosedRange(Object key) {
224.1306 +            return (fromStart || m.compare(key, lo) >= 0)
224.1307 +                && (toEnd || m.compare(hi, key) >= 0);
224.1308 +        }
224.1309 +
224.1310 +        final boolean inRange(Object key, boolean inclusive) {
224.1311 +            return inclusive ? inRange(key) : inClosedRange(key);
224.1312 +        }
224.1313 +
224.1314 +        /*
224.1315 +         * Absolute versions of relation operations.
224.1316 +         * Subclasses map to these using like-named "sub"
224.1317 +         * versions that invert senses for descending maps
224.1318 +         */
224.1319 +
224.1320 +        final TreeMap.Entry<K,V> absLowest() {
224.1321 +            TreeMap.Entry<K,V> e =
224.1322 +                (fromStart ?  m.getFirstEntry() :
224.1323 +                 (loInclusive ? m.getCeilingEntry(lo) :
224.1324 +                                m.getHigherEntry(lo)));
224.1325 +            return (e == null || tooHigh(e.key)) ? null : e;
224.1326 +        }
224.1327 +
224.1328 +        final TreeMap.Entry<K,V> absHighest() {
224.1329 +            TreeMap.Entry<K,V> e =
224.1330 +                (toEnd ?  m.getLastEntry() :
224.1331 +                 (hiInclusive ?  m.getFloorEntry(hi) :
224.1332 +                                 m.getLowerEntry(hi)));
224.1333 +            return (e == null || tooLow(e.key)) ? null : e;
224.1334 +        }
224.1335 +
224.1336 +        final TreeMap.Entry<K,V> absCeiling(K key) {
224.1337 +            if (tooLow(key))
224.1338 +                return absLowest();
224.1339 +            TreeMap.Entry<K,V> e = m.getCeilingEntry(key);
224.1340 +            return (e == null || tooHigh(e.key)) ? null : e;
224.1341 +        }
224.1342 +
224.1343 +        final TreeMap.Entry<K,V> absHigher(K key) {
224.1344 +            if (tooLow(key))
224.1345 +                return absLowest();
224.1346 +            TreeMap.Entry<K,V> e = m.getHigherEntry(key);
224.1347 +            return (e == null || tooHigh(e.key)) ? null : e;
224.1348 +        }
224.1349 +
224.1350 +        final TreeMap.Entry<K,V> absFloor(K key) {
224.1351 +            if (tooHigh(key))
224.1352 +                return absHighest();
224.1353 +            TreeMap.Entry<K,V> e = m.getFloorEntry(key);
224.1354 +            return (e == null || tooLow(e.key)) ? null : e;
224.1355 +        }
224.1356 +
224.1357 +        final TreeMap.Entry<K,V> absLower(K key) {
224.1358 +            if (tooHigh(key))
224.1359 +                return absHighest();
224.1360 +            TreeMap.Entry<K,V> e = m.getLowerEntry(key);
224.1361 +            return (e == null || tooLow(e.key)) ? null : e;
224.1362 +        }
224.1363 +
224.1364 +        /** Returns the absolute high fence for ascending traversal */
224.1365 +        final TreeMap.Entry<K,V> absHighFence() {
224.1366 +            return (toEnd ? null : (hiInclusive ?
224.1367 +                                    m.getHigherEntry(hi) :
224.1368 +                                    m.getCeilingEntry(hi)));
224.1369 +        }
224.1370 +
224.1371 +        /** Return the absolute low fence for descending traversal  */
224.1372 +        final TreeMap.Entry<K,V> absLowFence() {
224.1373 +            return (fromStart ? null : (loInclusive ?
224.1374 +                                        m.getLowerEntry(lo) :
224.1375 +                                        m.getFloorEntry(lo)));
224.1376 +        }
224.1377 +
224.1378 +        // Abstract methods defined in ascending vs descending classes
224.1379 +        // These relay to the appropriate absolute versions
224.1380 +
224.1381 +        abstract TreeMap.Entry<K,V> subLowest();
224.1382 +        abstract TreeMap.Entry<K,V> subHighest();
224.1383 +        abstract TreeMap.Entry<K,V> subCeiling(K key);
224.1384 +        abstract TreeMap.Entry<K,V> subHigher(K key);
224.1385 +        abstract TreeMap.Entry<K,V> subFloor(K key);
224.1386 +        abstract TreeMap.Entry<K,V> subLower(K key);
224.1387 +
224.1388 +        /** Returns ascending iterator from the perspective of this submap */
224.1389 +        abstract Iterator<K> keyIterator();
224.1390 +
224.1391 +        /** Returns descending iterator from the perspective of this submap */
224.1392 +        abstract Iterator<K> descendingKeyIterator();
224.1393 +
224.1394 +        // public methods
224.1395 +
224.1396 +        public boolean isEmpty() {
224.1397 +            return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty();
224.1398 +        }
224.1399 +
224.1400 +        public int size() {
224.1401 +            return (fromStart && toEnd) ? m.size() : entrySet().size();
224.1402 +        }
224.1403 +
224.1404 +        public final boolean containsKey(Object key) {
224.1405 +            return inRange(key) && m.containsKey(key);
224.1406 +        }
224.1407 +
224.1408 +        public final V put(K key, V value) {
224.1409 +            if (!inRange(key))
224.1410 +                throw new IllegalArgumentException("key out of range");
224.1411 +            return m.put(key, value);
224.1412 +        }
224.1413 +
224.1414 +        public final V get(Object key) {
224.1415 +            return !inRange(key) ? null :  m.get(key);
224.1416 +        }
224.1417 +
224.1418 +        public final V remove(Object key) {
224.1419 +            return !inRange(key) ? null : m.remove(key);
224.1420 +        }
224.1421 +
224.1422 +        public final Map.Entry<K,V> ceilingEntry(K key) {
224.1423 +            return exportEntry(subCeiling(key));
224.1424 +        }
224.1425 +
224.1426 +        public final K ceilingKey(K key) {
224.1427 +            return keyOrNull(subCeiling(key));
224.1428 +        }
224.1429 +
224.1430 +        public final Map.Entry<K,V> higherEntry(K key) {
224.1431 +            return exportEntry(subHigher(key));
224.1432 +        }
224.1433 +
224.1434 +        public final K higherKey(K key) {
224.1435 +            return keyOrNull(subHigher(key));
224.1436 +        }
224.1437 +
224.1438 +        public final Map.Entry<K,V> floorEntry(K key) {
224.1439 +            return exportEntry(subFloor(key));
224.1440 +        }
224.1441 +
224.1442 +        public final K floorKey(K key) {
224.1443 +            return keyOrNull(subFloor(key));
224.1444 +        }
224.1445 +
224.1446 +        public final Map.Entry<K,V> lowerEntry(K key) {
224.1447 +            return exportEntry(subLower(key));
224.1448 +        }
224.1449 +
224.1450 +        public final K lowerKey(K key) {
224.1451 +            return keyOrNull(subLower(key));
224.1452 +        }
224.1453 +
224.1454 +        public final K firstKey() {
224.1455 +            return key(subLowest());
224.1456 +        }
224.1457 +
224.1458 +        public final K lastKey() {
224.1459 +            return key(subHighest());
224.1460 +        }
224.1461 +
224.1462 +        public final Map.Entry<K,V> firstEntry() {
224.1463 +            return exportEntry(subLowest());
224.1464 +        }
224.1465 +
224.1466 +        public final Map.Entry<K,V> lastEntry() {
224.1467 +            return exportEntry(subHighest());
224.1468 +        }
224.1469 +
224.1470 +        public final Map.Entry<K,V> pollFirstEntry() {
224.1471 +            TreeMap.Entry<K,V> e = subLowest();
224.1472 +            Map.Entry<K,V> result = exportEntry(e);
224.1473 +            if (e != null)
224.1474 +                m.deleteEntry(e);
224.1475 +            return result;
224.1476 +        }
224.1477 +
224.1478 +        public final Map.Entry<K,V> pollLastEntry() {
224.1479 +            TreeMap.Entry<K,V> e = subHighest();
224.1480 +            Map.Entry<K,V> result = exportEntry(e);
224.1481 +            if (e != null)
224.1482 +                m.deleteEntry(e);
224.1483 +            return result;
224.1484 +        }
224.1485 +
224.1486 +        // Views
224.1487 +        transient NavigableMap<K,V> descendingMapView = null;
224.1488 +        transient EntrySetView entrySetView = null;
224.1489 +        transient KeySet<K> navigableKeySetView = null;
224.1490 +
224.1491 +        public final NavigableSet<K> navigableKeySet() {
224.1492 +            KeySet<K> nksv = navigableKeySetView;
224.1493 +            return (nksv != null) ? nksv :
224.1494 +                (navigableKeySetView = new TreeMap.KeySet(this));
224.1495 +        }
224.1496 +
224.1497 +        public final Set<K> keySet() {
224.1498 +            return navigableKeySet();
224.1499 +        }
224.1500 +
224.1501 +        public NavigableSet<K> descendingKeySet() {
224.1502 +            return descendingMap().navigableKeySet();
224.1503 +        }
224.1504 +
224.1505 +        public final SortedMap<K,V> subMap(K fromKey, K toKey) {
224.1506 +            return subMap(fromKey, true, toKey, false);
224.1507 +        }
224.1508 +
224.1509 +        public final SortedMap<K,V> headMap(K toKey) {
224.1510 +            return headMap(toKey, false);
224.1511 +        }
224.1512 +
224.1513 +        public final SortedMap<K,V> tailMap(K fromKey) {
224.1514 +            return tailMap(fromKey, true);
224.1515 +        }
224.1516 +
224.1517 +        // View classes
224.1518 +
224.1519 +        abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
224.1520 +            private transient int size = -1, sizeModCount;
224.1521 +
224.1522 +            public int size() {
224.1523 +                if (fromStart && toEnd)
224.1524 +                    return m.size();
224.1525 +                if (size == -1 || sizeModCount != m.modCount) {
224.1526 +                    sizeModCount = m.modCount;
224.1527 +                    size = 0;
224.1528 +                    Iterator i = iterator();
224.1529 +                    while (i.hasNext()) {
224.1530 +                        size++;
224.1531 +                        i.next();
224.1532 +                    }
224.1533 +                }
224.1534 +                return size;
224.1535 +            }
224.1536 +
224.1537 +            public boolean isEmpty() {
224.1538 +                TreeMap.Entry<K,V> n = absLowest();
224.1539 +                return n == null || tooHigh(n.key);
224.1540 +            }
224.1541 +
224.1542 +            public boolean contains(Object o) {
224.1543 +                if (!(o instanceof Map.Entry))
224.1544 +                    return false;
224.1545 +                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
224.1546 +                K key = entry.getKey();
224.1547 +                if (!inRange(key))
224.1548 +                    return false;
224.1549 +                TreeMap.Entry node = m.getEntry(key);
224.1550 +                return node != null &&
224.1551 +                    valEquals(node.getValue(), entry.getValue());
224.1552 +            }
224.1553 +
224.1554 +            public boolean remove(Object o) {
224.1555 +                if (!(o instanceof Map.Entry))
224.1556 +                    return false;
224.1557 +                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
224.1558 +                K key = entry.getKey();
224.1559 +                if (!inRange(key))
224.1560 +                    return false;
224.1561 +                TreeMap.Entry<K,V> node = m.getEntry(key);
224.1562 +                if (node!=null && valEquals(node.getValue(),
224.1563 +                                            entry.getValue())) {
224.1564 +                    m.deleteEntry(node);
224.1565 +                    return true;
224.1566 +                }
224.1567 +                return false;
224.1568 +            }
224.1569 +        }
224.1570 +
224.1571 +        /**
224.1572 +         * Iterators for SubMaps
224.1573 +         */
224.1574 +        abstract class SubMapIterator<T> implements Iterator<T> {
224.1575 +            TreeMap.Entry<K,V> lastReturned;
224.1576 +            TreeMap.Entry<K,V> next;
224.1577 +            final Object fenceKey;
224.1578 +            int expectedModCount;
224.1579 +
224.1580 +            SubMapIterator(TreeMap.Entry<K,V> first,
224.1581 +                           TreeMap.Entry<K,V> fence) {
224.1582 +                expectedModCount = m.modCount;
224.1583 +                lastReturned = null;
224.1584 +                next = first;
224.1585 +                fenceKey = fence == null ? UNBOUNDED : fence.key;
224.1586 +            }
224.1587 +
224.1588 +            public final boolean hasNext() {
224.1589 +                return next != null && next.key != fenceKey;
224.1590 +            }
224.1591 +
224.1592 +            final TreeMap.Entry<K,V> nextEntry() {
224.1593 +                TreeMap.Entry<K,V> e = next;
224.1594 +                if (e == null || e.key == fenceKey)
224.1595 +                    throw new NoSuchElementException();
224.1596 +                if (m.modCount != expectedModCount)
224.1597 +                    throw new ConcurrentModificationException();
224.1598 +                next = successor(e);
224.1599 +                lastReturned = e;
224.1600 +                return e;
224.1601 +            }
224.1602 +
224.1603 +            final TreeMap.Entry<K,V> prevEntry() {
224.1604 +                TreeMap.Entry<K,V> e = next;
224.1605 +                if (e == null || e.key == fenceKey)
224.1606 +                    throw new NoSuchElementException();
224.1607 +                if (m.modCount != expectedModCount)
224.1608 +                    throw new ConcurrentModificationException();
224.1609 +                next = predecessor(e);
224.1610 +                lastReturned = e;
224.1611 +                return e;
224.1612 +            }
224.1613 +
224.1614 +            final void removeAscending() {
224.1615 +                if (lastReturned == null)
224.1616 +                    throw new IllegalStateException();
224.1617 +                if (m.modCount != expectedModCount)
224.1618 +                    throw new ConcurrentModificationException();
224.1619 +                // deleted entries are replaced by their successors
224.1620 +                if (lastReturned.left != null && lastReturned.right != null)
224.1621 +                    next = lastReturned;
224.1622 +                m.deleteEntry(lastReturned);
224.1623 +                lastReturned = null;
224.1624 +                expectedModCount = m.modCount;
224.1625 +            }
224.1626 +
224.1627 +            final void removeDescending() {
224.1628 +                if (lastReturned == null)
224.1629 +                    throw new IllegalStateException();
224.1630 +                if (m.modCount != expectedModCount)
224.1631 +                    throw new ConcurrentModificationException();
224.1632 +                m.deleteEntry(lastReturned);
224.1633 +                lastReturned = null;
224.1634 +                expectedModCount = m.modCount;
224.1635 +            }
224.1636 +
224.1637 +        }
224.1638 +
224.1639 +        final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
224.1640 +            SubMapEntryIterator(TreeMap.Entry<K,V> first,
224.1641 +                                TreeMap.Entry<K,V> fence) {
224.1642 +                super(first, fence);
224.1643 +            }
224.1644 +            public Map.Entry<K,V> next() {
224.1645 +                return nextEntry();
224.1646 +            }
224.1647 +            public void remove() {
224.1648 +                removeAscending();
224.1649 +            }
224.1650 +        }
224.1651 +
224.1652 +        final class SubMapKeyIterator extends SubMapIterator<K> {
224.1653 +            SubMapKeyIterator(TreeMap.Entry<K,V> first,
224.1654 +                              TreeMap.Entry<K,V> fence) {
224.1655 +                super(first, fence);
224.1656 +            }
224.1657 +            public K next() {
224.1658 +                return nextEntry().key;
224.1659 +            }
224.1660 +            public void remove() {
224.1661 +                removeAscending();
224.1662 +            }
224.1663 +        }
224.1664 +
224.1665 +        final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
224.1666 +            DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last,
224.1667 +                                          TreeMap.Entry<K,V> fence) {
224.1668 +                super(last, fence);
224.1669 +            }
224.1670 +
224.1671 +            public Map.Entry<K,V> next() {
224.1672 +                return prevEntry();
224.1673 +            }
224.1674 +            public void remove() {
224.1675 +                removeDescending();
224.1676 +            }
224.1677 +        }
224.1678 +
224.1679 +        final class DescendingSubMapKeyIterator extends SubMapIterator<K> {
224.1680 +            DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last,
224.1681 +                                        TreeMap.Entry<K,V> fence) {
224.1682 +                super(last, fence);
224.1683 +            }
224.1684 +            public K next() {
224.1685 +                return prevEntry().key;
224.1686 +            }
224.1687 +            public void remove() {
224.1688 +                removeDescending();
224.1689 +            }
224.1690 +        }
224.1691 +    }
224.1692 +
224.1693 +    /**
224.1694 +     * @serial include
224.1695 +     */
224.1696 +    static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> {
224.1697 +        private static final long serialVersionUID = 912986545866124060L;
224.1698 +
224.1699 +        AscendingSubMap(TreeMap<K,V> m,
224.1700 +                        boolean fromStart, K lo, boolean loInclusive,
224.1701 +                        boolean toEnd,     K hi, boolean hiInclusive) {
224.1702 +            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
224.1703 +        }
224.1704 +
224.1705 +        public Comparator<? super K> comparator() {
224.1706 +            return m.comparator();
224.1707 +        }
224.1708 +
224.1709 +        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
224.1710 +                                        K toKey,   boolean toInclusive) {
224.1711 +            if (!inRange(fromKey, fromInclusive))
224.1712 +                throw new IllegalArgumentException("fromKey out of range");
224.1713 +            if (!inRange(toKey, toInclusive))
224.1714 +                throw new IllegalArgumentException("toKey out of range");
224.1715 +            return new AscendingSubMap(m,
224.1716 +                                       false, fromKey, fromInclusive,
224.1717 +                                       false, toKey,   toInclusive);
224.1718 +        }
224.1719 +
224.1720 +        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
224.1721 +            if (!inRange(toKey, inclusive))
224.1722 +                throw new IllegalArgumentException("toKey out of range");
224.1723 +            return new AscendingSubMap(m,
224.1724 +                                       fromStart, lo,    loInclusive,
224.1725 +                                       false,     toKey, inclusive);
224.1726 +        }
224.1727 +
224.1728 +        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
224.1729 +            if (!inRange(fromKey, inclusive))
224.1730 +                throw new IllegalArgumentException("fromKey out of range");
224.1731 +            return new AscendingSubMap(m,
224.1732 +                                       false, fromKey, inclusive,
224.1733 +                                       toEnd, hi,      hiInclusive);
224.1734 +        }
224.1735 +
224.1736 +        public NavigableMap<K,V> descendingMap() {
224.1737 +            NavigableMap<K,V> mv = descendingMapView;
224.1738 +            return (mv != null) ? mv :
224.1739 +                (descendingMapView =
224.1740 +                 new DescendingSubMap(m,
224.1741 +                                      fromStart, lo, loInclusive,
224.1742 +                                      toEnd,     hi, hiInclusive));
224.1743 +        }
224.1744 +
224.1745 +        Iterator<K> keyIterator() {
224.1746 +            return new SubMapKeyIterator(absLowest(), absHighFence());
224.1747 +        }
224.1748 +
224.1749 +        Iterator<K> descendingKeyIterator() {
224.1750 +            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
224.1751 +        }
224.1752 +
224.1753 +        final class AscendingEntrySetView extends EntrySetView {
224.1754 +            public Iterator<Map.Entry<K,V>> iterator() {
224.1755 +                return new SubMapEntryIterator(absLowest(), absHighFence());
224.1756 +            }
224.1757 +        }
224.1758 +
224.1759 +        public Set<Map.Entry<K,V>> entrySet() {
224.1760 +            EntrySetView es = entrySetView;
224.1761 +            return (es != null) ? es : new AscendingEntrySetView();
224.1762 +        }
224.1763 +
224.1764 +        TreeMap.Entry<K,V> subLowest()       { return absLowest(); }
224.1765 +        TreeMap.Entry<K,V> subHighest()      { return absHighest(); }
224.1766 +        TreeMap.Entry<K,V> subCeiling(K key) { return absCeiling(key); }
224.1767 +        TreeMap.Entry<K,V> subHigher(K key)  { return absHigher(key); }
224.1768 +        TreeMap.Entry<K,V> subFloor(K key)   { return absFloor(key); }
224.1769 +        TreeMap.Entry<K,V> subLower(K key)   { return absLower(key); }
224.1770 +    }
224.1771 +
224.1772 +    /**
224.1773 +     * @serial include
224.1774 +     */
224.1775 +    static final class DescendingSubMap<K,V>  extends NavigableSubMap<K,V> {
224.1776 +        private static final long serialVersionUID = 912986545866120460L;
224.1777 +        DescendingSubMap(TreeMap<K,V> m,
224.1778 +                        boolean fromStart, K lo, boolean loInclusive,
224.1779 +                        boolean toEnd,     K hi, boolean hiInclusive) {
224.1780 +            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
224.1781 +        }
224.1782 +
224.1783 +        private final Comparator<? super K> reverseComparator =
224.1784 +            Collections.reverseOrder(m.comparator);
224.1785 +
224.1786 +        public Comparator<? super K> comparator() {
224.1787 +            return reverseComparator;
224.1788 +        }
224.1789 +
224.1790 +        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
224.1791 +                                        K toKey,   boolean toInclusive) {
224.1792 +            if (!inRange(fromKey, fromInclusive))
224.1793 +                throw new IllegalArgumentException("fromKey out of range");
224.1794 +            if (!inRange(toKey, toInclusive))
224.1795 +                throw new IllegalArgumentException("toKey out of range");
224.1796 +            return new DescendingSubMap(m,
224.1797 +                                        false, toKey,   toInclusive,
224.1798 +                                        false, fromKey, fromInclusive);
224.1799 +        }
224.1800 +
224.1801 +        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
224.1802 +            if (!inRange(toKey, inclusive))
224.1803 +                throw new IllegalArgumentException("toKey out of range");
224.1804 +            return new DescendingSubMap(m,
224.1805 +                                        false, toKey, inclusive,
224.1806 +                                        toEnd, hi,    hiInclusive);
224.1807 +        }
224.1808 +
224.1809 +        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
224.1810 +            if (!inRange(fromKey, inclusive))
224.1811 +                throw new IllegalArgumentException("fromKey out of range");
224.1812 +            return new DescendingSubMap(m,
224.1813 +                                        fromStart, lo, loInclusive,
224.1814 +                                        false, fromKey, inclusive);
224.1815 +        }
224.1816 +
224.1817 +        public NavigableMap<K,V> descendingMap() {
224.1818 +            NavigableMap<K,V> mv = descendingMapView;
224.1819 +            return (mv != null) ? mv :
224.1820 +                (descendingMapView =
224.1821 +                 new AscendingSubMap(m,
224.1822 +                                     fromStart, lo, loInclusive,
224.1823 +                                     toEnd,     hi, hiInclusive));
224.1824 +        }
224.1825 +
224.1826 +        Iterator<K> keyIterator() {
224.1827 +            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
224.1828 +        }
224.1829 +
224.1830 +        Iterator<K> descendingKeyIterator() {
224.1831 +            return new SubMapKeyIterator(absLowest(), absHighFence());
224.1832 +        }
224.1833 +
224.1834 +        final class DescendingEntrySetView extends EntrySetView {
224.1835 +            public Iterator<Map.Entry<K,V>> iterator() {
224.1836 +                return new DescendingSubMapEntryIterator(absHighest(), absLowFence());
224.1837 +            }
224.1838 +        }
224.1839 +
224.1840 +        public Set<Map.Entry<K,V>> entrySet() {
224.1841 +            EntrySetView es = entrySetView;
224.1842 +            return (es != null) ? es : new DescendingEntrySetView();
224.1843 +        }
224.1844 +
224.1845 +        TreeMap.Entry<K,V> subLowest()       { return absHighest(); }
224.1846 +        TreeMap.Entry<K,V> subHighest()      { return absLowest(); }
224.1847 +        TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); }
224.1848 +        TreeMap.Entry<K,V> subHigher(K key)  { return absLower(key); }
224.1849 +        TreeMap.Entry<K,V> subFloor(K key)   { return absCeiling(key); }
224.1850 +        TreeMap.Entry<K,V> subLower(K key)   { return absHigher(key); }
224.1851 +    }
224.1852 +
224.1853 +    /**
224.1854 +     * This class exists solely for the sake of serialization
224.1855 +     * compatibility with previous releases of TreeMap that did not
224.1856 +     * support NavigableMap.  It translates an old-version SubMap into
224.1857 +     * a new-version AscendingSubMap. This class is never otherwise
224.1858 +     * used.
224.1859 +     *
224.1860 +     * @serial include
224.1861 +     */
224.1862 +    private class SubMap extends AbstractMap<K,V>
224.1863 +        implements SortedMap<K,V>, java.io.Serializable {
224.1864 +        private static final long serialVersionUID = -6520786458950516097L;
224.1865 +        private boolean fromStart = false, toEnd = false;
224.1866 +        private K fromKey, toKey;
224.1867 +        private Object readResolve() {
224.1868 +            return new AscendingSubMap(TreeMap.this,
224.1869 +                                       fromStart, fromKey, true,
224.1870 +                                       toEnd, toKey, false);
224.1871 +        }
224.1872 +        public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); }
224.1873 +        public K lastKey() { throw new InternalError(); }
224.1874 +        public K firstKey() { throw new InternalError(); }
224.1875 +        public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); }
224.1876 +        public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); }
224.1877 +        public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); }
224.1878 +        public Comparator<? super K> comparator() { throw new InternalError(); }
224.1879 +    }
224.1880 +
224.1881 +
224.1882 +    // Red-black mechanics
224.1883 +
224.1884 +    private static final boolean RED   = false;
224.1885 +    private static final boolean BLACK = true;
224.1886 +
224.1887 +    /**
224.1888 +     * Node in the Tree.  Doubles as a means to pass key-value pairs back to
224.1889 +     * user (see Map.Entry).
224.1890 +     */
224.1891 +
224.1892 +    static final class Entry<K,V> implements Map.Entry<K,V> {
224.1893 +        K key;
224.1894 +        V value;
224.1895 +        Entry<K,V> left = null;
224.1896 +        Entry<K,V> right = null;
224.1897 +        Entry<K,V> parent;
224.1898 +        boolean color = BLACK;
224.1899 +
224.1900 +        /**
224.1901 +         * Make a new cell with given key, value, and parent, and with
224.1902 +         * {@code null} child links, and BLACK color.
224.1903 +         */
224.1904 +        Entry(K key, V value, Entry<K,V> parent) {
224.1905 +            this.key = key;
224.1906 +            this.value = value;
224.1907 +            this.parent = parent;
224.1908 +        }
224.1909 +
224.1910 +        /**
224.1911 +         * Returns the key.
224.1912 +         *
224.1913 +         * @return the key
224.1914 +         */
224.1915 +        public K getKey() {
224.1916 +            return key;
224.1917 +        }
224.1918 +
224.1919 +        /**
224.1920 +         * Returns the value associated with the key.
224.1921 +         *
224.1922 +         * @return the value associated with the key
224.1923 +         */
224.1924 +        public V getValue() {
224.1925 +            return value;
224.1926 +        }
224.1927 +
224.1928 +        /**
224.1929 +         * Replaces the value currently associated with the key with the given
224.1930 +         * value.
224.1931 +         *
224.1932 +         * @return the value associated with the key before this method was
224.1933 +         *         called
224.1934 +         */
224.1935 +        public V setValue(V value) {
224.1936 +            V oldValue = this.value;
224.1937 +            this.value = value;
224.1938 +            return oldValue;
224.1939 +        }
224.1940 +
224.1941 +        public boolean equals(Object o) {
224.1942 +            if (!(o instanceof Map.Entry))
224.1943 +                return false;
224.1944 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
224.1945 +
224.1946 +            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
224.1947 +        }
224.1948 +
224.1949 +        public int hashCode() {
224.1950 +            int keyHash = (key==null ? 0 : key.hashCode());
224.1951 +            int valueHash = (value==null ? 0 : value.hashCode());
224.1952 +            return keyHash ^ valueHash;
224.1953 +        }
224.1954 +
224.1955 +        public String toString() {
224.1956 +            return key + "=" + value;
224.1957 +        }
224.1958 +    }
224.1959 +
224.1960 +    /**
224.1961 +     * Returns the first Entry in the TreeMap (according to the TreeMap's
224.1962 +     * key-sort function).  Returns null if the TreeMap is empty.
224.1963 +     */
224.1964 +    final Entry<K,V> getFirstEntry() {
224.1965 +        Entry<K,V> p = root;
224.1966 +        if (p != null)
224.1967 +            while (p.left != null)
224.1968 +                p = p.left;
224.1969 +        return p;
224.1970 +    }
224.1971 +
224.1972 +    /**
224.1973 +     * Returns the last Entry in the TreeMap (according to the TreeMap's
224.1974 +     * key-sort function).  Returns null if the TreeMap is empty.
224.1975 +     */
224.1976 +    final Entry<K,V> getLastEntry() {
224.1977 +        Entry<K,V> p = root;
224.1978 +        if (p != null)
224.1979 +            while (p.right != null)
224.1980 +                p = p.right;
224.1981 +        return p;
224.1982 +    }
224.1983 +
224.1984 +    /**
224.1985 +     * Returns the successor of the specified Entry, or null if no such.
224.1986 +     */
224.1987 +    static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
224.1988 +        if (t == null)
224.1989 +            return null;
224.1990 +        else if (t.right != null) {
224.1991 +            Entry<K,V> p = t.right;
224.1992 +            while (p.left != null)
224.1993 +                p = p.left;
224.1994 +            return p;
224.1995 +        } else {
224.1996 +            Entry<K,V> p = t.parent;
224.1997 +            Entry<K,V> ch = t;
224.1998 +            while (p != null && ch == p.right) {
224.1999 +                ch = p;
224.2000 +                p = p.parent;
224.2001 +            }
224.2002 +            return p;
224.2003 +        }
224.2004 +    }
224.2005 +
224.2006 +    /**
224.2007 +     * Returns the predecessor of the specified Entry, or null if no such.
224.2008 +     */
224.2009 +    static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
224.2010 +        if (t == null)
224.2011 +            return null;
224.2012 +        else if (t.left != null) {
224.2013 +            Entry<K,V> p = t.left;
224.2014 +            while (p.right != null)
224.2015 +                p = p.right;
224.2016 +            return p;
224.2017 +        } else {
224.2018 +            Entry<K,V> p = t.parent;
224.2019 +            Entry<K,V> ch = t;
224.2020 +            while (p != null && ch == p.left) {
224.2021 +                ch = p;
224.2022 +                p = p.parent;
224.2023 +            }
224.2024 +            return p;
224.2025 +        }
224.2026 +    }
224.2027 +
224.2028 +    /**
224.2029 +     * Balancing operations.
224.2030 +     *
224.2031 +     * Implementations of rebalancings during insertion and deletion are
224.2032 +     * slightly different than the CLR version.  Rather than using dummy
224.2033 +     * nilnodes, we use a set of accessors that deal properly with null.  They
224.2034 +     * are used to avoid messiness surrounding nullness checks in the main
224.2035 +     * algorithms.
224.2036 +     */
224.2037 +
224.2038 +    private static <K,V> boolean colorOf(Entry<K,V> p) {
224.2039 +        return (p == null ? BLACK : p.color);
224.2040 +    }
224.2041 +
224.2042 +    private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) {
224.2043 +        return (p == null ? null: p.parent);
224.2044 +    }
224.2045 +
224.2046 +    private static <K,V> void setColor(Entry<K,V> p, boolean c) {
224.2047 +        if (p != null)
224.2048 +            p.color = c;
224.2049 +    }
224.2050 +
224.2051 +    private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) {
224.2052 +        return (p == null) ? null: p.left;
224.2053 +    }
224.2054 +
224.2055 +    private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) {
224.2056 +        return (p == null) ? null: p.right;
224.2057 +    }
224.2058 +
224.2059 +    /** From CLR */
224.2060 +    private void rotateLeft(Entry<K,V> p) {
224.2061 +        if (p != null) {
224.2062 +            Entry<K,V> r = p.right;
224.2063 +            p.right = r.left;
224.2064 +            if (r.left != null)
224.2065 +                r.left.parent = p;
224.2066 +            r.parent = p.parent;
224.2067 +            if (p.parent == null)
224.2068 +                root = r;
224.2069 +            else if (p.parent.left == p)
224.2070 +                p.parent.left = r;
224.2071 +            else
224.2072 +                p.parent.right = r;
224.2073 +            r.left = p;
224.2074 +            p.parent = r;
224.2075 +        }
224.2076 +    }
224.2077 +
224.2078 +    /** From CLR */
224.2079 +    private void rotateRight(Entry<K,V> p) {
224.2080 +        if (p != null) {
224.2081 +            Entry<K,V> l = p.left;
224.2082 +            p.left = l.right;
224.2083 +            if (l.right != null) l.right.parent = p;
224.2084 +            l.parent = p.parent;
224.2085 +            if (p.parent == null)
224.2086 +                root = l;
224.2087 +            else if (p.parent.right == p)
224.2088 +                p.parent.right = l;
224.2089 +            else p.parent.left = l;
224.2090 +            l.right = p;
224.2091 +            p.parent = l;
224.2092 +        }
224.2093 +    }
224.2094 +
224.2095 +    /** From CLR */
224.2096 +    private void fixAfterInsertion(Entry<K,V> x) {
224.2097 +        x.color = RED;
224.2098 +
224.2099 +        while (x != null && x != root && x.parent.color == RED) {
224.2100 +            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
224.2101 +                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
224.2102 +                if (colorOf(y) == RED) {
224.2103 +                    setColor(parentOf(x), BLACK);
224.2104 +                    setColor(y, BLACK);
224.2105 +                    setColor(parentOf(parentOf(x)), RED);
224.2106 +                    x = parentOf(parentOf(x));
224.2107 +                } else {
224.2108 +                    if (x == rightOf(parentOf(x))) {
224.2109 +                        x = parentOf(x);
224.2110 +                        rotateLeft(x);
224.2111 +                    }
224.2112 +                    setColor(parentOf(x), BLACK);
224.2113 +                    setColor(parentOf(parentOf(x)), RED);
224.2114 +                    rotateRight(parentOf(parentOf(x)));
224.2115 +                }
224.2116 +            } else {
224.2117 +                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
224.2118 +                if (colorOf(y) == RED) {
224.2119 +                    setColor(parentOf(x), BLACK);
224.2120 +                    setColor(y, BLACK);
224.2121 +                    setColor(parentOf(parentOf(x)), RED);
224.2122 +                    x = parentOf(parentOf(x));
224.2123 +                } else {
224.2124 +                    if (x == leftOf(parentOf(x))) {
224.2125 +                        x = parentOf(x);
224.2126 +                        rotateRight(x);
224.2127 +                    }
224.2128 +                    setColor(parentOf(x), BLACK);
224.2129 +                    setColor(parentOf(parentOf(x)), RED);
224.2130 +                    rotateLeft(parentOf(parentOf(x)));
224.2131 +                }
224.2132 +            }
224.2133 +        }
224.2134 +        root.color = BLACK;
224.2135 +    }
224.2136 +
224.2137 +    /**
224.2138 +     * Delete node p, and then rebalance the tree.
224.2139 +     */
224.2140 +    private void deleteEntry(Entry<K,V> p) {
224.2141 +        modCount++;
224.2142 +        size--;
224.2143 +
224.2144 +        // If strictly internal, copy successor's element to p and then make p
224.2145 +        // point to successor.
224.2146 +        if (p.left != null && p.right != null) {
224.2147 +            Entry<K,V> s = successor(p);
224.2148 +            p.key = s.key;
224.2149 +            p.value = s.value;
224.2150 +            p = s;
224.2151 +        } // p has 2 children
224.2152 +
224.2153 +        // Start fixup at replacement node, if it exists.
224.2154 +        Entry<K,V> replacement = (p.left != null ? p.left : p.right);
224.2155 +
224.2156 +        if (replacement != null) {
224.2157 +            // Link replacement to parent
224.2158 +            replacement.parent = p.parent;
224.2159 +            if (p.parent == null)
224.2160 +                root = replacement;
224.2161 +            else if (p == p.parent.left)
224.2162 +                p.parent.left  = replacement;
224.2163 +            else
224.2164 +                p.parent.right = replacement;
224.2165 +
224.2166 +            // Null out links so they are OK to use by fixAfterDeletion.
224.2167 +            p.left = p.right = p.parent = null;
224.2168 +
224.2169 +            // Fix replacement
224.2170 +            if (p.color == BLACK)
224.2171 +                fixAfterDeletion(replacement);
224.2172 +        } else if (p.parent == null) { // return if we are the only node.
224.2173 +            root = null;
224.2174 +        } else { //  No children. Use self as phantom replacement and unlink.
224.2175 +            if (p.color == BLACK)
224.2176 +                fixAfterDeletion(p);
224.2177 +
224.2178 +            if (p.parent != null) {
224.2179 +                if (p == p.parent.left)
224.2180 +                    p.parent.left = null;
224.2181 +                else if (p == p.parent.right)
224.2182 +                    p.parent.right = null;
224.2183 +                p.parent = null;
224.2184 +            }
224.2185 +        }
224.2186 +    }
224.2187 +
224.2188 +    /** From CLR */
224.2189 +    private void fixAfterDeletion(Entry<K,V> x) {
224.2190 +        while (x != root && colorOf(x) == BLACK) {
224.2191 +            if (x == leftOf(parentOf(x))) {
224.2192 +                Entry<K,V> sib = rightOf(parentOf(x));
224.2193 +
224.2194 +                if (colorOf(sib) == RED) {
224.2195 +                    setColor(sib, BLACK);
224.2196 +                    setColor(parentOf(x), RED);
224.2197 +                    rotateLeft(parentOf(x));
224.2198 +                    sib = rightOf(parentOf(x));
224.2199 +                }
224.2200 +
224.2201 +                if (colorOf(leftOf(sib))  == BLACK &&
224.2202 +                    colorOf(rightOf(sib)) == BLACK) {
224.2203 +                    setColor(sib, RED);
224.2204 +                    x = parentOf(x);
224.2205 +                } else {
224.2206 +                    if (colorOf(rightOf(sib)) == BLACK) {
224.2207 +                        setColor(leftOf(sib), BLACK);
224.2208 +                        setColor(sib, RED);
224.2209 +                        rotateRight(sib);
224.2210 +                        sib = rightOf(parentOf(x));
224.2211 +                    }
224.2212 +                    setColor(sib, colorOf(parentOf(x)));
224.2213 +                    setColor(parentOf(x), BLACK);
224.2214 +                    setColor(rightOf(sib), BLACK);
224.2215 +                    rotateLeft(parentOf(x));
224.2216 +                    x = root;
224.2217 +                }
224.2218 +            } else { // symmetric
224.2219 +                Entry<K,V> sib = leftOf(parentOf(x));
224.2220 +
224.2221 +                if (colorOf(sib) == RED) {
224.2222 +                    setColor(sib, BLACK);
224.2223 +                    setColor(parentOf(x), RED);
224.2224 +                    rotateRight(parentOf(x));
224.2225 +                    sib = leftOf(parentOf(x));
224.2226 +                }
224.2227 +
224.2228 +                if (colorOf(rightOf(sib)) == BLACK &&
224.2229 +                    colorOf(leftOf(sib)) == BLACK) {
224.2230 +                    setColor(sib, RED);
224.2231 +                    x = parentOf(x);
224.2232 +                } else {
224.2233 +                    if (colorOf(leftOf(sib)) == BLACK) {
224.2234 +                        setColor(rightOf(sib), BLACK);
224.2235 +                        setColor(sib, RED);
224.2236 +                        rotateLeft(sib);
224.2237 +                        sib = leftOf(parentOf(x));
224.2238 +                    }
224.2239 +                    setColor(sib, colorOf(parentOf(x)));
224.2240 +                    setColor(parentOf(x), BLACK);
224.2241 +                    setColor(leftOf(sib), BLACK);
224.2242 +                    rotateRight(parentOf(x));
224.2243 +                    x = root;
224.2244 +                }
224.2245 +            }
224.2246 +        }
224.2247 +
224.2248 +        setColor(x, BLACK);
224.2249 +    }
224.2250 +
224.2251 +    private static final long serialVersionUID = 919286545866124006L;
224.2252 +
224.2253 +    /**
224.2254 +     * Save the state of the {@code TreeMap} instance to a stream (i.e.,
224.2255 +     * serialize it).
224.2256 +     *
224.2257 +     * @serialData The <em>size</em> of the TreeMap (the number of key-value
224.2258 +     *             mappings) is emitted (int), followed by the key (Object)
224.2259 +     *             and value (Object) for each key-value mapping represented
224.2260 +     *             by the TreeMap. The key-value mappings are emitted in
224.2261 +     *             key-order (as determined by the TreeMap's Comparator,
224.2262 +     *             or by the keys' natural ordering if the TreeMap has no
224.2263 +     *             Comparator).
224.2264 +     */
224.2265 +    private void writeObject(java.io.ObjectOutputStream s)
224.2266 +        throws java.io.IOException {
224.2267 +        // Write out the Comparator and any hidden stuff
224.2268 +        s.defaultWriteObject();
224.2269 +
224.2270 +        // Write out size (number of Mappings)
224.2271 +        s.writeInt(size);
224.2272 +
224.2273 +        // Write out keys and values (alternating)
224.2274 +        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
224.2275 +            Map.Entry<K,V> e = i.next();
224.2276 +            s.writeObject(e.getKey());
224.2277 +            s.writeObject(e.getValue());
224.2278 +        }
224.2279 +    }
224.2280 +
224.2281 +    /**
224.2282 +     * Reconstitute the {@code TreeMap} instance from a stream (i.e.,
224.2283 +     * deserialize it).
224.2284 +     */
224.2285 +    private void readObject(final java.io.ObjectInputStream s)
224.2286 +        throws java.io.IOException, ClassNotFoundException {
224.2287 +        // Read in the Comparator and any hidden stuff
224.2288 +        s.defaultReadObject();
224.2289 +
224.2290 +        // Read in size
224.2291 +        int size = s.readInt();
224.2292 +
224.2293 +        buildFromSorted(size, null, s, null);
224.2294 +    }
224.2295 +
224.2296 +    /** Intended to be called only from TreeSet.readObject */
224.2297 +    void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal)
224.2298 +        throws java.io.IOException, ClassNotFoundException {
224.2299 +        buildFromSorted(size, null, s, defaultVal);
224.2300 +    }
224.2301 +
224.2302 +    /** Intended to be called only from TreeSet.addAll */
224.2303 +    void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) {
224.2304 +        try {
224.2305 +            buildFromSorted(set.size(), set.iterator(), null, defaultVal);
224.2306 +        } catch (java.io.IOException cannotHappen) {
224.2307 +        } catch (ClassNotFoundException cannotHappen) {
224.2308 +        }
224.2309 +    }
224.2310 +
224.2311 +
224.2312 +    /**
224.2313 +     * Linear time tree building algorithm from sorted data.  Can accept keys
224.2314 +     * and/or values from iterator or stream. This leads to too many
224.2315 +     * parameters, but seems better than alternatives.  The four formats
224.2316 +     * that this method accepts are:
224.2317 +     *
224.2318 +     *    1) An iterator of Map.Entries.  (it != null, defaultVal == null).
224.2319 +     *    2) An iterator of keys.         (it != null, defaultVal != null).
224.2320 +     *    3) A stream of alternating serialized keys and values.
224.2321 +     *                                   (it == null, defaultVal == null).
224.2322 +     *    4) A stream of serialized keys. (it == null, defaultVal != null).
224.2323 +     *
224.2324 +     * It is assumed that the comparator of the TreeMap is already set prior
224.2325 +     * to calling this method.
224.2326 +     *
224.2327 +     * @param size the number of keys (or key-value pairs) to be read from
224.2328 +     *        the iterator or stream
224.2329 +     * @param it If non-null, new entries are created from entries
224.2330 +     *        or keys read from this iterator.
224.2331 +     * @param str If non-null, new entries are created from keys and
224.2332 +     *        possibly values read from this stream in serialized form.
224.2333 +     *        Exactly one of it and str should be non-null.
224.2334 +     * @param defaultVal if non-null, this default value is used for
224.2335 +     *        each value in the map.  If null, each value is read from
224.2336 +     *        iterator or stream, as described above.
224.2337 +     * @throws IOException propagated from stream reads. This cannot
224.2338 +     *         occur if str is null.
224.2339 +     * @throws ClassNotFoundException propagated from readObject.
224.2340 +     *         This cannot occur if str is null.
224.2341 +     */
224.2342 +    private void buildFromSorted(int size, Iterator it,
224.2343 +                                 java.io.ObjectInputStream str,
224.2344 +                                 V defaultVal)
224.2345 +        throws  java.io.IOException, ClassNotFoundException {
224.2346 +        this.size = size;
224.2347 +        root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
224.2348 +                               it, str, defaultVal);
224.2349 +    }
224.2350 +
224.2351 +    /**
224.2352 +     * Recursive "helper method" that does the real work of the
224.2353 +     * previous method.  Identically named parameters have
224.2354 +     * identical definitions.  Additional parameters are documented below.
224.2355 +     * It is assumed that the comparator and size fields of the TreeMap are
224.2356 +     * already set prior to calling this method.  (It ignores both fields.)
224.2357 +     *
224.2358 +     * @param level the current level of tree. Initial call should be 0.
224.2359 +     * @param lo the first element index of this subtree. Initial should be 0.
224.2360 +     * @param hi the last element index of this subtree.  Initial should be
224.2361 +     *        size-1.
224.2362 +     * @param redLevel the level at which nodes should be red.
224.2363 +     *        Must be equal to computeRedLevel for tree of this size.
224.2364 +     */
224.2365 +    private final Entry<K,V> buildFromSorted(int level, int lo, int hi,
224.2366 +                                             int redLevel,
224.2367 +                                             Iterator it,
224.2368 +                                             java.io.ObjectInputStream str,
224.2369 +                                             V defaultVal)
224.2370 +        throws  java.io.IOException, ClassNotFoundException {
224.2371 +        /*
224.2372 +         * Strategy: The root is the middlemost element. To get to it, we
224.2373 +         * have to first recursively construct the entire left subtree,
224.2374 +         * so as to grab all of its elements. We can then proceed with right
224.2375 +         * subtree.
224.2376 +         *
224.2377 +         * The lo and hi arguments are the minimum and maximum
224.2378 +         * indices to pull out of the iterator or stream for current subtree.
224.2379 +         * They are not actually indexed, we just proceed sequentially,
224.2380 +         * ensuring that items are extracted in corresponding order.
224.2381 +         */
224.2382 +
224.2383 +        if (hi < lo) return null;
224.2384 +
224.2385 +        int mid = (lo + hi) >>> 1;
224.2386 +
224.2387 +        Entry<K,V> left  = null;
224.2388 +        if (lo < mid)
224.2389 +            left = buildFromSorted(level+1, lo, mid - 1, redLevel,
224.2390 +                                   it, str, defaultVal);
224.2391 +
224.2392 +        // extract key and/or value from iterator or stream
224.2393 +        K key;
224.2394 +        V value;
224.2395 +        if (it != null) {
224.2396 +            if (defaultVal==null) {
224.2397 +                Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next();
224.2398 +                key = entry.getKey();
224.2399 +                value = entry.getValue();
224.2400 +            } else {
224.2401 +                key = (K)it.next();
224.2402 +                value = defaultVal;
224.2403 +            }
224.2404 +        } else { // use stream
224.2405 +            key = (K) str.readObject();
224.2406 +            value = (defaultVal != null ? defaultVal : (V) str.readObject());
224.2407 +        }
224.2408 +
224.2409 +        Entry<K,V> middle =  new Entry<>(key, value, null);
224.2410 +
224.2411 +        // color nodes in non-full bottommost level red
224.2412 +        if (level == redLevel)
224.2413 +            middle.color = RED;
224.2414 +
224.2415 +        if (left != null) {
224.2416 +            middle.left = left;
224.2417 +            left.parent = middle;
224.2418 +        }
224.2419 +
224.2420 +        if (mid < hi) {
224.2421 +            Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel,
224.2422 +                                               it, str, defaultVal);
224.2423 +            middle.right = right;
224.2424 +            right.parent = middle;
224.2425 +        }
224.2426 +
224.2427 +        return middle;
224.2428 +    }
224.2429 +
224.2430 +    /**
224.2431 +     * Find the level down to which to assign all nodes BLACK.  This is the
224.2432 +     * last `full' level of the complete binary tree produced by
224.2433 +     * buildTree. The remaining nodes are colored RED. (This makes a `nice'
224.2434 +     * set of color assignments wrt future insertions.) This level number is
224.2435 +     * computed by finding the number of splits needed to reach the zeroeth
224.2436 +     * node.  (The answer is ~lg(N), but in any case must be computed by same
224.2437 +     * quick O(lg(N)) loop.)
224.2438 +     */
224.2439 +    private static int computeRedLevel(int sz) {
224.2440 +        int level = 0;
224.2441 +        for (int m = sz - 1; m >= 0; m = m / 2 - 1)
224.2442 +            level++;
224.2443 +        return level;
224.2444 +    }
224.2445 +}
   225.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   225.2 +++ b/rt/emul/compact/src/main/java/java/util/TreeSet.java	Wed Apr 30 15:04:10 2014 +0200
   225.3 @@ -0,0 +1,539 @@
   225.4 +/*
   225.5 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
   225.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   225.7 + *
   225.8 + * This code is free software; you can redistribute it and/or modify it
   225.9 + * under the terms of the GNU General Public License version 2 only, as
  225.10 + * published by the Free Software Foundation.  Oracle designates this
  225.11 + * particular file as subject to the "Classpath" exception as provided
  225.12 + * by Oracle in the LICENSE file that accompanied this code.
  225.13 + *
  225.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  225.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  225.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  225.17 + * version 2 for more details (a copy is included in the LICENSE file that
  225.18 + * accompanied this code).
  225.19 + *
  225.20 + * You should have received a copy of the GNU General Public License version
  225.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  225.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  225.23 + *
  225.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  225.25 + * or visit www.oracle.com if you need additional information or have any
  225.26 + * questions.
  225.27 + */
  225.28 +
  225.29 +package java.util;
  225.30 +
  225.31 +/**
  225.32 + * A {@link NavigableSet} implementation based on a {@link TreeMap}.
  225.33 + * The elements are ordered using their {@linkplain Comparable natural
  225.34 + * ordering}, or by a {@link Comparator} provided at set creation
  225.35 + * time, depending on which constructor is used.
  225.36 + *
  225.37 + * <p>This implementation provides guaranteed log(n) time cost for the basic
  225.38 + * operations ({@code add}, {@code remove} and {@code contains}).
  225.39 + *
  225.40 + * <p>Note that the ordering maintained by a set (whether or not an explicit
  225.41 + * comparator is provided) must be <i>consistent with equals</i> if it is to
  225.42 + * correctly implement the {@code Set} interface.  (See {@code Comparable}
  225.43 + * or {@code Comparator} for a precise definition of <i>consistent with
  225.44 + * equals</i>.)  This is so because the {@code Set} interface is defined in
  225.45 + * terms of the {@code equals} operation, but a {@code TreeSet} instance
  225.46 + * performs all element comparisons using its {@code compareTo} (or
  225.47 + * {@code compare}) method, so two elements that are deemed equal by this method
  225.48 + * are, from the standpoint of the set, equal.  The behavior of a set
  225.49 + * <i>is</i> well-defined even if its ordering is inconsistent with equals; it
  225.50 + * just fails to obey the general contract of the {@code Set} interface.
  225.51 + *
  225.52 + * <p><strong>Note that this implementation is not synchronized.</strong>
  225.53 + * If multiple threads access a tree set concurrently, and at least one
  225.54 + * of the threads modifies the set, it <i>must</i> be synchronized
  225.55 + * externally.  This is typically accomplished by synchronizing on some
  225.56 + * object that naturally encapsulates the set.
  225.57 + * If no such object exists, the set should be "wrapped" using the
  225.58 + * {@link Collections#synchronizedSortedSet Collections.synchronizedSortedSet}
  225.59 + * method.  This is best done at creation time, to prevent accidental
  225.60 + * unsynchronized access to the set: <pre>
  225.61 + *   SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));</pre>
  225.62 + *
  225.63 + * <p>The iterators returned by this class's {@code iterator} method are
  225.64 + * <i>fail-fast</i>: if the set is modified at any time after the iterator is
  225.65 + * created, in any way except through the iterator's own {@code remove}
  225.66 + * method, the iterator will throw a {@link ConcurrentModificationException}.
  225.67 + * Thus, in the face of concurrent modification, the iterator fails quickly
  225.68 + * and cleanly, rather than risking arbitrary, non-deterministic behavior at
  225.69 + * an undetermined time in the future.
  225.70 + *
  225.71 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  225.72 + * as it is, generally speaking, impossible to make any hard guarantees in the
  225.73 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
  225.74 + * throw {@code ConcurrentModificationException} on a best-effort basis.
  225.75 + * Therefore, it would be wrong to write a program that depended on this
  225.76 + * exception for its correctness:   <i>the fail-fast behavior of iterators
  225.77 + * should be used only to detect bugs.</i>
  225.78 + *
  225.79 + * <p>This class is a member of the
  225.80 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  225.81 + * Java Collections Framework</a>.
  225.82 + *
  225.83 + * @param <E> the type of elements maintained by this set
  225.84 + *
  225.85 + * @author  Josh Bloch
  225.86 + * @see     Collection
  225.87 + * @see     Set
  225.88 + * @see     HashSet
  225.89 + * @see     Comparable
  225.90 + * @see     Comparator
  225.91 + * @see     TreeMap
  225.92 + * @since   1.2
  225.93 + */
  225.94 +
  225.95 +public class TreeSet<E> extends AbstractSet<E>
  225.96 +    implements NavigableSet<E>, Cloneable, java.io.Serializable
  225.97 +{
  225.98 +    /**
  225.99 +     * The backing map.
 225.100 +     */
 225.101 +    private transient NavigableMap<E,Object> m;
 225.102 +
 225.103 +    // Dummy value to associate with an Object in the backing Map
 225.104 +    private static final Object PRESENT = new Object();
 225.105 +
 225.106 +    /**
 225.107 +     * Constructs a set backed by the specified navigable map.
 225.108 +     */
 225.109 +    TreeSet(NavigableMap<E,Object> m) {
 225.110 +        this.m = m;
 225.111 +    }
 225.112 +
 225.113 +    /**
 225.114 +     * Constructs a new, empty tree set, sorted according to the
 225.115 +     * natural ordering of its elements.  All elements inserted into
 225.116 +     * the set must implement the {@link Comparable} interface.
 225.117 +     * Furthermore, all such elements must be <i>mutually
 225.118 +     * comparable</i>: {@code e1.compareTo(e2)} must not throw a
 225.119 +     * {@code ClassCastException} for any elements {@code e1} and
 225.120 +     * {@code e2} in the set.  If the user attempts to add an element
 225.121 +     * to the set that violates this constraint (for example, the user
 225.122 +     * attempts to add a string element to a set whose elements are
 225.123 +     * integers), the {@code add} call will throw a
 225.124 +     * {@code ClassCastException}.
 225.125 +     */
 225.126 +    public TreeSet() {
 225.127 +        this(new TreeMap<E,Object>());
 225.128 +    }
 225.129 +
 225.130 +    /**
 225.131 +     * Constructs a new, empty tree set, sorted according to the specified
 225.132 +     * comparator.  All elements inserted into the set must be <i>mutually
 225.133 +     * comparable</i> by the specified comparator: {@code comparator.compare(e1,
 225.134 +     * e2)} must not throw a {@code ClassCastException} for any elements
 225.135 +     * {@code e1} and {@code e2} in the set.  If the user attempts to add
 225.136 +     * an element to the set that violates this constraint, the
 225.137 +     * {@code add} call will throw a {@code ClassCastException}.
 225.138 +     *
 225.139 +     * @param comparator the comparator that will be used to order this set.
 225.140 +     *        If {@code null}, the {@linkplain Comparable natural
 225.141 +     *        ordering} of the elements will be used.
 225.142 +     */
 225.143 +    public TreeSet(Comparator<? super E> comparator) {
 225.144 +        this(new TreeMap<>(comparator));
 225.145 +    }
 225.146 +
 225.147 +    /**
 225.148 +     * Constructs a new tree set containing the elements in the specified
 225.149 +     * collection, sorted according to the <i>natural ordering</i> of its
 225.150 +     * elements.  All elements inserted into the set must implement the
 225.151 +     * {@link Comparable} interface.  Furthermore, all such elements must be
 225.152 +     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
 225.153 +     * {@code ClassCastException} for any elements {@code e1} and
 225.154 +     * {@code e2} in the set.
 225.155 +     *
 225.156 +     * @param c collection whose elements will comprise the new set
 225.157 +     * @throws ClassCastException if the elements in {@code c} are
 225.158 +     *         not {@link Comparable}, or are not mutually comparable
 225.159 +     * @throws NullPointerException if the specified collection is null
 225.160 +     */
 225.161 +    public TreeSet(Collection<? extends E> c) {
 225.162 +        this();
 225.163 +        addAll(c);
 225.164 +    }
 225.165 +
 225.166 +    /**
 225.167 +     * Constructs a new tree set containing the same elements and
 225.168 +     * using the same ordering as the specified sorted set.
 225.169 +     *
 225.170 +     * @param s sorted set whose elements will comprise the new set
 225.171 +     * @throws NullPointerException if the specified sorted set is null
 225.172 +     */
 225.173 +    public TreeSet(SortedSet<E> s) {
 225.174 +        this(s.comparator());
 225.175 +        addAll(s);
 225.176 +    }
 225.177 +
 225.178 +    /**
 225.179 +     * Returns an iterator over the elements in this set in ascending order.
 225.180 +     *
 225.181 +     * @return an iterator over the elements in this set in ascending order
 225.182 +     */
 225.183 +    public Iterator<E> iterator() {
 225.184 +        return m.navigableKeySet().iterator();
 225.185 +    }
 225.186 +
 225.187 +    /**
 225.188 +     * Returns an iterator over the elements in this set in descending order.
 225.189 +     *
 225.190 +     * @return an iterator over the elements in this set in descending order
 225.191 +     * @since 1.6
 225.192 +     */
 225.193 +    public Iterator<E> descendingIterator() {
 225.194 +        return m.descendingKeySet().iterator();
 225.195 +    }
 225.196 +
 225.197 +    /**
 225.198 +     * @since 1.6
 225.199 +     */
 225.200 +    public NavigableSet<E> descendingSet() {
 225.201 +        return new TreeSet<>(m.descendingMap());
 225.202 +    }
 225.203 +
 225.204 +    /**
 225.205 +     * Returns the number of elements in this set (its cardinality).
 225.206 +     *
 225.207 +     * @return the number of elements in this set (its cardinality)
 225.208 +     */
 225.209 +    public int size() {
 225.210 +        return m.size();
 225.211 +    }
 225.212 +
 225.213 +    /**
 225.214 +     * Returns {@code true} if this set contains no elements.
 225.215 +     *
 225.216 +     * @return {@code true} if this set contains no elements
 225.217 +     */
 225.218 +    public boolean isEmpty() {
 225.219 +        return m.isEmpty();
 225.220 +    }
 225.221 +
 225.222 +    /**
 225.223 +     * Returns {@code true} if this set contains the specified element.
 225.224 +     * More formally, returns {@code true} if and only if this set
 225.225 +     * contains an element {@code e} such that
 225.226 +     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
 225.227 +     *
 225.228 +     * @param o object to be checked for containment in this set
 225.229 +     * @return {@code true} if this set contains the specified element
 225.230 +     * @throws ClassCastException if the specified object cannot be compared
 225.231 +     *         with the elements currently in the set
 225.232 +     * @throws NullPointerException if the specified element is null
 225.233 +     *         and this set uses natural ordering, or its comparator
 225.234 +     *         does not permit null elements
 225.235 +     */
 225.236 +    public boolean contains(Object o) {
 225.237 +        return m.containsKey(o);
 225.238 +    }
 225.239 +
 225.240 +    /**
 225.241 +     * Adds the specified element to this set if it is not already present.
 225.242 +     * More formally, adds the specified element {@code e} to this set if
 225.243 +     * the set contains no element {@code e2} such that
 225.244 +     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
 225.245 +     * If this set already contains the element, the call leaves the set
 225.246 +     * unchanged and returns {@code false}.
 225.247 +     *
 225.248 +     * @param e element to be added to this set
 225.249 +     * @return {@code true} if this set did not already contain the specified
 225.250 +     *         element
 225.251 +     * @throws ClassCastException if the specified object cannot be compared
 225.252 +     *         with the elements currently in this set
 225.253 +     * @throws NullPointerException if the specified element is null
 225.254 +     *         and this set uses natural ordering, or its comparator
 225.255 +     *         does not permit null elements
 225.256 +     */
 225.257 +    public boolean add(E e) {
 225.258 +        return m.put(e, PRESENT)==null;
 225.259 +    }
 225.260 +
 225.261 +    /**
 225.262 +     * Removes the specified element from this set if it is present.
 225.263 +     * More formally, removes an element {@code e} such that
 225.264 +     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
 225.265 +     * if this set contains such an element.  Returns {@code true} if
 225.266 +     * this set contained the element (or equivalently, if this set
 225.267 +     * changed as a result of the call).  (This set will not contain the
 225.268 +     * element once the call returns.)
 225.269 +     *
 225.270 +     * @param o object to be removed from this set, if present
 225.271 +     * @return {@code true} if this set contained the specified element
 225.272 +     * @throws ClassCastException if the specified object cannot be compared
 225.273 +     *         with the elements currently in this set
 225.274 +     * @throws NullPointerException if the specified element is null
 225.275 +     *         and this set uses natural ordering, or its comparator
 225.276 +     *         does not permit null elements
 225.277 +     */
 225.278 +    public boolean remove(Object o) {
 225.279 +        return m.remove(o)==PRESENT;
 225.280 +    }
 225.281 +
 225.282 +    /**
 225.283 +     * Removes all of the elements from this set.
 225.284 +     * The set will be empty after this call returns.
 225.285 +     */
 225.286 +    public void clear() {
 225.287 +        m.clear();
 225.288 +    }
 225.289 +
 225.290 +    /**
 225.291 +     * Adds all of the elements in the specified collection to this set.
 225.292 +     *
 225.293 +     * @param c collection containing elements to be added to this set
 225.294 +     * @return {@code true} if this set changed as a result of the call
 225.295 +     * @throws ClassCastException if the elements provided cannot be compared
 225.296 +     *         with the elements currently in the set
 225.297 +     * @throws NullPointerException if the specified collection is null or
 225.298 +     *         if any element is null and this set uses natural ordering, or
 225.299 +     *         its comparator does not permit null elements
 225.300 +     */
 225.301 +    public  boolean addAll(Collection<? extends E> c) {
 225.302 +        // Use linear-time version if applicable
 225.303 +        if (m.size()==0 && c.size() > 0 &&
 225.304 +            c instanceof SortedSet &&
 225.305 +            m instanceof TreeMap) {
 225.306 +            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
 225.307 +            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
 225.308 +            Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
 225.309 +            Comparator<? super E> mc = map.comparator();
 225.310 +            if (cc==mc || (cc != null && cc.equals(mc))) {
 225.311 +                map.addAllForTreeSet(set, PRESENT);
 225.312 +                return true;
 225.313 +            }
 225.314 +        }
 225.315 +        return super.addAll(c);
 225.316 +    }
 225.317 +
 225.318 +    /**
 225.319 +     * @throws ClassCastException {@inheritDoc}
 225.320 +     * @throws NullPointerException if {@code fromElement} or {@code toElement}
 225.321 +     *         is null and this set uses natural ordering, or its comparator
 225.322 +     *         does not permit null elements
 225.323 +     * @throws IllegalArgumentException {@inheritDoc}
 225.324 +     * @since 1.6
 225.325 +     */
 225.326 +    public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
 225.327 +                                  E toElement,   boolean toInclusive) {
 225.328 +        return new TreeSet<>(m.subMap(fromElement, fromInclusive,
 225.329 +                                       toElement,   toInclusive));
 225.330 +    }
 225.331 +
 225.332 +    /**
 225.333 +     * @throws ClassCastException {@inheritDoc}
 225.334 +     * @throws NullPointerException if {@code toElement} is null and
 225.335 +     *         this set uses natural ordering, or its comparator does
 225.336 +     *         not permit null elements
 225.337 +     * @throws IllegalArgumentException {@inheritDoc}
 225.338 +     * @since 1.6
 225.339 +     */
 225.340 +    public NavigableSet<E> headSet(E toElement, boolean inclusive) {
 225.341 +        return new TreeSet<>(m.headMap(toElement, inclusive));
 225.342 +    }
 225.343 +
 225.344 +    /**
 225.345 +     * @throws ClassCastException {@inheritDoc}
 225.346 +     * @throws NullPointerException if {@code fromElement} is null and
 225.347 +     *         this set uses natural ordering, or its comparator does
 225.348 +     *         not permit null elements
 225.349 +     * @throws IllegalArgumentException {@inheritDoc}
 225.350 +     * @since 1.6
 225.351 +     */
 225.352 +    public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
 225.353 +        return new TreeSet<>(m.tailMap(fromElement, inclusive));
 225.354 +    }
 225.355 +
 225.356 +    /**
 225.357 +     * @throws ClassCastException {@inheritDoc}
 225.358 +     * @throws NullPointerException if {@code fromElement} or
 225.359 +     *         {@code toElement} is null and this set uses natural ordering,
 225.360 +     *         or its comparator does not permit null elements
 225.361 +     * @throws IllegalArgumentException {@inheritDoc}
 225.362 +     */
 225.363 +    public SortedSet<E> subSet(E fromElement, E toElement) {
 225.364 +        return subSet(fromElement, true, toElement, false);
 225.365 +    }
 225.366 +
 225.367 +    /**
 225.368 +     * @throws ClassCastException {@inheritDoc}
 225.369 +     * @throws NullPointerException if {@code toElement} is null
 225.370 +     *         and this set uses natural ordering, or its comparator does
 225.371 +     *         not permit null elements
 225.372 +     * @throws IllegalArgumentException {@inheritDoc}
 225.373 +     */
 225.374 +    public SortedSet<E> headSet(E toElement) {
 225.375 +        return headSet(toElement, false);
 225.376 +    }
 225.377 +
 225.378 +    /**
 225.379 +     * @throws ClassCastException {@inheritDoc}
 225.380 +     * @throws NullPointerException if {@code fromElement} is null
 225.381 +     *         and this set uses natural ordering, or its comparator does
 225.382 +     *         not permit null elements
 225.383 +     * @throws IllegalArgumentException {@inheritDoc}
 225.384 +     */
 225.385 +    public SortedSet<E> tailSet(E fromElement) {
 225.386 +        return tailSet(fromElement, true);
 225.387 +    }
 225.388 +
 225.389 +    public Comparator<? super E> comparator() {
 225.390 +        return m.comparator();
 225.391 +    }
 225.392 +
 225.393 +    /**
 225.394 +     * @throws NoSuchElementException {@inheritDoc}
 225.395 +     */
 225.396 +    public E first() {
 225.397 +        return m.firstKey();
 225.398 +    }
 225.399 +
 225.400 +    /**
 225.401 +     * @throws NoSuchElementException {@inheritDoc}
 225.402 +     */
 225.403 +    public E last() {
 225.404 +        return m.lastKey();
 225.405 +    }
 225.406 +
 225.407 +    // NavigableSet API methods
 225.408 +
 225.409 +    /**
 225.410 +     * @throws ClassCastException {@inheritDoc}
 225.411 +     * @throws NullPointerException if the specified element is null
 225.412 +     *         and this set uses natural ordering, or its comparator
 225.413 +     *         does not permit null elements
 225.414 +     * @since 1.6
 225.415 +     */
 225.416 +    public E lower(E e) {
 225.417 +        return m.lowerKey(e);
 225.418 +    }
 225.419 +
 225.420 +    /**
 225.421 +     * @throws ClassCastException {@inheritDoc}
 225.422 +     * @throws NullPointerException if the specified element is null
 225.423 +     *         and this set uses natural ordering, or its comparator
 225.424 +     *         does not permit null elements
 225.425 +     * @since 1.6
 225.426 +     */
 225.427 +    public E floor(E e) {
 225.428 +        return m.floorKey(e);
 225.429 +    }
 225.430 +
 225.431 +    /**
 225.432 +     * @throws ClassCastException {@inheritDoc}
 225.433 +     * @throws NullPointerException if the specified element is null
 225.434 +     *         and this set uses natural ordering, or its comparator
 225.435 +     *         does not permit null elements
 225.436 +     * @since 1.6
 225.437 +     */
 225.438 +    public E ceiling(E e) {
 225.439 +        return m.ceilingKey(e);
 225.440 +    }
 225.441 +
 225.442 +    /**
 225.443 +     * @throws ClassCastException {@inheritDoc}
 225.444 +     * @throws NullPointerException if the specified element is null
 225.445 +     *         and this set uses natural ordering, or its comparator
 225.446 +     *         does not permit null elements
 225.447 +     * @since 1.6
 225.448 +     */
 225.449 +    public E higher(E e) {
 225.450 +        return m.higherKey(e);
 225.451 +    }
 225.452 +
 225.453 +    /**
 225.454 +     * @since 1.6
 225.455 +     */
 225.456 +    public E pollFirst() {
 225.457 +        Map.Entry<E,?> e = m.pollFirstEntry();
 225.458 +        return (e == null) ? null : e.getKey();
 225.459 +    }
 225.460 +
 225.461 +    /**
 225.462 +     * @since 1.6
 225.463 +     */
 225.464 +    public E pollLast() {
 225.465 +        Map.Entry<E,?> e = m.pollLastEntry();
 225.466 +        return (e == null) ? null : e.getKey();
 225.467 +    }
 225.468 +
 225.469 +    /**
 225.470 +     * Returns a shallow copy of this {@code TreeSet} instance. (The elements
 225.471 +     * themselves are not cloned.)
 225.472 +     *
 225.473 +     * @return a shallow copy of this set
 225.474 +     */
 225.475 +    public Object clone() {
 225.476 +        TreeSet<E> clone = null;
 225.477 +        try {
 225.478 +            clone = (TreeSet<E>) super.clone();
 225.479 +        } catch (CloneNotSupportedException e) {
 225.480 +            throw new InternalError();
 225.481 +        }
 225.482 +
 225.483 +        clone.m = new TreeMap<>(m);
 225.484 +        return clone;
 225.485 +    }
 225.486 +
 225.487 +    /**
 225.488 +     * Save the state of the {@code TreeSet} instance to a stream (that is,
 225.489 +     * serialize it).
 225.490 +     *
 225.491 +     * @serialData Emits the comparator used to order this set, or
 225.492 +     *             {@code null} if it obeys its elements' natural ordering
 225.493 +     *             (Object), followed by the size of the set (the number of
 225.494 +     *             elements it contains) (int), followed by all of its
 225.495 +     *             elements (each an Object) in order (as determined by the
 225.496 +     *             set's Comparator, or by the elements' natural ordering if
 225.497 +     *             the set has no Comparator).
 225.498 +     */
 225.499 +    private void writeObject(java.io.ObjectOutputStream s)
 225.500 +        throws java.io.IOException {
 225.501 +        // Write out any hidden stuff
 225.502 +        s.defaultWriteObject();
 225.503 +
 225.504 +        // Write out Comparator
 225.505 +        s.writeObject(m.comparator());
 225.506 +
 225.507 +        // Write out size
 225.508 +        s.writeInt(m.size());
 225.509 +
 225.510 +        // Write out all elements in the proper order.
 225.511 +        for (E e : m.keySet())
 225.512 +            s.writeObject(e);
 225.513 +    }
 225.514 +
 225.515 +    /**
 225.516 +     * Reconstitute the {@code TreeSet} instance from a stream (that is,
 225.517 +     * deserialize it).
 225.518 +     */
 225.519 +    private void readObject(java.io.ObjectInputStream s)
 225.520 +        throws java.io.IOException, ClassNotFoundException {
 225.521 +        // Read in any hidden stuff
 225.522 +        s.defaultReadObject();
 225.523 +
 225.524 +        // Read in Comparator
 225.525 +        Comparator<? super E> c = (Comparator<? super E>) s.readObject();
 225.526 +
 225.527 +        // Create backing TreeMap
 225.528 +        TreeMap<E,Object> tm;
 225.529 +        if (c==null)
 225.530 +            tm = new TreeMap<>();
 225.531 +        else
 225.532 +            tm = new TreeMap<>(c);
 225.533 +        m = tm;
 225.534 +
 225.535 +        // Read in size
 225.536 +        int size = s.readInt();
 225.537 +
 225.538 +        tm.readTreeSet(size, s, PRESENT);
 225.539 +    }
 225.540 +
 225.541 +    private static final long serialVersionUID = -2479143000061671589L;
 225.542 +}
   226.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.2 +++ b/rt/emul/compact/src/main/java/java/util/WeakHashMap.java	Wed Apr 30 15:04:10 2014 +0200
   226.3 @@ -0,0 +1,972 @@
   226.4 +/*
   226.5 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
   226.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   226.7 + *
   226.8 + * This code is free software; you can redistribute it and/or modify it
   226.9 + * under the terms of the GNU General Public License version 2 only, as
  226.10 + * published by the Free Software Foundation.  Oracle designates this
  226.11 + * particular file as subject to the "Classpath" exception as provided
  226.12 + * by Oracle in the LICENSE file that accompanied this code.
  226.13 + *
  226.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  226.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  226.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  226.17 + * version 2 for more details (a copy is included in the LICENSE file that
  226.18 + * accompanied this code).
  226.19 + *
  226.20 + * You should have received a copy of the GNU General Public License version
  226.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  226.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  226.23 + *
  226.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  226.25 + * or visit www.oracle.com if you need additional information or have any
  226.26 + * questions.
  226.27 + */
  226.28 +
  226.29 +package java.util;
  226.30 +import java.lang.ref.WeakReference;
  226.31 +import java.lang.ref.ReferenceQueue;
  226.32 +
  226.33 +
  226.34 +/**
  226.35 + * Hash table based implementation of the <tt>Map</tt> interface, with
  226.36 + * <em>weak keys</em>.
  226.37 + * An entry in a <tt>WeakHashMap</tt> will automatically be removed when
  226.38 + * its key is no longer in ordinary use.  More precisely, the presence of a
  226.39 + * mapping for a given key will not prevent the key from being discarded by the
  226.40 + * garbage collector, that is, made finalizable, finalized, and then reclaimed.
  226.41 + * When a key has been discarded its entry is effectively removed from the map,
  226.42 + * so this class behaves somewhat differently from other <tt>Map</tt>
  226.43 + * implementations.
  226.44 + *
  226.45 + * <p> Both null values and the null key are supported. This class has
  226.46 + * performance characteristics similar to those of the <tt>HashMap</tt>
  226.47 + * class, and has the same efficiency parameters of <em>initial capacity</em>
  226.48 + * and <em>load factor</em>.
  226.49 + *
  226.50 + * <p> Like most collection classes, this class is not synchronized.
  226.51 + * A synchronized <tt>WeakHashMap</tt> may be constructed using the
  226.52 + * {@link Collections#synchronizedMap Collections.synchronizedMap}
  226.53 + * method.
  226.54 + *
  226.55 + * <p> This class is intended primarily for use with key objects whose
  226.56 + * <tt>equals</tt> methods test for object identity using the
  226.57 + * <tt>==</tt> operator.  Once such a key is discarded it can never be
  226.58 + * recreated, so it is impossible to do a lookup of that key in a
  226.59 + * <tt>WeakHashMap</tt> at some later time and be surprised that its entry
  226.60 + * has been removed.  This class will work perfectly well with key objects
  226.61 + * whose <tt>equals</tt> methods are not based upon object identity, such
  226.62 + * as <tt>String</tt> instances.  With such recreatable key objects,
  226.63 + * however, the automatic removal of <tt>WeakHashMap</tt> entries whose
  226.64 + * keys have been discarded may prove to be confusing.
  226.65 + *
  226.66 + * <p> The behavior of the <tt>WeakHashMap</tt> class depends in part upon
  226.67 + * the actions of the garbage collector, so several familiar (though not
  226.68 + * required) <tt>Map</tt> invariants do not hold for this class.  Because
  226.69 + * the garbage collector may discard keys at any time, a
  226.70 + * <tt>WeakHashMap</tt> may behave as though an unknown thread is silently
  226.71 + * removing entries.  In particular, even if you synchronize on a
  226.72 + * <tt>WeakHashMap</tt> instance and invoke none of its mutator methods, it
  226.73 + * is possible for the <tt>size</tt> method to return smaller values over
  226.74 + * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
  226.75 + * then <tt>true</tt>, for the <tt>containsKey</tt> method to return
  226.76 + * <tt>true</tt> and later <tt>false</tt> for a given key, for the
  226.77 + * <tt>get</tt> method to return a value for a given key but later return
  226.78 + * <tt>null</tt>, for the <tt>put</tt> method to return
  226.79 + * <tt>null</tt> and the <tt>remove</tt> method to return
  226.80 + * <tt>false</tt> for a key that previously appeared to be in the map, and
  226.81 + * for successive examinations of the key set, the value collection, and
  226.82 + * the entry set to yield successively smaller numbers of elements.
  226.83 + *
  226.84 + * <p> Each key object in a <tt>WeakHashMap</tt> is stored indirectly as
  226.85 + * the referent of a weak reference.  Therefore a key will automatically be
  226.86 + * removed only after the weak references to it, both inside and outside of the
  226.87 + * map, have been cleared by the garbage collector.
  226.88 + *
  226.89 + * <p> <strong>Implementation note:</strong> The value objects in a
  226.90 + * <tt>WeakHashMap</tt> are held by ordinary strong references.  Thus care
  226.91 + * should be taken to ensure that value objects do not strongly refer to their
  226.92 + * own keys, either directly or indirectly, since that will prevent the keys
  226.93 + * from being discarded.  Note that a value object may refer indirectly to its
  226.94 + * key via the <tt>WeakHashMap</tt> itself; that is, a value object may
  226.95 + * strongly refer to some other key object whose associated value object, in
  226.96 + * turn, strongly refers to the key of the first value object.  One way
  226.97 + * to deal with this is to wrap values themselves within
  226.98 + * <tt>WeakReferences</tt> before
  226.99 + * inserting, as in: <tt>m.put(key, new WeakReference(value))</tt>,
 226.100 + * and then unwrapping upon each <tt>get</tt>.
 226.101 + *
 226.102 + * <p>The iterators returned by the <tt>iterator</tt> method of the collections
 226.103 + * returned by all of this class's "collection view methods" are
 226.104 + * <i>fail-fast</i>: if the map is structurally modified at any time after the
 226.105 + * iterator is created, in any way except through the iterator's own
 226.106 + * <tt>remove</tt> method, the iterator will throw a {@link
 226.107 + * ConcurrentModificationException}.  Thus, in the face of concurrent
 226.108 + * modification, the iterator fails quickly and cleanly, rather than risking
 226.109 + * arbitrary, non-deterministic behavior at an undetermined time in the future.
 226.110 + *
 226.111 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 226.112 + * as it is, generally speaking, impossible to make any hard guarantees in the
 226.113 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 226.114 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 226.115 + * Therefore, it would be wrong to write a program that depended on this
 226.116 + * exception for its correctness:  <i>the fail-fast behavior of iterators
 226.117 + * should be used only to detect bugs.</i>
 226.118 + *
 226.119 + * <p>This class is a member of the
 226.120 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 226.121 + * Java Collections Framework</a>.
 226.122 + *
 226.123 + * @param <K> the type of keys maintained by this map
 226.124 + * @param <V> the type of mapped values
 226.125 + *
 226.126 + * @author      Doug Lea
 226.127 + * @author      Josh Bloch
 226.128 + * @author      Mark Reinhold
 226.129 + * @since       1.2
 226.130 + * @see         java.util.HashMap
 226.131 + * @see         java.lang.ref.WeakReference
 226.132 + */
 226.133 +public class WeakHashMap<K,V>
 226.134 +    extends AbstractMap<K,V>
 226.135 +    implements Map<K,V> {
 226.136 +
 226.137 +    /**
 226.138 +     * The default initial capacity -- MUST be a power of two.
 226.139 +     */
 226.140 +    private static final int DEFAULT_INITIAL_CAPACITY = 16;
 226.141 +
 226.142 +    /**
 226.143 +     * The maximum capacity, used if a higher value is implicitly specified
 226.144 +     * by either of the constructors with arguments.
 226.145 +     * MUST be a power of two <= 1<<30.
 226.146 +     */
 226.147 +    private static final int MAXIMUM_CAPACITY = 1 << 30;
 226.148 +
 226.149 +    /**
 226.150 +     * The load factor used when none specified in constructor.
 226.151 +     */
 226.152 +    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
 226.153 +
 226.154 +    /**
 226.155 +     * The table, resized as necessary. Length MUST Always be a power of two.
 226.156 +     */
 226.157 +    Entry<K,V>[] table;
 226.158 +
 226.159 +    /**
 226.160 +     * The number of key-value mappings contained in this weak hash map.
 226.161 +     */
 226.162 +    private int size;
 226.163 +
 226.164 +    /**
 226.165 +     * The next size value at which to resize (capacity * load factor).
 226.166 +     */
 226.167 +    private int threshold;
 226.168 +
 226.169 +    /**
 226.170 +     * The load factor for the hash table.
 226.171 +     */
 226.172 +    private final float loadFactor;
 226.173 +
 226.174 +    /**
 226.175 +     * Reference queue for cleared WeakEntries
 226.176 +     */
 226.177 +    private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
 226.178 +
 226.179 +    /**
 226.180 +     * The number of times this WeakHashMap has been structurally modified.
 226.181 +     * Structural modifications are those that change the number of
 226.182 +     * mappings in the map or otherwise modify its internal structure
 226.183 +     * (e.g., rehash).  This field is used to make iterators on
 226.184 +     * Collection-views of the map fail-fast.
 226.185 +     *
 226.186 +     * @see ConcurrentModificationException
 226.187 +     */
 226.188 +    int modCount;
 226.189 +
 226.190 +    @SuppressWarnings("unchecked")
 226.191 +    private Entry<K,V>[] newTable(int n) {
 226.192 +        return (Entry<K,V>[]) new Entry[n];
 226.193 +    }
 226.194 +
 226.195 +    /**
 226.196 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
 226.197 +     * capacity and the given load factor.
 226.198 +     *
 226.199 +     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
 226.200 +     * @param  loadFactor      The load factor of the <tt>WeakHashMap</tt>
 226.201 +     * @throws IllegalArgumentException if the initial capacity is negative,
 226.202 +     *         or if the load factor is nonpositive.
 226.203 +     */
 226.204 +    public WeakHashMap(int initialCapacity, float loadFactor) {
 226.205 +        if (initialCapacity < 0)
 226.206 +            throw new IllegalArgumentException("Illegal Initial Capacity: "+
 226.207 +                                               initialCapacity);
 226.208 +        if (initialCapacity > MAXIMUM_CAPACITY)
 226.209 +            initialCapacity = MAXIMUM_CAPACITY;
 226.210 +
 226.211 +        if (loadFactor <= 0 || Float.isNaN(loadFactor))
 226.212 +            throw new IllegalArgumentException("Illegal Load factor: "+
 226.213 +                                               loadFactor);
 226.214 +        int capacity = 1;
 226.215 +        while (capacity < initialCapacity)
 226.216 +            capacity <<= 1;
 226.217 +        table = newTable(capacity);
 226.218 +        this.loadFactor = loadFactor;
 226.219 +        threshold = (int)(capacity * loadFactor);
 226.220 +    }
 226.221 +
 226.222 +    /**
 226.223 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
 226.224 +     * capacity and the default load factor (0.75).
 226.225 +     *
 226.226 +     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
 226.227 +     * @throws IllegalArgumentException if the initial capacity is negative
 226.228 +     */
 226.229 +    public WeakHashMap(int initialCapacity) {
 226.230 +        this(initialCapacity, DEFAULT_LOAD_FACTOR);
 226.231 +    }
 226.232 +
 226.233 +    /**
 226.234 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
 226.235 +     * capacity (16) and load factor (0.75).
 226.236 +     */
 226.237 +    public WeakHashMap() {
 226.238 +        this.loadFactor = DEFAULT_LOAD_FACTOR;
 226.239 +        threshold = DEFAULT_INITIAL_CAPACITY;
 226.240 +        table = newTable(DEFAULT_INITIAL_CAPACITY);
 226.241 +    }
 226.242 +
 226.243 +    /**
 226.244 +     * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the
 226.245 +     * specified map.  The <tt>WeakHashMap</tt> is created with the default
 226.246 +     * load factor (0.75) and an initial capacity sufficient to hold the
 226.247 +     * mappings in the specified map.
 226.248 +     *
 226.249 +     * @param   m the map whose mappings are to be placed in this map
 226.250 +     * @throws  NullPointerException if the specified map is null
 226.251 +     * @since   1.3
 226.252 +     */
 226.253 +    public WeakHashMap(Map<? extends K, ? extends V> m) {
 226.254 +        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 16),
 226.255 +             DEFAULT_LOAD_FACTOR);
 226.256 +        putAll(m);
 226.257 +    }
 226.258 +
 226.259 +    // internal utilities
 226.260 +
 226.261 +    /**
 226.262 +     * Value representing null keys inside tables.
 226.263 +     */
 226.264 +    private static final Object NULL_KEY = new Object();
 226.265 +
 226.266 +    /**
 226.267 +     * Use NULL_KEY for key if it is null.
 226.268 +     */
 226.269 +    private static Object maskNull(Object key) {
 226.270 +        return (key == null) ? NULL_KEY : key;
 226.271 +    }
 226.272 +
 226.273 +    /**
 226.274 +     * Returns internal representation of null key back to caller as null.
 226.275 +     */
 226.276 +    static Object unmaskNull(Object key) {
 226.277 +        return (key == NULL_KEY) ? null : key;
 226.278 +    }
 226.279 +
 226.280 +    /**
 226.281 +     * Checks for equality of non-null reference x and possibly-null y.  By
 226.282 +     * default uses Object.equals.
 226.283 +     */
 226.284 +    private static boolean eq(Object x, Object y) {
 226.285 +        return x == y || x.equals(y);
 226.286 +    }
 226.287 +
 226.288 +    /**
 226.289 +     * Returns index for hash code h.
 226.290 +     */
 226.291 +    private static int indexFor(int h, int length) {
 226.292 +        return h & (length-1);
 226.293 +    }
 226.294 +
 226.295 +    /**
 226.296 +     * Expunges stale entries from the table.
 226.297 +     */
 226.298 +    private void expungeStaleEntries() {
 226.299 +        for (Object x; (x = queue.poll()) != null; ) {
 226.300 +            synchronized (queue) {
 226.301 +                @SuppressWarnings("unchecked")
 226.302 +                    Entry<K,V> e = (Entry<K,V>) x;
 226.303 +                int i = indexFor(e.hash, table.length);
 226.304 +
 226.305 +                Entry<K,V> prev = table[i];
 226.306 +                Entry<K,V> p = prev;
 226.307 +                while (p != null) {
 226.308 +                    Entry<K,V> next = p.next;
 226.309 +                    if (p == e) {
 226.310 +                        if (prev == e)
 226.311 +                            table[i] = next;
 226.312 +                        else
 226.313 +                            prev.next = next;
 226.314 +                        // Must not null out e.next;
 226.315 +                        // stale entries may be in use by a HashIterator
 226.316 +                        e.value = null; // Help GC
 226.317 +                        size--;
 226.318 +                        break;
 226.319 +                    }
 226.320 +                    prev = p;
 226.321 +                    p = next;
 226.322 +                }
 226.323 +            }
 226.324 +        }
 226.325 +    }
 226.326 +
 226.327 +    /**
 226.328 +     * Returns the table after first expunging stale entries.
 226.329 +     */
 226.330 +    private Entry<K,V>[] getTable() {
 226.331 +        expungeStaleEntries();
 226.332 +        return table;
 226.333 +    }
 226.334 +
 226.335 +    /**
 226.336 +     * Returns the number of key-value mappings in this map.
 226.337 +     * This result is a snapshot, and may not reflect unprocessed
 226.338 +     * entries that will be removed before next attempted access
 226.339 +     * because they are no longer referenced.
 226.340 +     */
 226.341 +    public int size() {
 226.342 +        if (size == 0)
 226.343 +            return 0;
 226.344 +        expungeStaleEntries();
 226.345 +        return size;
 226.346 +    }
 226.347 +
 226.348 +    /**
 226.349 +     * Returns <tt>true</tt> if this map contains no key-value mappings.
 226.350 +     * This result is a snapshot, and may not reflect unprocessed
 226.351 +     * entries that will be removed before next attempted access
 226.352 +     * because they are no longer referenced.
 226.353 +     */
 226.354 +    public boolean isEmpty() {
 226.355 +        return size() == 0;
 226.356 +    }
 226.357 +
 226.358 +    /**
 226.359 +     * Returns the value to which the specified key is mapped,
 226.360 +     * or {@code null} if this map contains no mapping for the key.
 226.361 +     *
 226.362 +     * <p>More formally, if this map contains a mapping from a key
 226.363 +     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
 226.364 +     * key.equals(k))}, then this method returns {@code v}; otherwise
 226.365 +     * it returns {@code null}.  (There can be at most one such mapping.)
 226.366 +     *
 226.367 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 226.368 +     * indicate that the map contains no mapping for the key; it's also
 226.369 +     * possible that the map explicitly maps the key to {@code null}.
 226.370 +     * The {@link #containsKey containsKey} operation may be used to
 226.371 +     * distinguish these two cases.
 226.372 +     *
 226.373 +     * @see #put(Object, Object)
 226.374 +     */
 226.375 +    public V get(Object key) {
 226.376 +        Object k = maskNull(key);
 226.377 +        int h = HashMap.hash(k.hashCode());
 226.378 +        Entry<K,V>[] tab = getTable();
 226.379 +        int index = indexFor(h, tab.length);
 226.380 +        Entry<K,V> e = tab[index];
 226.381 +        while (e != null) {
 226.382 +            if (e.hash == h && eq(k, e.get()))
 226.383 +                return e.value;
 226.384 +            e = e.next;
 226.385 +        }
 226.386 +        return null;
 226.387 +    }
 226.388 +
 226.389 +    /**
 226.390 +     * Returns <tt>true</tt> if this map contains a mapping for the
 226.391 +     * specified key.
 226.392 +     *
 226.393 +     * @param  key   The key whose presence in this map is to be tested
 226.394 +     * @return <tt>true</tt> if there is a mapping for <tt>key</tt>;
 226.395 +     *         <tt>false</tt> otherwise
 226.396 +     */
 226.397 +    public boolean containsKey(Object key) {
 226.398 +        return getEntry(key) != null;
 226.399 +    }
 226.400 +
 226.401 +    /**
 226.402 +     * Returns the entry associated with the specified key in this map.
 226.403 +     * Returns null if the map contains no mapping for this key.
 226.404 +     */
 226.405 +    Entry<K,V> getEntry(Object key) {
 226.406 +        Object k = maskNull(key);
 226.407 +        int h = HashMap.hash(k.hashCode());
 226.408 +        Entry<K,V>[] tab = getTable();
 226.409 +        int index = indexFor(h, tab.length);
 226.410 +        Entry<K,V> e = tab[index];
 226.411 +        while (e != null && !(e.hash == h && eq(k, e.get())))
 226.412 +            e = e.next;
 226.413 +        return e;
 226.414 +    }
 226.415 +
 226.416 +    /**
 226.417 +     * Associates the specified value with the specified key in this map.
 226.418 +     * If the map previously contained a mapping for this key, the old
 226.419 +     * value is replaced.
 226.420 +     *
 226.421 +     * @param key key with which the specified value is to be associated.
 226.422 +     * @param value value to be associated with the specified key.
 226.423 +     * @return the previous value associated with <tt>key</tt>, or
 226.424 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 226.425 +     *         (A <tt>null</tt> return can also indicate that the map
 226.426 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 226.427 +     */
 226.428 +    public V put(K key, V value) {
 226.429 +        Object k = maskNull(key);
 226.430 +        int h = HashMap.hash(k.hashCode());
 226.431 +        Entry<K,V>[] tab = getTable();
 226.432 +        int i = indexFor(h, tab.length);
 226.433 +
 226.434 +        for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
 226.435 +            if (h == e.hash && eq(k, e.get())) {
 226.436 +                V oldValue = e.value;
 226.437 +                if (value != oldValue)
 226.438 +                    e.value = value;
 226.439 +                return oldValue;
 226.440 +            }
 226.441 +        }
 226.442 +
 226.443 +        modCount++;
 226.444 +        Entry<K,V> e = tab[i];
 226.445 +        tab[i] = new Entry<>(k, value, queue, h, e);
 226.446 +        if (++size >= threshold)
 226.447 +            resize(tab.length * 2);
 226.448 +        return null;
 226.449 +    }
 226.450 +
 226.451 +    /**
 226.452 +     * Rehashes the contents of this map into a new array with a
 226.453 +     * larger capacity.  This method is called automatically when the
 226.454 +     * number of keys in this map reaches its threshold.
 226.455 +     *
 226.456 +     * If current capacity is MAXIMUM_CAPACITY, this method does not
 226.457 +     * resize the map, but sets threshold to Integer.MAX_VALUE.
 226.458 +     * This has the effect of preventing future calls.
 226.459 +     *
 226.460 +     * @param newCapacity the new capacity, MUST be a power of two;
 226.461 +     *        must be greater than current capacity unless current
 226.462 +     *        capacity is MAXIMUM_CAPACITY (in which case value
 226.463 +     *        is irrelevant).
 226.464 +     */
 226.465 +    void resize(int newCapacity) {
 226.466 +        Entry<K,V>[] oldTable = getTable();
 226.467 +        int oldCapacity = oldTable.length;
 226.468 +        if (oldCapacity == MAXIMUM_CAPACITY) {
 226.469 +            threshold = Integer.MAX_VALUE;
 226.470 +            return;
 226.471 +        }
 226.472 +
 226.473 +        Entry<K,V>[] newTable = newTable(newCapacity);
 226.474 +        transfer(oldTable, newTable);
 226.475 +        table = newTable;
 226.476 +
 226.477 +        /*
 226.478 +         * If ignoring null elements and processing ref queue caused massive
 226.479 +         * shrinkage, then restore old table.  This should be rare, but avoids
 226.480 +         * unbounded expansion of garbage-filled tables.
 226.481 +         */
 226.482 +        if (size >= threshold / 2) {
 226.483 +            threshold = (int)(newCapacity * loadFactor);
 226.484 +        } else {
 226.485 +            expungeStaleEntries();
 226.486 +            transfer(newTable, oldTable);
 226.487 +            table = oldTable;
 226.488 +        }
 226.489 +    }
 226.490 +
 226.491 +    /** Transfers all entries from src to dest tables */
 226.492 +    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
 226.493 +        for (int j = 0; j < src.length; ++j) {
 226.494 +            Entry<K,V> e = src[j];
 226.495 +            src[j] = null;
 226.496 +            while (e != null) {
 226.497 +                Entry<K,V> next = e.next;
 226.498 +                Object key = e.get();
 226.499 +                if (key == null) {
 226.500 +                    e.next = null;  // Help GC
 226.501 +                    e.value = null; //  "   "
 226.502 +                    size--;
 226.503 +                } else {
 226.504 +                    int i = indexFor(e.hash, dest.length);
 226.505 +                    e.next = dest[i];
 226.506 +                    dest[i] = e;
 226.507 +                }
 226.508 +                e = next;
 226.509 +            }
 226.510 +        }
 226.511 +    }
 226.512 +
 226.513 +    /**
 226.514 +     * Copies all of the mappings from the specified map to this map.
 226.515 +     * These mappings will replace any mappings that this map had for any
 226.516 +     * of the keys currently in the specified map.
 226.517 +     *
 226.518 +     * @param m mappings to be stored in this map.
 226.519 +     * @throws  NullPointerException if the specified map is null.
 226.520 +     */
 226.521 +    public void putAll(Map<? extends K, ? extends V> m) {
 226.522 +        int numKeysToBeAdded = m.size();
 226.523 +        if (numKeysToBeAdded == 0)
 226.524 +            return;
 226.525 +
 226.526 +        /*
 226.527 +         * Expand the map if the map if the number of mappings to be added
 226.528 +         * is greater than or equal to threshold.  This is conservative; the
 226.529 +         * obvious condition is (m.size() + size) >= threshold, but this
 226.530 +         * condition could result in a map with twice the appropriate capacity,
 226.531 +         * if the keys to be added overlap with the keys already in this map.
 226.532 +         * By using the conservative calculation, we subject ourself
 226.533 +         * to at most one extra resize.
 226.534 +         */
 226.535 +        if (numKeysToBeAdded > threshold) {
 226.536 +            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
 226.537 +            if (targetCapacity > MAXIMUM_CAPACITY)
 226.538 +                targetCapacity = MAXIMUM_CAPACITY;
 226.539 +            int newCapacity = table.length;
 226.540 +            while (newCapacity < targetCapacity)
 226.541 +                newCapacity <<= 1;
 226.542 +            if (newCapacity > table.length)
 226.543 +                resize(newCapacity);
 226.544 +        }
 226.545 +
 226.546 +        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
 226.547 +            put(e.getKey(), e.getValue());
 226.548 +    }
 226.549 +
 226.550 +    /**
 226.551 +     * Removes the mapping for a key from this weak hash map if it is present.
 226.552 +     * More formally, if this map contains a mapping from key <tt>k</tt> to
 226.553 +     * value <tt>v</tt> such that <code>(key==null ?  k==null :
 226.554 +     * key.equals(k))</code>, that mapping is removed.  (The map can contain
 226.555 +     * at most one such mapping.)
 226.556 +     *
 226.557 +     * <p>Returns the value to which this map previously associated the key,
 226.558 +     * or <tt>null</tt> if the map contained no mapping for the key.  A
 226.559 +     * return value of <tt>null</tt> does not <i>necessarily</i> indicate
 226.560 +     * that the map contained no mapping for the key; it's also possible
 226.561 +     * that the map explicitly mapped the key to <tt>null</tt>.
 226.562 +     *
 226.563 +     * <p>The map will not contain a mapping for the specified key once the
 226.564 +     * call returns.
 226.565 +     *
 226.566 +     * @param key key whose mapping is to be removed from the map
 226.567 +     * @return the previous value associated with <tt>key</tt>, or
 226.568 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
 226.569 +     */
 226.570 +    public V remove(Object key) {
 226.571 +        Object k = maskNull(key);
 226.572 +        int h = HashMap.hash(k.hashCode());
 226.573 +        Entry<K,V>[] tab = getTable();
 226.574 +        int i = indexFor(h, tab.length);
 226.575 +        Entry<K,V> prev = tab[i];
 226.576 +        Entry<K,V> e = prev;
 226.577 +
 226.578 +        while (e != null) {
 226.579 +            Entry<K,V> next = e.next;
 226.580 +            if (h == e.hash && eq(k, e.get())) {
 226.581 +                modCount++;
 226.582 +                size--;
 226.583 +                if (prev == e)
 226.584 +                    tab[i] = next;
 226.585 +                else
 226.586 +                    prev.next = next;
 226.587 +                return e.value;
 226.588 +            }
 226.589 +            prev = e;
 226.590 +            e = next;
 226.591 +        }
 226.592 +
 226.593 +        return null;
 226.594 +    }
 226.595 +
 226.596 +    /** Special version of remove needed by Entry set */
 226.597 +    boolean removeMapping(Object o) {
 226.598 +        if (!(o instanceof Map.Entry))
 226.599 +            return false;
 226.600 +        Entry<K,V>[] tab = getTable();
 226.601 +        Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
 226.602 +        Object k = maskNull(entry.getKey());
 226.603 +        int h = HashMap.hash(k.hashCode());
 226.604 +        int i = indexFor(h, tab.length);
 226.605 +        Entry<K,V> prev = tab[i];
 226.606 +        Entry<K,V> e = prev;
 226.607 +
 226.608 +        while (e != null) {
 226.609 +            Entry<K,V> next = e.next;
 226.610 +            if (h == e.hash && e.equals(entry)) {
 226.611 +                modCount++;
 226.612 +                size--;
 226.613 +                if (prev == e)
 226.614 +                    tab[i] = next;
 226.615 +                else
 226.616 +                    prev.next = next;
 226.617 +                return true;
 226.618 +            }
 226.619 +            prev = e;
 226.620 +            e = next;
 226.621 +        }
 226.622 +
 226.623 +        return false;
 226.624 +    }
 226.625 +
 226.626 +    /**
 226.627 +     * Removes all of the mappings from this map.
 226.628 +     * The map will be empty after this call returns.
 226.629 +     */
 226.630 +    public void clear() {
 226.631 +        // clear out ref queue. We don't need to expunge entries
 226.632 +        // since table is getting cleared.
 226.633 +        while (queue.poll() != null)
 226.634 +            ;
 226.635 +
 226.636 +        modCount++;
 226.637 +        Arrays.fill(table, null);
 226.638 +        size = 0;
 226.639 +
 226.640 +        // Allocation of array may have caused GC, which may have caused
 226.641 +        // additional entries to go stale.  Removing these entries from the
 226.642 +        // reference queue will make them eligible for reclamation.
 226.643 +        while (queue.poll() != null)
 226.644 +            ;
 226.645 +    }
 226.646 +
 226.647 +    /**
 226.648 +     * Returns <tt>true</tt> if this map maps one or more keys to the
 226.649 +     * specified value.
 226.650 +     *
 226.651 +     * @param value value whose presence in this map is to be tested
 226.652 +     * @return <tt>true</tt> if this map maps one or more keys to the
 226.653 +     *         specified value
 226.654 +     */
 226.655 +    public boolean containsValue(Object value) {
 226.656 +        if (value==null)
 226.657 +            return containsNullValue();
 226.658 +
 226.659 +        Entry<K,V>[] tab = getTable();
 226.660 +        for (int i = tab.length; i-- > 0;)
 226.661 +            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
 226.662 +                if (value.equals(e.value))
 226.663 +                    return true;
 226.664 +        return false;
 226.665 +    }
 226.666 +
 226.667 +    /**
 226.668 +     * Special-case code for containsValue with null argument
 226.669 +     */
 226.670 +    private boolean containsNullValue() {
 226.671 +        Entry<K,V>[] tab = getTable();
 226.672 +        for (int i = tab.length; i-- > 0;)
 226.673 +            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
 226.674 +                if (e.value==null)
 226.675 +                    return true;
 226.676 +        return false;
 226.677 +    }
 226.678 +
 226.679 +    /**
 226.680 +     * The entries in this hash table extend WeakReference, using its main ref
 226.681 +     * field as the key.
 226.682 +     */
 226.683 +    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
 226.684 +        V value;
 226.685 +        final int hash;
 226.686 +        Entry<K,V> next;
 226.687 +
 226.688 +        /**
 226.689 +         * Creates new entry.
 226.690 +         */
 226.691 +        Entry(Object key, V value,
 226.692 +              ReferenceQueue<Object> queue,
 226.693 +              int hash, Entry<K,V> next) {
 226.694 +            super(key, queue);
 226.695 +            this.value = value;
 226.696 +            this.hash  = hash;
 226.697 +            this.next  = next;
 226.698 +        }
 226.699 +
 226.700 +        @SuppressWarnings("unchecked")
 226.701 +        public K getKey() {
 226.702 +            return (K) WeakHashMap.unmaskNull(get());
 226.703 +        }
 226.704 +
 226.705 +        public V getValue() {
 226.706 +            return value;
 226.707 +        }
 226.708 +
 226.709 +        public V setValue(V newValue) {
 226.710 +            V oldValue = value;
 226.711 +            value = newValue;
 226.712 +            return oldValue;
 226.713 +        }
 226.714 +
 226.715 +        public boolean equals(Object o) {
 226.716 +            if (!(o instanceof Map.Entry))
 226.717 +                return false;
 226.718 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
 226.719 +            K k1 = getKey();
 226.720 +            Object k2 = e.getKey();
 226.721 +            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
 226.722 +                V v1 = getValue();
 226.723 +                Object v2 = e.getValue();
 226.724 +                if (v1 == v2 || (v1 != null && v1.equals(v2)))
 226.725 +                    return true;
 226.726 +            }
 226.727 +            return false;
 226.728 +        }
 226.729 +
 226.730 +        public int hashCode() {
 226.731 +            K k = getKey();
 226.732 +            V v = getValue();
 226.733 +            return ((k==null ? 0 : k.hashCode()) ^
 226.734 +                    (v==null ? 0 : v.hashCode()));
 226.735 +        }
 226.736 +
 226.737 +        public String toString() {
 226.738 +            return getKey() + "=" + getValue();
 226.739 +        }
 226.740 +    }
 226.741 +
 226.742 +    private abstract class HashIterator<T> implements Iterator<T> {
 226.743 +        private int index;
 226.744 +        private Entry<K,V> entry = null;
 226.745 +        private Entry<K,V> lastReturned = null;
 226.746 +        private int expectedModCount = modCount;
 226.747 +
 226.748 +        /**
 226.749 +         * Strong reference needed to avoid disappearance of key
 226.750 +         * between hasNext and next
 226.751 +         */
 226.752 +        private Object nextKey = null;
 226.753 +
 226.754 +        /**
 226.755 +         * Strong reference needed to avoid disappearance of key
 226.756 +         * between nextEntry() and any use of the entry
 226.757 +         */
 226.758 +        private Object currentKey = null;
 226.759 +
 226.760 +        HashIterator() {
 226.761 +            index = isEmpty() ? 0 : table.length;
 226.762 +        }
 226.763 +
 226.764 +        public boolean hasNext() {
 226.765 +            Entry<K,V>[] t = table;
 226.766 +
 226.767 +            while (nextKey == null) {
 226.768 +                Entry<K,V> e = entry;
 226.769 +                int i = index;
 226.770 +                while (e == null && i > 0)
 226.771 +                    e = t[--i];
 226.772 +                entry = e;
 226.773 +                index = i;
 226.774 +                if (e == null) {
 226.775 +                    currentKey = null;
 226.776 +                    return false;
 226.777 +                }
 226.778 +                nextKey = e.get(); // hold on to key in strong ref
 226.779 +                if (nextKey == null)
 226.780 +                    entry = entry.next;
 226.781 +            }
 226.782 +            return true;
 226.783 +        }
 226.784 +
 226.785 +        /** The common parts of next() across different types of iterators */
 226.786 +        protected Entry<K,V> nextEntry() {
 226.787 +            if (modCount != expectedModCount)
 226.788 +                throw new ConcurrentModificationException();
 226.789 +            if (nextKey == null && !hasNext())
 226.790 +                throw new NoSuchElementException();
 226.791 +
 226.792 +            lastReturned = entry;
 226.793 +            entry = entry.next;
 226.794 +            currentKey = nextKey;
 226.795 +            nextKey = null;
 226.796 +            return lastReturned;
 226.797 +        }
 226.798 +
 226.799 +        public void remove() {
 226.800 +            if (lastReturned == null)
 226.801 +                throw new IllegalStateException();
 226.802 +            if (modCount != expectedModCount)
 226.803 +                throw new ConcurrentModificationException();
 226.804 +
 226.805 +            WeakHashMap.this.remove(currentKey);
 226.806 +            expectedModCount = modCount;
 226.807 +            lastReturned = null;
 226.808 +            currentKey = null;
 226.809 +        }
 226.810 +
 226.811 +    }
 226.812 +
 226.813 +    private class ValueIterator extends HashIterator<V> {
 226.814 +        public V next() {
 226.815 +            return nextEntry().value;
 226.816 +        }
 226.817 +    }
 226.818 +
 226.819 +    private class KeyIterator extends HashIterator<K> {
 226.820 +        public K next() {
 226.821 +            return nextEntry().getKey();
 226.822 +        }
 226.823 +    }
 226.824 +
 226.825 +    private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
 226.826 +        public Map.Entry<K,V> next() {
 226.827 +            return nextEntry();
 226.828 +        }
 226.829 +    }
 226.830 +
 226.831 +    // Views
 226.832 +
 226.833 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 226.834 +
 226.835 +    /**
 226.836 +     * Returns a {@link Set} view of the keys contained in this map.
 226.837 +     * The set is backed by the map, so changes to the map are
 226.838 +     * reflected in the set, and vice-versa.  If the map is modified
 226.839 +     * while an iteration over the set is in progress (except through
 226.840 +     * the iterator's own <tt>remove</tt> operation), the results of
 226.841 +     * the iteration are undefined.  The set supports element removal,
 226.842 +     * which removes the corresponding mapping from the map, via the
 226.843 +     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
 226.844 +     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
 226.845 +     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
 226.846 +     * operations.
 226.847 +     */
 226.848 +    public Set<K> keySet() {
 226.849 +        Set<K> ks = keySet;
 226.850 +        return (ks != null ? ks : (keySet = new KeySet()));
 226.851 +    }
 226.852 +
 226.853 +    private class KeySet extends AbstractSet<K> {
 226.854 +        public Iterator<K> iterator() {
 226.855 +            return new KeyIterator();
 226.856 +        }
 226.857 +
 226.858 +        public int size() {
 226.859 +            return WeakHashMap.this.size();
 226.860 +        }
 226.861 +
 226.862 +        public boolean contains(Object o) {
 226.863 +            return containsKey(o);
 226.864 +        }
 226.865 +
 226.866 +        public boolean remove(Object o) {
 226.867 +            if (containsKey(o)) {
 226.868 +                WeakHashMap.this.remove(o);
 226.869 +                return true;
 226.870 +            }
 226.871 +            else
 226.872 +                return false;
 226.873 +        }
 226.874 +
 226.875 +        public void clear() {
 226.876 +            WeakHashMap.this.clear();
 226.877 +        }
 226.878 +    }
 226.879 +
 226.880 +    /**
 226.881 +     * Returns a {@link Collection} view of the values contained in this map.
 226.882 +     * The collection is backed by the map, so changes to the map are
 226.883 +     * reflected in the collection, and vice-versa.  If the map is
 226.884 +     * modified while an iteration over the collection is in progress
 226.885 +     * (except through the iterator's own <tt>remove</tt> operation),
 226.886 +     * the results of the iteration are undefined.  The collection
 226.887 +     * supports element removal, which removes the corresponding
 226.888 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
 226.889 +     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
 226.890 +     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
 226.891 +     * support the <tt>add</tt> or <tt>addAll</tt> operations.
 226.892 +     */
 226.893 +    public Collection<V> values() {
 226.894 +        Collection<V> vs = values;
 226.895 +        return (vs != null) ? vs : (values = new Values());
 226.896 +    }
 226.897 +
 226.898 +    private class Values extends AbstractCollection<V> {
 226.899 +        public Iterator<V> iterator() {
 226.900 +            return new ValueIterator();
 226.901 +        }
 226.902 +
 226.903 +        public int size() {
 226.904 +            return WeakHashMap.this.size();
 226.905 +        }
 226.906 +
 226.907 +        public boolean contains(Object o) {
 226.908 +            return containsValue(o);
 226.909 +        }
 226.910 +
 226.911 +        public void clear() {
 226.912 +            WeakHashMap.this.clear();
 226.913 +        }
 226.914 +    }
 226.915 +
 226.916 +    /**
 226.917 +     * Returns a {@link Set} view of the mappings contained in this map.
 226.918 +     * The set is backed by the map, so changes to the map are
 226.919 +     * reflected in the set, and vice-versa.  If the map is modified
 226.920 +     * while an iteration over the set is in progress (except through
 226.921 +     * the iterator's own <tt>remove</tt> operation, or through the
 226.922 +     * <tt>setValue</tt> operation on a map entry returned by the
 226.923 +     * iterator) the results of the iteration are undefined.  The set
 226.924 +     * supports element removal, which removes the corresponding
 226.925 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
 226.926 +     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
 226.927 +     * <tt>clear</tt> operations.  It does not support the
 226.928 +     * <tt>add</tt> or <tt>addAll</tt> operations.
 226.929 +     */
 226.930 +    public Set<Map.Entry<K,V>> entrySet() {
 226.931 +        Set<Map.Entry<K,V>> es = entrySet;
 226.932 +        return es != null ? es : (entrySet = new EntrySet());
 226.933 +    }
 226.934 +
 226.935 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 226.936 +        public Iterator<Map.Entry<K,V>> iterator() {
 226.937 +            return new EntryIterator();
 226.938 +        }
 226.939 +
 226.940 +        public boolean contains(Object o) {
 226.941 +            if (!(o instanceof Map.Entry))
 226.942 +                return false;
 226.943 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
 226.944 +            Entry<K,V> candidate = getEntry(e.getKey());
 226.945 +            return candidate != null && candidate.equals(e);
 226.946 +        }
 226.947 +
 226.948 +        public boolean remove(Object o) {
 226.949 +            return removeMapping(o);
 226.950 +        }
 226.951 +
 226.952 +        public int size() {
 226.953 +            return WeakHashMap.this.size();
 226.954 +        }
 226.955 +
 226.956 +        public void clear() {
 226.957 +            WeakHashMap.this.clear();
 226.958 +        }
 226.959 +
 226.960 +        private List<Map.Entry<K,V>> deepCopy() {
 226.961 +            List<Map.Entry<K,V>> list = new ArrayList<>(size());
 226.962 +            for (Map.Entry<K,V> e : this)
 226.963 +                list.add(new AbstractMap.SimpleEntry<>(e));
 226.964 +            return list;
 226.965 +        }
 226.966 +
 226.967 +        public Object[] toArray() {
 226.968 +            return deepCopy().toArray();
 226.969 +        }
 226.970 +
 226.971 +        public <T> T[] toArray(T[] a) {
 226.972 +            return deepCopy().toArray(a);
 226.973 +        }
 226.974 +    }
 226.975 +}
   227.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   227.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/ConcurrentHashMap.java	Wed Apr 30 15:04:10 2014 +0200
   227.3 @@ -0,0 +1,327 @@
   227.4 +/*
   227.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   227.6 + *
   227.7 + * This code is free software; you can redistribute it and/or modify it
   227.8 + * under the terms of the GNU General Public License version 2 only, as
   227.9 + * published by the Free Software Foundation.  Oracle designates this
  227.10 + * particular file as subject to the "Classpath" exception as provided
  227.11 + * by Oracle in the LICENSE file that accompanied this code.
  227.12 + *
  227.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  227.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  227.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  227.16 + * version 2 for more details (a copy is included in the LICENSE file that
  227.17 + * accompanied this code).
  227.18 + *
  227.19 + * You should have received a copy of the GNU General Public License version
  227.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  227.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  227.22 + *
  227.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  227.24 + * or visit www.oracle.com if you need additional information or have any
  227.25 + * questions.
  227.26 + */
  227.27 +
  227.28 +/*
  227.29 + * This file is available under and governed by the GNU General Public
  227.30 + * License version 2 only, as published by the Free Software Foundation.
  227.31 + * However, the following notice accompanied the original version of this
  227.32 + * file:
  227.33 + *
  227.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  227.35 + * Expert Group and released to the public domain, as explained at
  227.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  227.37 + */
  227.38 +package java.util.concurrent;
  227.39 +
  227.40 +import java.util.*;
  227.41 +import java.io.Serializable;
  227.42 +import java.io.IOException;
  227.43 +import java.io.ObjectInputStream;
  227.44 +import java.io.ObjectOutputStream;
  227.45 +
  227.46 +/**
  227.47 + * A hash table supporting full concurrency of retrievals and adjustable
  227.48 + * expected concurrency for updates. This class obeys the same functional
  227.49 + * specification as {@link java.util.Hashtable}, and includes versions of
  227.50 + * methods corresponding to each method of
  227.51 + * <tt>Hashtable</tt>. However, even though all operations are thread-safe,
  227.52 + * retrieval operations do <em>not</em> entail locking, and there is
  227.53 + * <em>not</em> any support for locking the entire table in a way that prevents
  227.54 + * all access. This class is fully interoperable with <tt>Hashtable</tt> in
  227.55 + * programs that rely on its thread safety but not on its synchronization
  227.56 + * details.
  227.57 + *
  227.58 + * <p>
  227.59 + * Retrieval operations (including <tt>get</tt>) generally do not block, so may
  227.60 + * overlap with update operations (including
  227.61 + * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results of the most
  227.62 + * recently <em>completed</em> update operations holding upon their onset. For
  227.63 + * aggregate operations such as <tt>putAll</tt>
  227.64 + * and <tt>clear</tt>, concurrent retrievals may reflect insertion or removal of
  227.65 + * only some entries. Similarly, Iterators and Enumerations return elements
  227.66 + * reflecting the state of the hash table at some point at or since the creation
  227.67 + * of the iterator/enumeration. They do <em>not</em> throw
  227.68 + * {@link ConcurrentModificationException}. However, iterators are designed to
  227.69 + * be used by only one thread at a time.
  227.70 + *
  227.71 + * <p>
  227.72 + * The allowed concurrency among update operations is guided by the optional
  227.73 + * <tt>concurrencyLevel</tt> constructor argument (default <tt>16</tt>), which
  227.74 + * is used as a hint for internal sizing. The table is internally partitioned to
  227.75 + * try to permit the indicated number of concurrent updates without contention.
  227.76 + * Because placement in hash tables is essentially random, the actual
  227.77 + * concurrency will vary. Ideally, you should choose a value to accommodate as
  227.78 + * many threads as will ever concurrently modify the table. Using a
  227.79 + * significantly higher value than you need can waste space and time, and a
  227.80 + * significantly lower value can lead to thread contention. But overestimates
  227.81 + * and underestimates within an order of magnitude do not usually have much
  227.82 + * noticeable impact. A value of one is appropriate when it is known that only
  227.83 + * one thread will modify and all others will only read. Also, resizing this or
  227.84 + * any other kind of hash table is a relatively slow operation, so, when
  227.85 + * possible, it is a good idea to provide estimates of expected table sizes in
  227.86 + * constructors.
  227.87 + *
  227.88 + * <p>
  227.89 + * This class and its views and iterators implement all of the
  227.90 + * <em>optional</em> methods of the {@link Map} and {@link Iterator} interfaces.
  227.91 + *
  227.92 + * <p>
  227.93 + * Like {@link Hashtable} but unlike {@link HashMap}, this class does
  227.94 + * <em>not</em> allow <tt>null</tt> to be used as a key or value.
  227.95 + *
  227.96 + * <p>
  227.97 + * This class is a member of the
  227.98 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  227.99 + * Java Collections Framework</a>.
 227.100 + *
 227.101 + * @since 1.5
 227.102 + * @author Doug Lea
 227.103 + * @param <K> the type of keys maintained by this map
 227.104 + * @param <V> the type of mapped values
 227.105 + */
 227.106 +public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
 227.107 +    implements ConcurrentMap<K, V>, Serializable {
 227.108 +
 227.109 +    private static final long serialVersionUID = 7249069246763182397L;
 227.110 +    /**
 227.111 +     * The default initial capacity for this table,
 227.112 +     * used when not otherwise specified in a constructor.
 227.113 +     */
 227.114 +    static final int DEFAULT_INITIAL_CAPACITY = 16;
 227.115 +
 227.116 +    /**
 227.117 +     * The default load factor for this table, used when not
 227.118 +     * otherwise specified in a constructor.
 227.119 +     */
 227.120 +    static final float DEFAULT_LOAD_FACTOR = 0.75f;
 227.121 +
 227.122 +    /**
 227.123 +     * The default concurrency level for this table, used when not
 227.124 +     * otherwise specified in a constructor.
 227.125 +     */
 227.126 +    static final int DEFAULT_CONCURRENCY_LEVEL = 16;
 227.127 +
 227.128 +    private final Map<K, V> delegate;
 227.129 +
 227.130 +
 227.131 +    /**
 227.132 +     * Creates a new, empty map with the specified initial
 227.133 +     * capacity, load factor and concurrency level.
 227.134 +     *
 227.135 +     * @param initialCapacity the initial capacity. The implementation
 227.136 +     * performs internal sizing to accommodate this many elements.
 227.137 +     * @param loadFactor  the load factor threshold, used to control resizing.
 227.138 +     * Resizing may be performed when the average number of elements per
 227.139 +     * bin exceeds this threshold.
 227.140 +     * @param concurrencyLevel the estimated number of concurrently
 227.141 +     * updating threads. The implementation performs internal sizing
 227.142 +     * to try to accommodate this many threads.
 227.143 +     * @throws IllegalArgumentException if the initial capacity is
 227.144 +     * negative or the load factor or concurrencyLevel are
 227.145 +     * nonpositive.
 227.146 +     */
 227.147 +    @SuppressWarnings("unchecked")
 227.148 +    public ConcurrentHashMap(int initialCapacity,
 227.149 +                             float loadFactor, int concurrencyLevel) {
 227.150 +        if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
 227.151 +            throw new IllegalArgumentException();
 227.152 +        delegate = new HashMap<>(initialCapacity, loadFactor);
 227.153 +    }
 227.154 +
 227.155 +    /**
 227.156 +     * Creates a new, empty map with the specified initial capacity
 227.157 +     * and load factor and with the default concurrencyLevel (16).
 227.158 +     *
 227.159 +     * @param initialCapacity The implementation performs internal
 227.160 +     * sizing to accommodate this many elements.
 227.161 +     * @param loadFactor  the load factor threshold, used to control resizing.
 227.162 +     * Resizing may be performed when the average number of elements per
 227.163 +     * bin exceeds this threshold.
 227.164 +     * @throws IllegalArgumentException if the initial capacity of
 227.165 +     * elements is negative or the load factor is nonpositive
 227.166 +     *
 227.167 +     * @since 1.6
 227.168 +     */
 227.169 +    public ConcurrentHashMap(int initialCapacity, float loadFactor) {
 227.170 +        this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
 227.171 +    }
 227.172 +
 227.173 +    /**
 227.174 +     * Creates a new, empty map with the specified initial capacity,
 227.175 +     * and with default load factor (0.75) and concurrencyLevel (16).
 227.176 +     *
 227.177 +     * @param initialCapacity the initial capacity. The implementation
 227.178 +     * performs internal sizing to accommodate this many elements.
 227.179 +     * @throws IllegalArgumentException if the initial capacity of
 227.180 +     * elements is negative.
 227.181 +     */
 227.182 +    public ConcurrentHashMap(int initialCapacity) {
 227.183 +        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
 227.184 +    }
 227.185 +
 227.186 +    /**
 227.187 +     * Creates a new, empty map with a default initial capacity (16),
 227.188 +     * load factor (0.75) and concurrencyLevel (16).
 227.189 +     */
 227.190 +    public ConcurrentHashMap() {
 227.191 +        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
 227.192 +    }
 227.193 +
 227.194 +    /**
 227.195 +     * Creates a new map with the same mappings as the given map.
 227.196 +     * The map is created with a capacity of 1.5 times the number
 227.197 +     * of mappings in the given map or 16 (whichever is greater),
 227.198 +     * and a default load factor (0.75) and concurrencyLevel (16).
 227.199 +     *
 227.200 +     * @param m the map
 227.201 +     */
 227.202 +    public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
 227.203 +        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
 227.204 +                      DEFAULT_INITIAL_CAPACITY),
 227.205 +             DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
 227.206 +        putAll(m);
 227.207 +    }
 227.208 +    
 227.209 +
 227.210 +    @Override
 227.211 +    public int size() {
 227.212 +        return delegate.size();
 227.213 +    }
 227.214 +
 227.215 +    @Override
 227.216 +    public boolean isEmpty() {
 227.217 +        return delegate.isEmpty();
 227.218 +    }
 227.219 +
 227.220 +    @Override
 227.221 +    public boolean containsKey(Object key) {
 227.222 +        return delegate.containsKey(key);
 227.223 +    }
 227.224 +
 227.225 +    @Override
 227.226 +    public boolean containsValue(Object value) {
 227.227 +        return delegate.containsValue(value);
 227.228 +    }
 227.229 +
 227.230 +    @Override
 227.231 +    public V get(Object key) {
 227.232 +        return delegate.get(key);
 227.233 +    }
 227.234 +
 227.235 +    @Override
 227.236 +    public V put(K key, V value) {
 227.237 +        return delegate.put(key, value);
 227.238 +    }
 227.239 +
 227.240 +    @Override
 227.241 +    public V remove(Object key) {
 227.242 +        return delegate.remove(key);
 227.243 +    }
 227.244 +
 227.245 +    @Override
 227.246 +    public void putAll(Map<? extends K, ? extends V> m) {
 227.247 +        delegate.putAll(m);
 227.248 +    }
 227.249 +
 227.250 +    @Override
 227.251 +    public void clear() {
 227.252 +        delegate.clear();
 227.253 +    }
 227.254 +
 227.255 +    @Override
 227.256 +    public Set<K> keySet() {
 227.257 +        return delegate.keySet();
 227.258 +    }
 227.259 +
 227.260 +    @Override
 227.261 +    public Collection<V> values() {
 227.262 +        return delegate.values();
 227.263 +    }
 227.264 +
 227.265 +    @Override
 227.266 +    public Set<Entry<K, V>> entrySet() {
 227.267 +        return delegate.entrySet();
 227.268 +    }
 227.269 +
 227.270 +    @Override
 227.271 +    public boolean equals(Object o) {
 227.272 +        return delegate.equals(o);
 227.273 +    }
 227.274 +
 227.275 +    @Override
 227.276 +    public int hashCode() {
 227.277 +        return delegate.hashCode();
 227.278 +    }
 227.279 +
 227.280 +    @Override
 227.281 +    public String toString() {
 227.282 +        return delegate.toString();
 227.283 +    }
 227.284 +
 227.285 +    @Override
 227.286 +    public V putIfAbsent(K key, V value) {
 227.287 +        V old = delegate.get(key);
 227.288 +        if (old == null) {
 227.289 +            return delegate.put(key, value);
 227.290 +        }
 227.291 +        return old;
 227.292 +    }
 227.293 +
 227.294 +    @Override
 227.295 +    public boolean remove(Object key, Object value) {
 227.296 +        if (equals(value, delegate.get(key))) {
 227.297 +            delegate.remove(key);
 227.298 +            return true;
 227.299 +        } else {
 227.300 +            return false;
 227.301 +        }
 227.302 +    }
 227.303 +
 227.304 +    @Override
 227.305 +    public boolean replace(K key, V oldValue, V newValue) {
 227.306 +        if (equals(oldValue, delegate.get(key))) {
 227.307 +            delegate.put(key, newValue);
 227.308 +            return true;
 227.309 +        } else {
 227.310 +            return false;
 227.311 +        }
 227.312 +    }
 227.313 +
 227.314 +    @Override
 227.315 +    public V replace(K key, V value) {
 227.316 +        if (delegate.containsKey(key)) {
 227.317 +            return delegate.put(key, value);
 227.318 +        } else {
 227.319 +            return null;
 227.320 +        }
 227.321 +    }
 227.322 +    
 227.323 +    private static boolean equals(Object a, Object b) {
 227.324 +        if (a == null) {
 227.325 +            return b == null;
 227.326 +        } else {
 227.327 +            return a.equals(b);
 227.328 +        }
 227.329 +    }
 227.330 +}
   228.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   228.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/ConcurrentMap.java	Wed Apr 30 15:04:10 2014 +0200
   228.3 @@ -0,0 +1,165 @@
   228.4 +/*
   228.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   228.6 + *
   228.7 + * This code is free software; you can redistribute it and/or modify it
   228.8 + * under the terms of the GNU General Public License version 2 only, as
   228.9 + * published by the Free Software Foundation.  Oracle designates this
  228.10 + * particular file as subject to the "Classpath" exception as provided
  228.11 + * by Oracle in the LICENSE file that accompanied this code.
  228.12 + *
  228.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  228.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  228.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  228.16 + * version 2 for more details (a copy is included in the LICENSE file that
  228.17 + * accompanied this code).
  228.18 + *
  228.19 + * You should have received a copy of the GNU General Public License version
  228.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  228.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  228.22 + *
  228.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  228.24 + * or visit www.oracle.com if you need additional information or have any
  228.25 + * questions.
  228.26 + */
  228.27 +
  228.28 +/*
  228.29 + * This file is available under and governed by the GNU General Public
  228.30 + * License version 2 only, as published by the Free Software Foundation.
  228.31 + * However, the following notice accompanied the original version of this
  228.32 + * file:
  228.33 + *
  228.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  228.35 + * Expert Group and released to the public domain, as explained at
  228.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  228.37 + */
  228.38 +
  228.39 +package java.util.concurrent;
  228.40 +import java.util.Map;
  228.41 +
  228.42 +/**
  228.43 + * A {@link java.util.Map} providing additional atomic
  228.44 + * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
  228.45 + *
  228.46 + * <p>Memory consistency effects: As with other concurrent
  228.47 + * collections, actions in a thread prior to placing an object into a
  228.48 + * {@code ConcurrentMap} as a key or value
  228.49 + * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  228.50 + * actions subsequent to the access or removal of that object from
  228.51 + * the {@code ConcurrentMap} in another thread.
  228.52 + *
  228.53 + * <p>This interface is a member of the
  228.54 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  228.55 + * Java Collections Framework</a>.
  228.56 + *
  228.57 + * @since 1.5
  228.58 + * @author Doug Lea
  228.59 + * @param <K> the type of keys maintained by this map
  228.60 + * @param <V> the type of mapped values
  228.61 + */
  228.62 +public interface ConcurrentMap<K, V> extends Map<K, V> {
  228.63 +    /**
  228.64 +     * If the specified key is not already associated
  228.65 +     * with a value, associate it with the given value.
  228.66 +     * This is equivalent to
  228.67 +     * <pre>
  228.68 +     *   if (!map.containsKey(key))
  228.69 +     *       return map.put(key, value);
  228.70 +     *   else
  228.71 +     *       return map.get(key);</pre>
  228.72 +     * except that the action is performed atomically.
  228.73 +     *
  228.74 +     * @param key key with which the specified value is to be associated
  228.75 +     * @param value value to be associated with the specified key
  228.76 +     * @return the previous value associated with the specified key, or
  228.77 +     *         <tt>null</tt> if there was no mapping for the key.
  228.78 +     *         (A <tt>null</tt> return can also indicate that the map
  228.79 +     *         previously associated <tt>null</tt> with the key,
  228.80 +     *         if the implementation supports null values.)
  228.81 +     * @throws UnsupportedOperationException if the <tt>put</tt> operation
  228.82 +     *         is not supported by this map
  228.83 +     * @throws ClassCastException if the class of the specified key or value
  228.84 +     *         prevents it from being stored in this map
  228.85 +     * @throws NullPointerException if the specified key or value is null,
  228.86 +     *         and this map does not permit null keys or values
  228.87 +     * @throws IllegalArgumentException if some property of the specified key
  228.88 +     *         or value prevents it from being stored in this map
  228.89 +     *
  228.90 +     */
  228.91 +    V putIfAbsent(K key, V value);
  228.92 +
  228.93 +    /**
  228.94 +     * Removes the entry for a key only if currently mapped to a given value.
  228.95 +     * This is equivalent to
  228.96 +     * <pre>
  228.97 +     *   if (map.containsKey(key) &amp;&amp; map.get(key).equals(value)) {
  228.98 +     *       map.remove(key);
  228.99 +     *       return true;
 228.100 +     *   } else return false;</pre>
 228.101 +     * except that the action is performed atomically.
 228.102 +     *
 228.103 +     * @param key key with which the specified value is associated
 228.104 +     * @param value value expected to be associated with the specified key
 228.105 +     * @return <tt>true</tt> if the value was removed
 228.106 +     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
 228.107 +     *         is not supported by this map
 228.108 +     * @throws ClassCastException if the key or value is of an inappropriate
 228.109 +     *         type for this map
 228.110 +     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 228.111 +     * @throws NullPointerException if the specified key or value is null,
 228.112 +     *         and this map does not permit null keys or values
 228.113 +     *         (<a href="../Collection.html#optional-restrictions">optional</a>)
 228.114 +     */
 228.115 +    boolean remove(Object key, Object value);
 228.116 +
 228.117 +    /**
 228.118 +     * Replaces the entry for a key only if currently mapped to a given value.
 228.119 +     * This is equivalent to
 228.120 +     * <pre>
 228.121 +     *   if (map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
 228.122 +     *       map.put(key, newValue);
 228.123 +     *       return true;
 228.124 +     *   } else return false;</pre>
 228.125 +     * except that the action is performed atomically.
 228.126 +     *
 228.127 +     * @param key key with which the specified value is associated
 228.128 +     * @param oldValue value expected to be associated with the specified key
 228.129 +     * @param newValue value to be associated with the specified key
 228.130 +     * @return <tt>true</tt> if the value was replaced
 228.131 +     * @throws UnsupportedOperationException if the <tt>put</tt> operation
 228.132 +     *         is not supported by this map
 228.133 +     * @throws ClassCastException if the class of a specified key or value
 228.134 +     *         prevents it from being stored in this map
 228.135 +     * @throws NullPointerException if a specified key or value is null,
 228.136 +     *         and this map does not permit null keys or values
 228.137 +     * @throws IllegalArgumentException if some property of a specified key
 228.138 +     *         or value prevents it from being stored in this map
 228.139 +     */
 228.140 +    boolean replace(K key, V oldValue, V newValue);
 228.141 +
 228.142 +    /**
 228.143 +     * Replaces the entry for a key only if currently mapped to some value.
 228.144 +     * This is equivalent to
 228.145 +     * <pre>
 228.146 +     *   if (map.containsKey(key)) {
 228.147 +     *       return map.put(key, value);
 228.148 +     *   } else return null;</pre>
 228.149 +     * except that the action is performed atomically.
 228.150 +     *
 228.151 +     * @param key key with which the specified value is associated
 228.152 +     * @param value value to be associated with the specified key
 228.153 +     * @return the previous value associated with the specified key, or
 228.154 +     *         <tt>null</tt> if there was no mapping for the key.
 228.155 +     *         (A <tt>null</tt> return can also indicate that the map
 228.156 +     *         previously associated <tt>null</tt> with the key,
 228.157 +     *         if the implementation supports null values.)
 228.158 +     * @throws UnsupportedOperationException if the <tt>put</tt> operation
 228.159 +     *         is not supported by this map
 228.160 +     * @throws ClassCastException if the class of the specified key or value
 228.161 +     *         prevents it from being stored in this map
 228.162 +     * @throws NullPointerException if the specified key or value is null,
 228.163 +     *         and this map does not permit null keys or values
 228.164 +     * @throws IllegalArgumentException if some property of the specified key
 228.165 +     *         or value prevents it from being stored in this map
 228.166 +     */
 228.167 +    V replace(K key, V value);
 228.168 +}
   229.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   229.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/Executor.java	Wed Apr 30 15:04:10 2014 +0200
   229.3 @@ -0,0 +1,141 @@
   229.4 +/*
   229.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   229.6 + *
   229.7 + * This code is free software; you can redistribute it and/or modify it
   229.8 + * under the terms of the GNU General Public License version 2 only, as
   229.9 + * published by the Free Software Foundation.  Oracle designates this
  229.10 + * particular file as subject to the "Classpath" exception as provided
  229.11 + * by Oracle in the LICENSE file that accompanied this code.
  229.12 + *
  229.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  229.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  229.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  229.16 + * version 2 for more details (a copy is included in the LICENSE file that
  229.17 + * accompanied this code).
  229.18 + *
  229.19 + * You should have received a copy of the GNU General Public License version
  229.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  229.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  229.22 + *
  229.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  229.24 + * or visit www.oracle.com if you need additional information or have any
  229.25 + * questions.
  229.26 + */
  229.27 +
  229.28 +/*
  229.29 + * This file is available under and governed by the GNU General Public
  229.30 + * License version 2 only, as published by the Free Software Foundation.
  229.31 + * However, the following notice accompanied the original version of this
  229.32 + * file:
  229.33 + *
  229.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  229.35 + * Expert Group and released to the public domain, as explained at
  229.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  229.37 + */
  229.38 +
  229.39 +package java.util.concurrent;
  229.40 +
  229.41 +/**
  229.42 + * An object that executes submitted {@link Runnable} tasks. This
  229.43 + * interface provides a way of decoupling task submission from the
  229.44 + * mechanics of how each task will be run, including details of thread
  229.45 + * use, scheduling, etc.  An <tt>Executor</tt> is normally used
  229.46 + * instead of explicitly creating threads. For example, rather than
  229.47 + * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
  229.48 + * of a set of tasks, you might use:
  229.49 + *
  229.50 + * <pre>
  229.51 + * Executor executor = <em>anExecutor</em>;
  229.52 + * executor.execute(new RunnableTask1());
  229.53 + * executor.execute(new RunnableTask2());
  229.54 + * ...
  229.55 + * </pre>
  229.56 + *
  229.57 + * However, the <tt>Executor</tt> interface does not strictly
  229.58 + * require that execution be asynchronous. In the simplest case, an
  229.59 + * executor can run the submitted task immediately in the caller's
  229.60 + * thread:
  229.61 + *
  229.62 + * <pre>
  229.63 + * class DirectExecutor implements Executor {
  229.64 + *     public void execute(Runnable r) {
  229.65 + *         r.run();
  229.66 + *     }
  229.67 + * }</pre>
  229.68 + *
  229.69 + * More typically, tasks are executed in some thread other
  229.70 + * than the caller's thread.  The executor below spawns a new thread
  229.71 + * for each task.
  229.72 + *
  229.73 + * <pre>
  229.74 + * class ThreadPerTaskExecutor implements Executor {
  229.75 + *     public void execute(Runnable r) {
  229.76 + *         new Thread(r).start();
  229.77 + *     }
  229.78 + * }</pre>
  229.79 + *
  229.80 + * Many <tt>Executor</tt> implementations impose some sort of
  229.81 + * limitation on how and when tasks are scheduled.  The executor below
  229.82 + * serializes the submission of tasks to a second executor,
  229.83 + * illustrating a composite executor.
  229.84 + *
  229.85 + *  <pre> {@code
  229.86 + * class SerialExecutor implements Executor {
  229.87 + *   final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
  229.88 + *   final Executor executor;
  229.89 + *   Runnable active;
  229.90 + *
  229.91 + *   SerialExecutor(Executor executor) {
  229.92 + *     this.executor = executor;
  229.93 + *   }
  229.94 + *
  229.95 + *   public synchronized void execute(final Runnable r) {
  229.96 + *     tasks.offer(new Runnable() {
  229.97 + *       public void run() {
  229.98 + *         try {
  229.99 + *           r.run();
 229.100 + *         } finally {
 229.101 + *           scheduleNext();
 229.102 + *         }
 229.103 + *       }
 229.104 + *     });
 229.105 + *     if (active == null) {
 229.106 + *       scheduleNext();
 229.107 + *     }
 229.108 + *   }
 229.109 + *
 229.110 + *   protected synchronized void scheduleNext() {
 229.111 + *     if ((active = tasks.poll()) != null) {
 229.112 + *       executor.execute(active);
 229.113 + *     }
 229.114 + *   }
 229.115 + * }}</pre>
 229.116 + *
 229.117 + * The <tt>Executor</tt> implementations provided in this package
 229.118 + * implement {@link ExecutorService}, which is a more extensive
 229.119 + * interface.  The {@link ThreadPoolExecutor} class provides an
 229.120 + * extensible thread pool implementation. The {@link Executors} class
 229.121 + * provides convenient factory methods for these Executors.
 229.122 + *
 229.123 + * <p>Memory consistency effects: Actions in a thread prior to
 229.124 + * submitting a {@code Runnable} object to an {@code Executor}
 229.125 + * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
 229.126 + * its execution begins, perhaps in another thread.
 229.127 + *
 229.128 + * @since 1.5
 229.129 + * @author Doug Lea
 229.130 + */
 229.131 +public interface Executor {
 229.132 +
 229.133 +    /**
 229.134 +     * Executes the given command at some time in the future.  The command
 229.135 +     * may execute in a new thread, in a pooled thread, or in the calling
 229.136 +     * thread, at the discretion of the <tt>Executor</tt> implementation.
 229.137 +     *
 229.138 +     * @param command the runnable task
 229.139 +     * @throws RejectedExecutionException if this task cannot be
 229.140 +     * accepted for execution.
 229.141 +     * @throws NullPointerException if command is null
 229.142 +     */
 229.143 +    void execute(Runnable command);
 229.144 +}
   230.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   230.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java	Wed Apr 30 15:04:10 2014 +0200
   230.3 @@ -0,0 +1,155 @@
   230.4 +/*
   230.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   230.6 + *
   230.7 + * This code is free software; you can redistribute it and/or modify it
   230.8 + * under the terms of the GNU General Public License version 2 only, as
   230.9 + * published by the Free Software Foundation.  Oracle designates this
  230.10 + * particular file as subject to the "Classpath" exception as provided
  230.11 + * by Oracle in the LICENSE file that accompanied this code.
  230.12 + *
  230.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  230.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  230.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  230.16 + * version 2 for more details (a copy is included in the LICENSE file that
  230.17 + * accompanied this code).
  230.18 + *
  230.19 + * You should have received a copy of the GNU General Public License version
  230.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  230.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  230.22 + *
  230.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  230.24 + * or visit www.oracle.com if you need additional information or have any
  230.25 + * questions.
  230.26 + */
  230.27 +
  230.28 +/*
  230.29 + * This file is available under and governed by the GNU General Public
  230.30 + * License version 2 only, as published by the Free Software Foundation.
  230.31 + * However, the following notice accompanied the original version of this
  230.32 + * file:
  230.33 + *
  230.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  230.35 + * Expert Group and released to the public domain, as explained at
  230.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  230.37 + */
  230.38 +
  230.39 +package java.util.concurrent.atomic;
  230.40 +
  230.41 +/**
  230.42 + * A {@code boolean} value that may be updated atomically. See the
  230.43 + * {@link java.util.concurrent.atomic} package specification for
  230.44 + * description of the properties of atomic variables. An
  230.45 + * {@code AtomicBoolean} is used in applications such as atomically
  230.46 + * updated flags, and cannot be used as a replacement for a
  230.47 + * {@link java.lang.Boolean}.
  230.48 + *
  230.49 + * @since 1.5
  230.50 + * @author Doug Lea
  230.51 + */
  230.52 +public class AtomicBoolean implements java.io.Serializable {
  230.53 +    private static final long serialVersionUID = 4654671469794556979L;
  230.54 +
  230.55 +    private volatile int value;
  230.56 +
  230.57 +    /**
  230.58 +     * Creates a new {@code AtomicBoolean} with the given initial value.
  230.59 +     *
  230.60 +     * @param initialValue the initial value
  230.61 +     */
  230.62 +    public AtomicBoolean(boolean initialValue) {
  230.63 +        value = initialValue ? 1 : 0;
  230.64 +    }
  230.65 +
  230.66 +    /**
  230.67 +     * Creates a new {@code AtomicBoolean} with initial value {@code false}.
  230.68 +     */
  230.69 +    public AtomicBoolean() {
  230.70 +    }
  230.71 +
  230.72 +    /**
  230.73 +     * Returns the current value.
  230.74 +     *
  230.75 +     * @return the current value
  230.76 +     */
  230.77 +    public final boolean get() {
  230.78 +        return value != 0;
  230.79 +    }
  230.80 +
  230.81 +    /**
  230.82 +     * Atomically sets the value to the given updated value
  230.83 +     * if the current value {@code ==} the expected value.
  230.84 +     *
  230.85 +     * @param expect the expected value
  230.86 +     * @param update the new value
  230.87 +     * @return true if successful. False return indicates that
  230.88 +     * the actual value was not equal to the expected value.
  230.89 +     */
  230.90 +    public final boolean compareAndSet(boolean expect, boolean update) {
  230.91 +        int e = expect ? 1 : 0;
  230.92 +        int u = update ? 1 : 0;
  230.93 +        if (this.value == e) {
  230.94 +            this.value = u;
  230.95 +            return true;
  230.96 +        } else {
  230.97 +            return false;
  230.98 +        }
  230.99 +    }
 230.100 +
 230.101 +    /**
 230.102 +     * Atomically sets the value to the given updated value
 230.103 +     * if the current value {@code ==} the expected value.
 230.104 +     *
 230.105 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 230.106 +     * and does not provide ordering guarantees, so is only rarely an
 230.107 +     * appropriate alternative to {@code compareAndSet}.
 230.108 +     *
 230.109 +     * @param expect the expected value
 230.110 +     * @param update the new value
 230.111 +     * @return true if successful.
 230.112 +     */
 230.113 +    public boolean weakCompareAndSet(boolean expect, boolean update) {
 230.114 +        return compareAndSet(expect, update);
 230.115 +    }
 230.116 +
 230.117 +    /**
 230.118 +     * Unconditionally sets to the given value.
 230.119 +     *
 230.120 +     * @param newValue the new value
 230.121 +     */
 230.122 +    public final void set(boolean newValue) {
 230.123 +        value = newValue ? 1 : 0;
 230.124 +    }
 230.125 +
 230.126 +    /**
 230.127 +     * Eventually sets to the given value.
 230.128 +     *
 230.129 +     * @param newValue the new value
 230.130 +     * @since 1.6
 230.131 +     */
 230.132 +    public final void lazySet(boolean newValue) {
 230.133 +        set(newValue);
 230.134 +    }
 230.135 +
 230.136 +    /**
 230.137 +     * Atomically sets to the given value and returns the previous value.
 230.138 +     *
 230.139 +     * @param newValue the new value
 230.140 +     * @return the previous value
 230.141 +     */
 230.142 +    public final boolean getAndSet(boolean newValue) {
 230.143 +        for (;;) {
 230.144 +            boolean current = get();
 230.145 +            if (compareAndSet(current, newValue))
 230.146 +                return current;
 230.147 +        }
 230.148 +    }
 230.149 +
 230.150 +    /**
 230.151 +     * Returns the String representation of the current value.
 230.152 +     * @return the String representation of the current value.
 230.153 +     */
 230.154 +    public String toString() {
 230.155 +        return Boolean.toString(get());
 230.156 +    }
 230.157 +
 230.158 +}
   231.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   231.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicInteger.java	Wed Apr 30 15:04:10 2014 +0200
   231.3 @@ -0,0 +1,258 @@
   231.4 +/*
   231.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   231.6 + *
   231.7 + * This code is free software; you can redistribute it and/or modify it
   231.8 + * under the terms of the GNU General Public License version 2 only, as
   231.9 + * published by the Free Software Foundation.  Oracle designates this
  231.10 + * particular file as subject to the "Classpath" exception as provided
  231.11 + * by Oracle in the LICENSE file that accompanied this code.
  231.12 + *
  231.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  231.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  231.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  231.16 + * version 2 for more details (a copy is included in the LICENSE file that
  231.17 + * accompanied this code).
  231.18 + *
  231.19 + * You should have received a copy of the GNU General Public License version
  231.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  231.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  231.22 + *
  231.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  231.24 + * or visit www.oracle.com if you need additional information or have any
  231.25 + * questions.
  231.26 + */
  231.27 +
  231.28 +/*
  231.29 + * This file is available under and governed by the GNU General Public
  231.30 + * License version 2 only, as published by the Free Software Foundation.
  231.31 + * However, the following notice accompanied the original version of this
  231.32 + * file:
  231.33 + *
  231.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  231.35 + * Expert Group and released to the public domain, as explained at
  231.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  231.37 + */
  231.38 +
  231.39 +package java.util.concurrent.atomic;
  231.40 +
  231.41 +/**
  231.42 + * An {@code int} value that may be updated atomically.  See the
  231.43 + * {@link java.util.concurrent.atomic} package specification for
  231.44 + * description of the properties of atomic variables. An
  231.45 + * {@code AtomicInteger} is used in applications such as atomically
  231.46 + * incremented counters, and cannot be used as a replacement for an
  231.47 + * {@link java.lang.Integer}. However, this class does extend
  231.48 + * {@code Number} to allow uniform access by tools and utilities that
  231.49 + * deal with numerically-based classes.
  231.50 + *
  231.51 + * @since 1.5
  231.52 + * @author Doug Lea
  231.53 +*/
  231.54 +public class AtomicInteger extends Number implements java.io.Serializable {
  231.55 +    private static final long serialVersionUID = 6214790243416807050L;
  231.56 +
  231.57 +    private volatile int value;
  231.58 +
  231.59 +    /**
  231.60 +     * Creates a new AtomicInteger with the given initial value.
  231.61 +     *
  231.62 +     * @param initialValue the initial value
  231.63 +     */
  231.64 +    public AtomicInteger(int initialValue) {
  231.65 +        value = initialValue;
  231.66 +    }
  231.67 +
  231.68 +    /**
  231.69 +     * Creates a new AtomicInteger with initial value {@code 0}.
  231.70 +     */
  231.71 +    public AtomicInteger() {
  231.72 +    }
  231.73 +
  231.74 +    /**
  231.75 +     * Gets the current value.
  231.76 +     *
  231.77 +     * @return the current value
  231.78 +     */
  231.79 +    public final int get() {
  231.80 +        return value;
  231.81 +    }
  231.82 +
  231.83 +    /**
  231.84 +     * Sets to the given value.
  231.85 +     *
  231.86 +     * @param newValue the new value
  231.87 +     */
  231.88 +    public final void set(int newValue) {
  231.89 +        value = newValue;
  231.90 +    }
  231.91 +
  231.92 +    /**
  231.93 +     * Eventually sets to the given value.
  231.94 +     *
  231.95 +     * @param newValue the new value
  231.96 +     * @since 1.6
  231.97 +     */
  231.98 +    public final void lazySet(int newValue) {
  231.99 +        value = newValue;
 231.100 +    }
 231.101 +
 231.102 +    /**
 231.103 +     * Atomically sets to the given value and returns the old value.
 231.104 +     *
 231.105 +     * @param newValue the new value
 231.106 +     * @return the previous value
 231.107 +     */
 231.108 +    public final int getAndSet(int newValue) {
 231.109 +        for (;;) {
 231.110 +            int current = get();
 231.111 +            if (compareAndSet(current, newValue))
 231.112 +                return current;
 231.113 +        }
 231.114 +    }
 231.115 +
 231.116 +    /**
 231.117 +     * Atomically sets the value to the given updated value
 231.118 +     * if the current value {@code ==} the expected value.
 231.119 +     *
 231.120 +     * @param expect the expected value
 231.121 +     * @param update the new value
 231.122 +     * @return true if successful. False return indicates that
 231.123 +     * the actual value was not equal to the expected value.
 231.124 +     */
 231.125 +    public final boolean compareAndSet(int expect, int update) {
 231.126 +        if (value == expect) {
 231.127 +            value = update;
 231.128 +            return true;
 231.129 +        } else {
 231.130 +            return false;
 231.131 +        }
 231.132 +    }
 231.133 +
 231.134 +    /**
 231.135 +     * Atomically sets the value to the given updated value
 231.136 +     * if the current value {@code ==} the expected value.
 231.137 +     *
 231.138 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 231.139 +     * and does not provide ordering guarantees, so is only rarely an
 231.140 +     * appropriate alternative to {@code compareAndSet}.
 231.141 +     *
 231.142 +     * @param expect the expected value
 231.143 +     * @param update the new value
 231.144 +     * @return true if successful.
 231.145 +     */
 231.146 +    public final boolean weakCompareAndSet(int expect, int update) {
 231.147 +        return compareAndSet(expect, update);
 231.148 +    }
 231.149 +
 231.150 +    /**
 231.151 +     * Atomically increments by one the current value.
 231.152 +     *
 231.153 +     * @return the previous value
 231.154 +     */
 231.155 +    public final int getAndIncrement() {
 231.156 +        for (;;) {
 231.157 +            int current = get();
 231.158 +            int next = current + 1;
 231.159 +            if (compareAndSet(current, next))
 231.160 +                return current;
 231.161 +        }
 231.162 +    }
 231.163 +
 231.164 +    /**
 231.165 +     * Atomically decrements by one the current value.
 231.166 +     *
 231.167 +     * @return the previous value
 231.168 +     */
 231.169 +    public final int getAndDecrement() {
 231.170 +        for (;;) {
 231.171 +            int current = get();
 231.172 +            int next = current - 1;
 231.173 +            if (compareAndSet(current, next))
 231.174 +                return current;
 231.175 +        }
 231.176 +    }
 231.177 +
 231.178 +    /**
 231.179 +     * Atomically adds the given value to the current value.
 231.180 +     *
 231.181 +     * @param delta the value to add
 231.182 +     * @return the previous value
 231.183 +     */
 231.184 +    public final int getAndAdd(int delta) {
 231.185 +        for (;;) {
 231.186 +            int current = get();
 231.187 +            int next = current + delta;
 231.188 +            if (compareAndSet(current, next))
 231.189 +                return current;
 231.190 +        }
 231.191 +    }
 231.192 +
 231.193 +    /**
 231.194 +     * Atomically increments by one the current value.
 231.195 +     *
 231.196 +     * @return the updated value
 231.197 +     */
 231.198 +    public final int incrementAndGet() {
 231.199 +        for (;;) {
 231.200 +            int current = get();
 231.201 +            int next = current + 1;
 231.202 +            if (compareAndSet(current, next))
 231.203 +                return next;
 231.204 +        }
 231.205 +    }
 231.206 +
 231.207 +    /**
 231.208 +     * Atomically decrements by one the current value.
 231.209 +     *
 231.210 +     * @return the updated value
 231.211 +     */
 231.212 +    public final int decrementAndGet() {
 231.213 +        for (;;) {
 231.214 +            int current = get();
 231.215 +            int next = current - 1;
 231.216 +            if (compareAndSet(current, next))
 231.217 +                return next;
 231.218 +        }
 231.219 +    }
 231.220 +
 231.221 +    /**
 231.222 +     * Atomically adds the given value to the current value.
 231.223 +     *
 231.224 +     * @param delta the value to add
 231.225 +     * @return the updated value
 231.226 +     */
 231.227 +    public final int addAndGet(int delta) {
 231.228 +        for (;;) {
 231.229 +            int current = get();
 231.230 +            int next = current + delta;
 231.231 +            if (compareAndSet(current, next))
 231.232 +                return next;
 231.233 +        }
 231.234 +    }
 231.235 +
 231.236 +    /**
 231.237 +     * Returns the String representation of the current value.
 231.238 +     * @return the String representation of the current value.
 231.239 +     */
 231.240 +    public String toString() {
 231.241 +        return Integer.toString(get());
 231.242 +    }
 231.243 +
 231.244 +
 231.245 +    public int intValue() {
 231.246 +        return get();
 231.247 +    }
 231.248 +
 231.249 +    public long longValue() {
 231.250 +        return (long)get();
 231.251 +    }
 231.252 +
 231.253 +    public float floatValue() {
 231.254 +        return (float)get();
 231.255 +    }
 231.256 +
 231.257 +    public double doubleValue() {
 231.258 +        return (double)get();
 231.259 +    }
 231.260 +
 231.261 +}
   232.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   232.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java	Wed Apr 30 15:04:10 2014 +0200
   232.3 @@ -0,0 +1,247 @@
   232.4 +/*
   232.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   232.6 + *
   232.7 + * This code is free software; you can redistribute it and/or modify it
   232.8 + * under the terms of the GNU General Public License version 2 only, as
   232.9 + * published by the Free Software Foundation.  Oracle designates this
  232.10 + * particular file as subject to the "Classpath" exception as provided
  232.11 + * by Oracle in the LICENSE file that accompanied this code.
  232.12 + *
  232.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  232.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  232.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  232.16 + * version 2 for more details (a copy is included in the LICENSE file that
  232.17 + * accompanied this code).
  232.18 + *
  232.19 + * You should have received a copy of the GNU General Public License version
  232.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  232.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  232.22 + *
  232.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  232.24 + * or visit www.oracle.com if you need additional information or have any
  232.25 + * questions.
  232.26 + */
  232.27 +
  232.28 +/*
  232.29 + * This file is available under and governed by the GNU General Public
  232.30 + * License version 2 only, as published by the Free Software Foundation.
  232.31 + * However, the following notice accompanied the original version of this
  232.32 + * file:
  232.33 + *
  232.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  232.35 + * Expert Group and released to the public domain, as explained at
  232.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  232.37 + */
  232.38 +
  232.39 +package java.util.concurrent.atomic;
  232.40 +
  232.41 +/**
  232.42 + * An {@code int} array in which elements may be updated atomically.
  232.43 + * See the {@link java.util.concurrent.atomic} package
  232.44 + * specification for description of the properties of atomic
  232.45 + * variables.
  232.46 + * @since 1.5
  232.47 + * @author Doug Lea
  232.48 + */
  232.49 +public class AtomicIntegerArray implements java.io.Serializable {
  232.50 +    private static final long serialVersionUID = 2862133569453604235L;
  232.51 +
  232.52 +    private final int[] array;
  232.53 +
  232.54 +    /**
  232.55 +     * Creates a new AtomicIntegerArray of the given length, with all
  232.56 +     * elements initially zero.
  232.57 +     *
  232.58 +     * @param length the length of the array
  232.59 +     */
  232.60 +    public AtomicIntegerArray(int length) {
  232.61 +        array = new int[length];
  232.62 +    }
  232.63 +
  232.64 +    /**
  232.65 +     * Creates a new AtomicIntegerArray with the same length as, and
  232.66 +     * all elements copied from, the given array.
  232.67 +     *
  232.68 +     * @param array the array to copy elements from
  232.69 +     * @throws NullPointerException if array is null
  232.70 +     */
  232.71 +    public AtomicIntegerArray(int[] array) {
  232.72 +        // Visibility guaranteed by final field guarantees
  232.73 +        this.array = array.clone();
  232.74 +    }
  232.75 +
  232.76 +    /**
  232.77 +     * Returns the length of the array.
  232.78 +     *
  232.79 +     * @return the length of the array
  232.80 +     */
  232.81 +    public final int length() {
  232.82 +        return array.length;
  232.83 +    }
  232.84 +
  232.85 +    /**
  232.86 +     * Gets the current value at position {@code i}.
  232.87 +     *
  232.88 +     * @param i the index
  232.89 +     * @return the current value
  232.90 +     */
  232.91 +    public final int get(int i) {
  232.92 +        return array[i];
  232.93 +    }
  232.94 +
  232.95 +    /**
  232.96 +     * Sets the element at position {@code i} to the given value.
  232.97 +     *
  232.98 +     * @param i the index
  232.99 +     * @param newValue the new value
 232.100 +     */
 232.101 +    public final void set(int i, int newValue) {
 232.102 +        array[i] = newValue;
 232.103 +    }
 232.104 +
 232.105 +    /**
 232.106 +     * Eventually sets the element at position {@code i} to the given value.
 232.107 +     *
 232.108 +     * @param i the index
 232.109 +     * @param newValue the new value
 232.110 +     * @since 1.6
 232.111 +     */
 232.112 +    public final void lazySet(int i, int newValue) {
 232.113 +        array[i] = newValue;
 232.114 +    }
 232.115 +
 232.116 +    /**
 232.117 +     * Atomically sets the element at position {@code i} to the given
 232.118 +     * value and returns the old value.
 232.119 +     *
 232.120 +     * @param i the index
 232.121 +     * @param newValue the new value
 232.122 +     * @return the previous value
 232.123 +     */
 232.124 +    public final int getAndSet(int i, int newValue) {
 232.125 +        int current = array[i];
 232.126 +        array[i] = newValue;
 232.127 +        return current;
 232.128 +    }
 232.129 +
 232.130 +    /**
 232.131 +     * Atomically sets the element at position {@code i} to the given
 232.132 +     * updated value if the current value {@code ==} the expected value.
 232.133 +     *
 232.134 +     * @param i the index
 232.135 +     * @param expect the expected value
 232.136 +     * @param update the new value
 232.137 +     * @return true if successful. False return indicates that
 232.138 +     * the actual value was not equal to the expected value.
 232.139 +     */
 232.140 +    public final boolean compareAndSet(int i, int expect, int update) {
 232.141 +        if (array[i] == expect) {
 232.142 +            array[i] = update;
 232.143 +            return true;
 232.144 +        } else {
 232.145 +            return false;
 232.146 +        }
 232.147 +    }
 232.148 +
 232.149 +    /**
 232.150 +     * Atomically sets the element at position {@code i} to the given
 232.151 +     * updated value if the current value {@code ==} the expected value.
 232.152 +     *
 232.153 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 232.154 +     * and does not provide ordering guarantees, so is only rarely an
 232.155 +     * appropriate alternative to {@code compareAndSet}.
 232.156 +     *
 232.157 +     * @param i the index
 232.158 +     * @param expect the expected value
 232.159 +     * @param update the new value
 232.160 +     * @return true if successful.
 232.161 +     */
 232.162 +    public final boolean weakCompareAndSet(int i, int expect, int update) {
 232.163 +        return compareAndSet(i, expect, update);
 232.164 +    }
 232.165 +
 232.166 +    /**
 232.167 +     * Atomically increments by one the element at index {@code i}.
 232.168 +     *
 232.169 +     * @param i the index
 232.170 +     * @return the previous value
 232.171 +     */
 232.172 +    public final int getAndIncrement(int i) {
 232.173 +        return getAndAdd(i, 1);
 232.174 +    }
 232.175 +
 232.176 +    /**
 232.177 +     * Atomically decrements by one the element at index {@code i}.
 232.178 +     *
 232.179 +     * @param i the index
 232.180 +     * @return the previous value
 232.181 +     */
 232.182 +    public final int getAndDecrement(int i) {
 232.183 +        return getAndAdd(i, -1);
 232.184 +    }
 232.185 +
 232.186 +    /**
 232.187 +     * Atomically adds the given value to the element at index {@code i}.
 232.188 +     *
 232.189 +     * @param i the index
 232.190 +     * @param delta the value to add
 232.191 +     * @return the previous value
 232.192 +     */
 232.193 +    public final int getAndAdd(int i, int delta) {
 232.194 +        int v = array[i];
 232.195 +        array[i] += delta;
 232.196 +        return v;
 232.197 +    }
 232.198 +
 232.199 +    /**
 232.200 +     * Atomically increments by one the element at index {@code i}.
 232.201 +     *
 232.202 +     * @param i the index
 232.203 +     * @return the updated value
 232.204 +     */
 232.205 +    public final int incrementAndGet(int i) {
 232.206 +        return addAndGet(i, 1);
 232.207 +    }
 232.208 +
 232.209 +    /**
 232.210 +     * Atomically decrements by one the element at index {@code i}.
 232.211 +     *
 232.212 +     * @param i the index
 232.213 +     * @return the updated value
 232.214 +     */
 232.215 +    public final int decrementAndGet(int i) {
 232.216 +        return addAndGet(i, -1);
 232.217 +    }
 232.218 +
 232.219 +    /**
 232.220 +     * Atomically adds the given value to the element at index {@code i}.
 232.221 +     *
 232.222 +     * @param i the index
 232.223 +     * @param delta the value to add
 232.224 +     * @return the updated value
 232.225 +     */
 232.226 +    public final int addAndGet(int i, int delta) {
 232.227 +        array[i] += delta;
 232.228 +        return array[i];
 232.229 +    }
 232.230 +
 232.231 +    /**
 232.232 +     * Returns the String representation of the current values of array.
 232.233 +     * @return the String representation of the current values of array
 232.234 +     */
 232.235 +    public String toString() {
 232.236 +        int iMax = array.length - 1;
 232.237 +        if (iMax == -1)
 232.238 +            return "[]";
 232.239 +
 232.240 +        StringBuilder b = new StringBuilder();
 232.241 +        b.append('[');
 232.242 +        for (int i = 0; ; i++) {
 232.243 +            b.append(get(i));
 232.244 +            if (i == iMax)
 232.245 +                return b.append(']').toString();
 232.246 +            b.append(',').append(' ');
 232.247 +        }
 232.248 +    }
 232.249 +
 232.250 +}
   233.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   233.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicLong.java	Wed Apr 30 15:04:10 2014 +0200
   233.3 @@ -0,0 +1,265 @@
   233.4 +/*
   233.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   233.6 + *
   233.7 + * This code is free software; you can redistribute it and/or modify it
   233.8 + * under the terms of the GNU General Public License version 2 only, as
   233.9 + * published by the Free Software Foundation.  Oracle designates this
  233.10 + * particular file as subject to the "Classpath" exception as provided
  233.11 + * by Oracle in the LICENSE file that accompanied this code.
  233.12 + *
  233.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  233.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  233.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  233.16 + * version 2 for more details (a copy is included in the LICENSE file that
  233.17 + * accompanied this code).
  233.18 + *
  233.19 + * You should have received a copy of the GNU General Public License version
  233.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  233.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  233.22 + *
  233.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  233.24 + * or visit www.oracle.com if you need additional information or have any
  233.25 + * questions.
  233.26 + */
  233.27 +
  233.28 +/*
  233.29 + * This file is available under and governed by the GNU General Public
  233.30 + * License version 2 only, as published by the Free Software Foundation.
  233.31 + * However, the following notice accompanied the original version of this
  233.32 + * file:
  233.33 + *
  233.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  233.35 + * Expert Group and released to the public domain, as explained at
  233.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  233.37 + */
  233.38 +
  233.39 +package java.util.concurrent.atomic;
  233.40 +
  233.41 +/**
  233.42 + * A {@code long} value that may be updated atomically.  See the
  233.43 + * {@link java.util.concurrent.atomic} package specification for
  233.44 + * description of the properties of atomic variables. An
  233.45 + * {@code AtomicLong} is used in applications such as atomically
  233.46 + * incremented sequence numbers, and cannot be used as a replacement
  233.47 + * for a {@link java.lang.Long}. However, this class does extend
  233.48 + * {@code Number} to allow uniform access by tools and utilities that
  233.49 + * deal with numerically-based classes.
  233.50 + *
  233.51 + * @since 1.5
  233.52 + * @author Doug Lea
  233.53 + */
  233.54 +public class AtomicLong extends Number implements java.io.Serializable {
  233.55 +    private static final long serialVersionUID = 1927816293512124184L;
  233.56 +
  233.57 +
  233.58 +    /**
  233.59 +     * Returns whether underlying JVM supports lockless CompareAndSet
  233.60 +     * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
  233.61 +     */
  233.62 +    private static native boolean VMSupportsCS8();
  233.63 +
  233.64 +    private volatile long value;
  233.65 +
  233.66 +    /**
  233.67 +     * Creates a new AtomicLong with the given initial value.
  233.68 +     *
  233.69 +     * @param initialValue the initial value
  233.70 +     */
  233.71 +    public AtomicLong(long initialValue) {
  233.72 +        value = initialValue;
  233.73 +    }
  233.74 +
  233.75 +    /**
  233.76 +     * Creates a new AtomicLong with initial value {@code 0}.
  233.77 +     */
  233.78 +    public AtomicLong() {
  233.79 +    }
  233.80 +
  233.81 +    /**
  233.82 +     * Gets the current value.
  233.83 +     *
  233.84 +     * @return the current value
  233.85 +     */
  233.86 +    public final long get() {
  233.87 +        return value;
  233.88 +    }
  233.89 +
  233.90 +    /**
  233.91 +     * Sets to the given value.
  233.92 +     *
  233.93 +     * @param newValue the new value
  233.94 +     */
  233.95 +    public final void set(long newValue) {
  233.96 +        value = newValue;
  233.97 +    }
  233.98 +
  233.99 +    /**
 233.100 +     * Eventually sets to the given value.
 233.101 +     *
 233.102 +     * @param newValue the new value
 233.103 +     * @since 1.6
 233.104 +     */
 233.105 +    public final void lazySet(long newValue) {
 233.106 +        value = newValue;
 233.107 +    }
 233.108 +
 233.109 +    /**
 233.110 +     * Atomically sets to the given value and returns the old value.
 233.111 +     *
 233.112 +     * @param newValue the new value
 233.113 +     * @return the previous value
 233.114 +     */
 233.115 +    public final long getAndSet(long newValue) {
 233.116 +        while (true) {
 233.117 +            long current = get();
 233.118 +            if (compareAndSet(current, newValue))
 233.119 +                return current;
 233.120 +        }
 233.121 +    }
 233.122 +
 233.123 +    /**
 233.124 +     * Atomically sets the value to the given updated value
 233.125 +     * if the current value {@code ==} the expected value.
 233.126 +     *
 233.127 +     * @param expect the expected value
 233.128 +     * @param update the new value
 233.129 +     * @return true if successful. False return indicates that
 233.130 +     * the actual value was not equal to the expected value.
 233.131 +     */
 233.132 +    public final boolean compareAndSet(long expect, long update) {
 233.133 +        if (value == expect) {
 233.134 +            value = update;
 233.135 +            return true;
 233.136 +        } else {
 233.137 +            return false;
 233.138 +        }
 233.139 +    }
 233.140 +
 233.141 +    /**
 233.142 +     * Atomically sets the value to the given updated value
 233.143 +     * if the current value {@code ==} the expected value.
 233.144 +     *
 233.145 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 233.146 +     * and does not provide ordering guarantees, so is only rarely an
 233.147 +     * appropriate alternative to {@code compareAndSet}.
 233.148 +     *
 233.149 +     * @param expect the expected value
 233.150 +     * @param update the new value
 233.151 +     * @return true if successful.
 233.152 +     */
 233.153 +    public final boolean weakCompareAndSet(long expect, long update) {
 233.154 +        return compareAndSet(expect, update);
 233.155 +    }
 233.156 +
 233.157 +    /**
 233.158 +     * Atomically increments by one the current value.
 233.159 +     *
 233.160 +     * @return the previous value
 233.161 +     */
 233.162 +    public final long getAndIncrement() {
 233.163 +        while (true) {
 233.164 +            long current = get();
 233.165 +            long next = current + 1;
 233.166 +            if (compareAndSet(current, next))
 233.167 +                return current;
 233.168 +        }
 233.169 +    }
 233.170 +
 233.171 +    /**
 233.172 +     * Atomically decrements by one the current value.
 233.173 +     *
 233.174 +     * @return the previous value
 233.175 +     */
 233.176 +    public final long getAndDecrement() {
 233.177 +        while (true) {
 233.178 +            long current = get();
 233.179 +            long next = current - 1;
 233.180 +            if (compareAndSet(current, next))
 233.181 +                return current;
 233.182 +        }
 233.183 +    }
 233.184 +
 233.185 +    /**
 233.186 +     * Atomically adds the given value to the current value.
 233.187 +     *
 233.188 +     * @param delta the value to add
 233.189 +     * @return the previous value
 233.190 +     */
 233.191 +    public final long getAndAdd(long delta) {
 233.192 +        while (true) {
 233.193 +            long current = get();
 233.194 +            long next = current + delta;
 233.195 +            if (compareAndSet(current, next))
 233.196 +                return current;
 233.197 +        }
 233.198 +    }
 233.199 +
 233.200 +    /**
 233.201 +     * Atomically increments by one the current value.
 233.202 +     *
 233.203 +     * @return the updated value
 233.204 +     */
 233.205 +    public final long incrementAndGet() {
 233.206 +        for (;;) {
 233.207 +            long current = get();
 233.208 +            long next = current + 1;
 233.209 +            if (compareAndSet(current, next))
 233.210 +                return next;
 233.211 +        }
 233.212 +    }
 233.213 +
 233.214 +    /**
 233.215 +     * Atomically decrements by one the current value.
 233.216 +     *
 233.217 +     * @return the updated value
 233.218 +     */
 233.219 +    public final long decrementAndGet() {
 233.220 +        for (;;) {
 233.221 +            long current = get();
 233.222 +            long next = current - 1;
 233.223 +            if (compareAndSet(current, next))
 233.224 +                return next;
 233.225 +        }
 233.226 +    }
 233.227 +
 233.228 +    /**
 233.229 +     * Atomically adds the given value to the current value.
 233.230 +     *
 233.231 +     * @param delta the value to add
 233.232 +     * @return the updated value
 233.233 +     */
 233.234 +    public final long addAndGet(long delta) {
 233.235 +        for (;;) {
 233.236 +            long current = get();
 233.237 +            long next = current + delta;
 233.238 +            if (compareAndSet(current, next))
 233.239 +                return next;
 233.240 +        }
 233.241 +    }
 233.242 +
 233.243 +    /**
 233.244 +     * Returns the String representation of the current value.
 233.245 +     * @return the String representation of the current value.
 233.246 +     */
 233.247 +    public String toString() {
 233.248 +        return Long.toString(get());
 233.249 +    }
 233.250 +
 233.251 +
 233.252 +    public int intValue() {
 233.253 +        return (int)get();
 233.254 +    }
 233.255 +
 233.256 +    public long longValue() {
 233.257 +        return get();
 233.258 +    }
 233.259 +
 233.260 +    public float floatValue() {
 233.261 +        return (float)get();
 233.262 +    }
 233.263 +
 233.264 +    public double doubleValue() {
 233.265 +        return (double)get();
 233.266 +    }
 233.267 +
 233.268 +}
   234.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   234.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java	Wed Apr 30 15:04:10 2014 +0200
   234.3 @@ -0,0 +1,247 @@
   234.4 +/*
   234.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   234.6 + *
   234.7 + * This code is free software; you can redistribute it and/or modify it
   234.8 + * under the terms of the GNU General Public License version 2 only, as
   234.9 + * published by the Free Software Foundation.  Oracle designates this
  234.10 + * particular file as subject to the "Classpath" exception as provided
  234.11 + * by Oracle in the LICENSE file that accompanied this code.
  234.12 + *
  234.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  234.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  234.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  234.16 + * version 2 for more details (a copy is included in the LICENSE file that
  234.17 + * accompanied this code).
  234.18 + *
  234.19 + * You should have received a copy of the GNU General Public License version
  234.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  234.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  234.22 + *
  234.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  234.24 + * or visit www.oracle.com if you need additional information or have any
  234.25 + * questions.
  234.26 + */
  234.27 +
  234.28 +/*
  234.29 + * This file is available under and governed by the GNU General Public
  234.30 + * License version 2 only, as published by the Free Software Foundation.
  234.31 + * However, the following notice accompanied the original version of this
  234.32 + * file:
  234.33 + *
  234.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  234.35 + * Expert Group and released to the public domain, as explained at
  234.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  234.37 + */
  234.38 +
  234.39 +package java.util.concurrent.atomic;
  234.40 +
  234.41 +/**
  234.42 + * A {@code long} array in which elements may be updated atomically.
  234.43 + * See the {@link java.util.concurrent.atomic} package specification
  234.44 + * for description of the properties of atomic variables.
  234.45 + * @since 1.5
  234.46 + * @author Doug Lea
  234.47 + */
  234.48 +public class AtomicLongArray implements java.io.Serializable {
  234.49 +    private static final long serialVersionUID = -2308431214976778248L;
  234.50 +
  234.51 +    private final long[] array;
  234.52 +
  234.53 +    /**
  234.54 +     * Creates a new AtomicLongArray of the given length, with all
  234.55 +     * elements initially zero.
  234.56 +     *
  234.57 +     * @param length the length of the array
  234.58 +     */
  234.59 +    public AtomicLongArray(int length) {
  234.60 +        array = new long[length];
  234.61 +    }
  234.62 +
  234.63 +    /**
  234.64 +     * Creates a new AtomicLongArray with the same length as, and
  234.65 +     * all elements copied from, the given array.
  234.66 +     *
  234.67 +     * @param array the array to copy elements from
  234.68 +     * @throws NullPointerException if array is null
  234.69 +     */
  234.70 +    public AtomicLongArray(long[] array) {
  234.71 +        // Visibility guaranteed by final field guarantees
  234.72 +        this.array = array.clone();
  234.73 +    }
  234.74 +
  234.75 +    /**
  234.76 +     * Returns the length of the array.
  234.77 +     *
  234.78 +     * @return the length of the array
  234.79 +     */
  234.80 +    public final int length() {
  234.81 +        return array.length;
  234.82 +    }
  234.83 +
  234.84 +    /**
  234.85 +     * Gets the current value at position {@code i}.
  234.86 +     *
  234.87 +     * @param i the index
  234.88 +     * @return the current value
  234.89 +     */
  234.90 +    public final long get(int i) {
  234.91 +        return array[i];
  234.92 +    }
  234.93 +
  234.94 +    /**
  234.95 +     * Sets the element at position {@code i} to the given value.
  234.96 +     *
  234.97 +     * @param i the index
  234.98 +     * @param newValue the new value
  234.99 +     */
 234.100 +    public final void set(int i, long newValue) {
 234.101 +        array[i] = newValue;
 234.102 +    }
 234.103 +
 234.104 +    /**
 234.105 +     * Eventually sets the element at position {@code i} to the given value.
 234.106 +     *
 234.107 +     * @param i the index
 234.108 +     * @param newValue the new value
 234.109 +     * @since 1.6
 234.110 +     */
 234.111 +    public final void lazySet(int i, long newValue) {
 234.112 +        array[i] = newValue;
 234.113 +    }
 234.114 +
 234.115 +
 234.116 +    /**
 234.117 +     * Atomically sets the element at position {@code i} to the given value
 234.118 +     * and returns the old value.
 234.119 +     *
 234.120 +     * @param i the index
 234.121 +     * @param newValue the new value
 234.122 +     * @return the previous value
 234.123 +     */
 234.124 +    public final long getAndSet(int i, long newValue) {
 234.125 +        long v = array[i];
 234.126 +        array[i] = newValue;
 234.127 +        return v;
 234.128 +    }
 234.129 +
 234.130 +    /**
 234.131 +     * Atomically sets the element at position {@code i} to the given
 234.132 +     * updated value if the current value {@code ==} the expected value.
 234.133 +     *
 234.134 +     * @param i the index
 234.135 +     * @param expect the expected value
 234.136 +     * @param update the new value
 234.137 +     * @return true if successful. False return indicates that
 234.138 +     * the actual value was not equal to the expected value.
 234.139 +     */
 234.140 +    public final boolean compareAndSet(int i, long expect, long update) {
 234.141 +        if (array[i] == expect) {
 234.142 +            array[i] = update;
 234.143 +            return true;
 234.144 +        } else {
 234.145 +            return false;
 234.146 +        }
 234.147 +    }
 234.148 +
 234.149 +    /**
 234.150 +     * Atomically sets the element at position {@code i} to the given
 234.151 +     * updated value if the current value {@code ==} the expected value.
 234.152 +     *
 234.153 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 234.154 +     * and does not provide ordering guarantees, so is only rarely an
 234.155 +     * appropriate alternative to {@code compareAndSet}.
 234.156 +     *
 234.157 +     * @param i the index
 234.158 +     * @param expect the expected value
 234.159 +     * @param update the new value
 234.160 +     * @return true if successful.
 234.161 +     */
 234.162 +    public final boolean weakCompareAndSet(int i, long expect, long update) {
 234.163 +        return compareAndSet(i, expect, update);
 234.164 +    }
 234.165 +
 234.166 +    /**
 234.167 +     * Atomically increments by one the element at index {@code i}.
 234.168 +     *
 234.169 +     * @param i the index
 234.170 +     * @return the previous value
 234.171 +     */
 234.172 +    public final long getAndIncrement(int i) {
 234.173 +        return getAndAdd(i, 1);
 234.174 +    }
 234.175 +
 234.176 +    /**
 234.177 +     * Atomically decrements by one the element at index {@code i}.
 234.178 +     *
 234.179 +     * @param i the index
 234.180 +     * @return the previous value
 234.181 +     */
 234.182 +    public final long getAndDecrement(int i) {
 234.183 +        return getAndAdd(i, -1);
 234.184 +    }
 234.185 +
 234.186 +    /**
 234.187 +     * Atomically adds the given value to the element at index {@code i}.
 234.188 +     *
 234.189 +     * @param i the index
 234.190 +     * @param delta the value to add
 234.191 +     * @return the previous value
 234.192 +     */
 234.193 +    public final long getAndAdd(int i, long delta) {
 234.194 +        long v = array[i];
 234.195 +        array[i] += delta;
 234.196 +        return v;
 234.197 +    }
 234.198 +
 234.199 +    /**
 234.200 +     * Atomically increments by one the element at index {@code i}.
 234.201 +     *
 234.202 +     * @param i the index
 234.203 +     * @return the updated value
 234.204 +     */
 234.205 +    public final long incrementAndGet(int i) {
 234.206 +        return addAndGet(i, 1);
 234.207 +    }
 234.208 +
 234.209 +    /**
 234.210 +     * Atomically decrements by one the element at index {@code i}.
 234.211 +     *
 234.212 +     * @param i the index
 234.213 +     * @return the updated value
 234.214 +     */
 234.215 +    public final long decrementAndGet(int i) {
 234.216 +        return addAndGet(i, -1);
 234.217 +    }
 234.218 +
 234.219 +    /**
 234.220 +     * Atomically adds the given value to the element at index {@code i}.
 234.221 +     *
 234.222 +     * @param i the index
 234.223 +     * @param delta the value to add
 234.224 +     * @return the updated value
 234.225 +     */
 234.226 +    public long addAndGet(int i, long delta) {
 234.227 +        array[i] += delta;
 234.228 +        return array[i];
 234.229 +    }
 234.230 +
 234.231 +    /**
 234.232 +     * Returns the String representation of the current values of array.
 234.233 +     * @return the String representation of the current values of array
 234.234 +     */
 234.235 +    public String toString() {
 234.236 +        int iMax = array.length - 1;
 234.237 +        if (iMax == -1)
 234.238 +            return "[]";
 234.239 +
 234.240 +        StringBuilder b = new StringBuilder();
 234.241 +        b.append('[');
 234.242 +        for (int i = 0; ; i++) {
 234.243 +            b.append(get(i));
 234.244 +            if (i == iMax)
 234.245 +                return b.append(']').toString();
 234.246 +            b.append(',').append(' ');
 234.247 +        }
 234.248 +    }
 234.249 +
 234.250 +}
   235.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   235.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicReference.java	Wed Apr 30 15:04:10 2014 +0200
   235.3 @@ -0,0 +1,149 @@
   235.4 +/*
   235.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   235.6 + *
   235.7 + * This code is free software; you can redistribute it and/or modify it
   235.8 + * under the terms of the GNU General Public License version 2 only, as
   235.9 + * published by the Free Software Foundation.  Oracle designates this
  235.10 + * particular file as subject to the "Classpath" exception as provided
  235.11 + * by Oracle in the LICENSE file that accompanied this code.
  235.12 + *
  235.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  235.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  235.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  235.16 + * version 2 for more details (a copy is included in the LICENSE file that
  235.17 + * accompanied this code).
  235.18 + *
  235.19 + * You should have received a copy of the GNU General Public License version
  235.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  235.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  235.22 + *
  235.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  235.24 + * or visit www.oracle.com if you need additional information or have any
  235.25 + * questions.
  235.26 + */
  235.27 +
  235.28 +/*
  235.29 + * This file is available under and governed by the GNU General Public
  235.30 + * License version 2 only, as published by the Free Software Foundation.
  235.31 + * However, the following notice accompanied the original version of this
  235.32 + * file:
  235.33 + *
  235.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  235.35 + * Expert Group and released to the public domain, as explained at
  235.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  235.37 + */
  235.38 +
  235.39 +package java.util.concurrent.atomic;
  235.40 +
  235.41 +/**
  235.42 + * An object reference that may be updated atomically. See the {@link
  235.43 + * java.util.concurrent.atomic} package specification for description
  235.44 + * of the properties of atomic variables.
  235.45 + * @since 1.5
  235.46 + * @author Doug Lea
  235.47 + * @param <V> The type of object referred to by this reference
  235.48 + */
  235.49 +public class AtomicReference<V>  implements java.io.Serializable {
  235.50 +    private static final long serialVersionUID = -1848883965231344442L;
  235.51 +
  235.52 +    private volatile V value;
  235.53 +
  235.54 +    /**
  235.55 +     * Creates a new AtomicReference with the given initial value.
  235.56 +     *
  235.57 +     * @param initialValue the initial value
  235.58 +     */
  235.59 +    public AtomicReference(V initialValue) {
  235.60 +        value = initialValue;
  235.61 +    }
  235.62 +
  235.63 +    /**
  235.64 +     * Creates a new AtomicReference with null initial value.
  235.65 +     */
  235.66 +    public AtomicReference() {
  235.67 +    }
  235.68 +
  235.69 +    /**
  235.70 +     * Gets the current value.
  235.71 +     *
  235.72 +     * @return the current value
  235.73 +     */
  235.74 +    public final V get() {
  235.75 +        return value;
  235.76 +    }
  235.77 +
  235.78 +    /**
  235.79 +     * Sets to the given value.
  235.80 +     *
  235.81 +     * @param newValue the new value
  235.82 +     */
  235.83 +    public final void set(V newValue) {
  235.84 +        value = newValue;
  235.85 +    }
  235.86 +
  235.87 +    /**
  235.88 +     * Eventually sets to the given value.
  235.89 +     *
  235.90 +     * @param newValue the new value
  235.91 +     * @since 1.6
  235.92 +     */
  235.93 +    public final void lazySet(V newValue) {
  235.94 +        value = newValue;
  235.95 +    }
  235.96 +
  235.97 +    /**
  235.98 +     * Atomically sets the value to the given updated value
  235.99 +     * if the current value {@code ==} the expected value.
 235.100 +     * @param expect the expected value
 235.101 +     * @param update the new value
 235.102 +     * @return true if successful. False return indicates that
 235.103 +     * the actual value was not equal to the expected value.
 235.104 +     */
 235.105 +    public final boolean compareAndSet(V expect, V update) {
 235.106 +        if (value == expect) {
 235.107 +            value = update;
 235.108 +            return true;
 235.109 +        } else {
 235.110 +            return false;
 235.111 +        }
 235.112 +    }
 235.113 +
 235.114 +    /**
 235.115 +     * Atomically sets the value to the given updated value
 235.116 +     * if the current value {@code ==} the expected value.
 235.117 +     *
 235.118 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 235.119 +     * and does not provide ordering guarantees, so is only rarely an
 235.120 +     * appropriate alternative to {@code compareAndSet}.
 235.121 +     *
 235.122 +     * @param expect the expected value
 235.123 +     * @param update the new value
 235.124 +     * @return true if successful.
 235.125 +     */
 235.126 +    public final boolean weakCompareAndSet(V expect, V update) {
 235.127 +        return compareAndSet(expect, update);
 235.128 +    }
 235.129 +
 235.130 +    /**
 235.131 +     * Atomically sets to the given value and returns the old value.
 235.132 +     *
 235.133 +     * @param newValue the new value
 235.134 +     * @return the previous value
 235.135 +     */
 235.136 +    public final V getAndSet(V newValue) {
 235.137 +        while (true) {
 235.138 +            V x = get();
 235.139 +            if (compareAndSet(x, newValue))
 235.140 +                return x;
 235.141 +        }
 235.142 +    }
 235.143 +
 235.144 +    /**
 235.145 +     * Returns the String representation of the current value.
 235.146 +     * @return the String representation of the current value.
 235.147 +     */
 235.148 +    public String toString() {
 235.149 +        return String.valueOf(get());
 235.150 +    }
 235.151 +
 235.152 +}
   236.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   236.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Apr 30 15:04:10 2014 +0200
   236.3 @@ -0,0 +1,184 @@
   236.4 +/*
   236.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   236.6 + *
   236.7 + * This code is free software; you can redistribute it and/or modify it
   236.8 + * under the terms of the GNU General Public License version 2 only, as
   236.9 + * published by the Free Software Foundation.  Oracle designates this
  236.10 + * particular file as subject to the "Classpath" exception as provided
  236.11 + * by Oracle in the LICENSE file that accompanied this code.
  236.12 + *
  236.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  236.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  236.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  236.16 + * version 2 for more details (a copy is included in the LICENSE file that
  236.17 + * accompanied this code).
  236.18 + *
  236.19 + * You should have received a copy of the GNU General Public License version
  236.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  236.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  236.22 + *
  236.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  236.24 + * or visit www.oracle.com if you need additional information or have any
  236.25 + * questions.
  236.26 + */
  236.27 +
  236.28 +/*
  236.29 + * This file is available under and governed by the GNU General Public
  236.30 + * License version 2 only, as published by the Free Software Foundation.
  236.31 + * However, the following notice accompanied the original version of this
  236.32 + * file:
  236.33 + *
  236.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  236.35 + * Expert Group and released to the public domain, as explained at
  236.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  236.37 + */
  236.38 +
  236.39 +package java.util.concurrent.atomic;
  236.40 +
  236.41 +/**
  236.42 + * An array of object references in which elements may be updated
  236.43 + * atomically.  See the {@link java.util.concurrent.atomic} package
  236.44 + * specification for description of the properties of atomic
  236.45 + * variables.
  236.46 + * @since 1.5
  236.47 + * @author Doug Lea
  236.48 + * @param <E> The base class of elements held in this array
  236.49 + */
  236.50 +public class AtomicReferenceArray<E> implements java.io.Serializable {
  236.51 +    private static final long serialVersionUID = -6209656149925076980L;
  236.52 +
  236.53 +    private final Object[] array;
  236.54 +
  236.55 +    /**
  236.56 +     * Creates a new AtomicReferenceArray of the given length, with all
  236.57 +     * elements initially null.
  236.58 +     *
  236.59 +     * @param length the length of the array
  236.60 +     */
  236.61 +    public AtomicReferenceArray(int length) {
  236.62 +        array = new Object[length];
  236.63 +    }
  236.64 +
  236.65 +    /**
  236.66 +     * Creates a new AtomicReferenceArray with the same length as, and
  236.67 +     * all elements copied from, the given array.
  236.68 +     *
  236.69 +     * @param array the array to copy elements from
  236.70 +     * @throws NullPointerException if array is null
  236.71 +     */
  236.72 +    public AtomicReferenceArray(E[] array) {
  236.73 +        // Visibility guaranteed by final field guarantees
  236.74 +        this.array = array.clone();
  236.75 +    }
  236.76 +
  236.77 +    /**
  236.78 +     * Returns the length of the array.
  236.79 +     *
  236.80 +     * @return the length of the array
  236.81 +     */
  236.82 +    public final int length() {
  236.83 +        return array.length;
  236.84 +    }
  236.85 +
  236.86 +    /**
  236.87 +     * Gets the current value at position {@code i}.
  236.88 +     *
  236.89 +     * @param i the index
  236.90 +     * @return the current value
  236.91 +     */
  236.92 +    public final E get(int i) {
  236.93 +        return (E)array[i];
  236.94 +    }
  236.95 +
  236.96 +    /**
  236.97 +     * Sets the element at position {@code i} to the given value.
  236.98 +     *
  236.99 +     * @param i the index
 236.100 +     * @param newValue the new value
 236.101 +     */
 236.102 +    public final void set(int i, E newValue) {
 236.103 +        array[i] = newValue;
 236.104 +    }
 236.105 +
 236.106 +    /**
 236.107 +     * Eventually sets the element at position {@code i} to the given value.
 236.108 +     *
 236.109 +     * @param i the index
 236.110 +     * @param newValue the new value
 236.111 +     * @since 1.6
 236.112 +     */
 236.113 +    public final void lazySet(int i, E newValue) {
 236.114 +        array[i] = newValue;
 236.115 +    }
 236.116 +
 236.117 +
 236.118 +    /**
 236.119 +     * Atomically sets the element at position {@code i} to the given
 236.120 +     * value and returns the old value.
 236.121 +     *
 236.122 +     * @param i the index
 236.123 +     * @param newValue the new value
 236.124 +     * @return the previous value
 236.125 +     */
 236.126 +    public final E getAndSet(int i, E newValue) {
 236.127 +        E v = (E)array[i];
 236.128 +        array[i] = newValue;
 236.129 +        return v;
 236.130 +    }
 236.131 +
 236.132 +    /**
 236.133 +     * Atomically sets the element at position {@code i} to the given
 236.134 +     * updated value if the current value {@code ==} the expected value.
 236.135 +     *
 236.136 +     * @param i the index
 236.137 +     * @param expect the expected value
 236.138 +     * @param update the new value
 236.139 +     * @return true if successful. False return indicates that
 236.140 +     * the actual value was not equal to the expected value.
 236.141 +     */
 236.142 +    public final boolean compareAndSet(int i, E expect, E update) {
 236.143 +        if (array[i] == expect) {
 236.144 +            array[i] = update;
 236.145 +            return true;
 236.146 +        } else {
 236.147 +            return false;
 236.148 +        }
 236.149 +    }
 236.150 +
 236.151 +    /**
 236.152 +     * Atomically sets the element at position {@code i} to the given
 236.153 +     * updated value if the current value {@code ==} the expected value.
 236.154 +     *
 236.155 +     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
 236.156 +     * and does not provide ordering guarantees, so is only rarely an
 236.157 +     * appropriate alternative to {@code compareAndSet}.
 236.158 +     *
 236.159 +     * @param i the index
 236.160 +     * @param expect the expected value
 236.161 +     * @param update the new value
 236.162 +     * @return true if successful.
 236.163 +     */
 236.164 +    public final boolean weakCompareAndSet(int i, E expect, E update) {
 236.165 +        return compareAndSet(i, expect, update);
 236.166 +    }
 236.167 +
 236.168 +    /**
 236.169 +     * Returns the String representation of the current values of array.
 236.170 +     * @return the String representation of the current values of array
 236.171 +     */
 236.172 +    public String toString() {
 236.173 +           int iMax = array.length - 1;
 236.174 +        if (iMax == -1)
 236.175 +            return "[]";
 236.176 +
 236.177 +        StringBuilder b = new StringBuilder();
 236.178 +        b.append('[');
 236.179 +        for (int i = 0; ; i++) {
 236.180 +            b.append(get(i));
 236.181 +            if (i == iMax)
 236.182 +                return b.append(']').toString();
 236.183 +            b.append(',').append(' ');
 236.184 +        }
 236.185 +    }
 236.186 +
 236.187 +}
   237.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   237.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/atomic/package-info.java	Wed Apr 30 15:04:10 2014 +0200
   237.3 @@ -0,0 +1,199 @@
   237.4 +/*
   237.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   237.6 + *
   237.7 + * This code is free software; you can redistribute it and/or modify it
   237.8 + * under the terms of the GNU General Public License version 2 only, as
   237.9 + * published by the Free Software Foundation.  Oracle designates this
  237.10 + * particular file as subject to the "Classpath" exception as provided
  237.11 + * by Oracle in the LICENSE file that accompanied this code.
  237.12 + *
  237.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  237.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  237.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  237.16 + * version 2 for more details (a copy is included in the LICENSE file that
  237.17 + * accompanied this code).
  237.18 + *
  237.19 + * You should have received a copy of the GNU General Public License version
  237.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  237.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  237.22 + *
  237.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  237.24 + * or visit www.oracle.com if you need additional information or have any
  237.25 + * questions.
  237.26 + */
  237.27 +
  237.28 +/*
  237.29 + * This file is available under and governed by the GNU General Public
  237.30 + * License version 2 only, as published by the Free Software Foundation.
  237.31 + * However, the following notice accompanied the original version of this
  237.32 + * file:
  237.33 + *
  237.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  237.35 + * Expert Group and released to the public domain, as explained at
  237.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  237.37 + */
  237.38 +
  237.39 +/**
  237.40 + * A small toolkit of classes that support lock-free thread-safe
  237.41 + * programming on single variables.  In essence, the classes in this
  237.42 + * package extend the notion of {@code volatile} values, fields, and
  237.43 + * array elements to those that also provide an atomic conditional update
  237.44 + * operation of the form:
  237.45 + *
  237.46 + * <pre>
  237.47 + *   boolean compareAndSet(expectedValue, updateValue);
  237.48 + * </pre>
  237.49 + *
  237.50 + * <p>This method (which varies in argument types across different
  237.51 + * classes) atomically sets a variable to the {@code updateValue} if it
  237.52 + * currently holds the {@code expectedValue}, reporting {@code true} on
  237.53 + * success.  The classes in this package also contain methods to get and
  237.54 + * unconditionally set values, as well as a weaker conditional atomic
  237.55 + * update operation {@code weakCompareAndSet} described below.
  237.56 + *
  237.57 + * <p>The specifications of these methods enable implementations to
  237.58 + * employ efficient machine-level atomic instructions that are available
  237.59 + * on contemporary processors.  However on some platforms, support may
  237.60 + * entail some form of internal locking.  Thus the methods are not
  237.61 + * strictly guaranteed to be non-blocking --
  237.62 + * a thread may block transiently before performing the operation.
  237.63 + *
  237.64 + * <p>Instances of classes
  237.65 + * {@link java.util.concurrent.atomic.AtomicBoolean},
  237.66 + * {@link java.util.concurrent.atomic.AtomicInteger},
  237.67 + * {@link java.util.concurrent.atomic.AtomicLong}, and
  237.68 + * {@link java.util.concurrent.atomic.AtomicReference}
  237.69 + * each provide access and updates to a single variable of the
  237.70 + * corresponding type.  Each class also provides appropriate utility
  237.71 + * methods for that type.  For example, classes {@code AtomicLong} and
  237.72 + * {@code AtomicInteger} provide atomic increment methods.  One
  237.73 + * application is to generate sequence numbers, as in:
  237.74 + *
  237.75 + * <pre>
  237.76 + * class Sequencer {
  237.77 + *   private final AtomicLong sequenceNumber
  237.78 + *     = new AtomicLong(0);
  237.79 + *   public long next() {
  237.80 + *     return sequenceNumber.getAndIncrement();
  237.81 + *   }
  237.82 + * }
  237.83 + * </pre>
  237.84 + *
  237.85 + * <p>The memory effects for accesses and updates of atomics generally
  237.86 + * follow the rules for volatiles, as stated in section 17.4 of
  237.87 + * <cite>The Java&trade; Language Specification</cite>.
  237.88 + *
  237.89 + * <ul>
  237.90 + *
  237.91 + *   <li> {@code get} has the memory effects of reading a
  237.92 + * {@code volatile} variable.
  237.93 + *
  237.94 + *   <li> {@code set} has the memory effects of writing (assigning) a
  237.95 + * {@code volatile} variable.
  237.96 + *
  237.97 + *   <li> {@code lazySet} has the memory effects of writing (assigning)
  237.98 + *   a {@code volatile} variable except that it permits reorderings with
  237.99 + *   subsequent (but not previous) memory actions that do not themselves
 237.100 + *   impose reordering constraints with ordinary non-{@code volatile}
 237.101 + *   writes.  Among other usage contexts, {@code lazySet} may apply when
 237.102 + *   nulling out, for the sake of garbage collection, a reference that is
 237.103 + *   never accessed again.
 237.104 + *
 237.105 + *   <li>{@code weakCompareAndSet} atomically reads and conditionally
 237.106 + *   writes a variable but does <em>not</em>
 237.107 + *   create any happens-before orderings, so provides no guarantees
 237.108 + *   with respect to previous or subsequent reads and writes of any
 237.109 + *   variables other than the target of the {@code weakCompareAndSet}.
 237.110 + *
 237.111 + *   <li> {@code compareAndSet}
 237.112 + *   and all other read-and-update operations such as {@code getAndIncrement}
 237.113 + *   have the memory effects of both reading and
 237.114 + *   writing {@code volatile} variables.
 237.115 + * </ul>
 237.116 + *
 237.117 + * <p>In addition to classes representing single values, this package
 237.118 + * contains <em>Updater</em> classes that can be used to obtain
 237.119 + * {@code compareAndSet} operations on any selected {@code volatile}
 237.120 + * field of any selected class.
 237.121 + *
 237.122 + * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
 237.123 + * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
 237.124 + * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
 237.125 + * reflection-based utilities that provide access to the associated
 237.126 + * field types.  These are mainly of use in atomic data structures in
 237.127 + * which several {@code volatile} fields of the same node (for
 237.128 + * example, the links of a tree node) are independently subject to
 237.129 + * atomic updates.  These classes enable greater flexibility in how
 237.130 + * and when to use atomic updates, at the expense of more awkward
 237.131 + * reflection-based setup, less convenient usage, and weaker
 237.132 + * guarantees.
 237.133 + *
 237.134 + * <p>The
 237.135 + * {@link java.util.concurrent.atomic.AtomicIntegerArray},
 237.136 + * {@link java.util.concurrent.atomic.AtomicLongArray}, and
 237.137 + * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
 237.138 + * further extend atomic operation support to arrays of these types.
 237.139 + * These classes are also notable in providing {@code volatile} access
 237.140 + * semantics for their array elements, which is not supported for
 237.141 + * ordinary arrays.
 237.142 + *
 237.143 + * <a name="Spurious">
 237.144 + * <p>The atomic classes also support method {@code weakCompareAndSet},
 237.145 + * which has limited applicability.  On some platforms, the weak version
 237.146 + * may be more efficient than {@code compareAndSet} in the normal case,
 237.147 + * but differs in that any given invocation of the
 237.148 + * {@code weakCompareAndSet} method may return {@code false}
 237.149 + * <em>spuriously</em> (that is, for no apparent reason)</a>.  A
 237.150 + * {@code false} return means only that the operation may be retried if
 237.151 + * desired, relying on the guarantee that repeated invocation when the
 237.152 + * variable holds {@code expectedValue} and no other thread is also
 237.153 + * attempting to set the variable will eventually succeed.  (Such
 237.154 + * spurious failures may for example be due to memory contention effects
 237.155 + * that are unrelated to whether the expected and current values are
 237.156 + * equal.)  Additionally {@code weakCompareAndSet} does not provide
 237.157 + * ordering guarantees that are usually needed for synchronization
 237.158 + * control.  However, the method may be useful for updating counters and
 237.159 + * statistics when such updates are unrelated to the other
 237.160 + * happens-before orderings of a program.  When a thread sees an update
 237.161 + * to an atomic variable caused by a {@code weakCompareAndSet}, it does
 237.162 + * not necessarily see updates to any <em>other</em> variables that
 237.163 + * occurred before the {@code weakCompareAndSet}.  This may be
 237.164 + * acceptable when, for example, updating performance statistics, but
 237.165 + * rarely otherwise.
 237.166 + *
 237.167 + * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
 237.168 + * class associates a single boolean with a reference.  For example, this
 237.169 + * bit might be used inside a data structure to mean that the object
 237.170 + * being referenced has logically been deleted.
 237.171 + *
 237.172 + * The {@link java.util.concurrent.atomic.AtomicStampedReference}
 237.173 + * class associates an integer value with a reference.  This may be
 237.174 + * used for example, to represent version numbers corresponding to
 237.175 + * series of updates.
 237.176 + *
 237.177 + * <p>Atomic classes are designed primarily as building blocks for
 237.178 + * implementing non-blocking data structures and related infrastructure
 237.179 + * classes.  The {@code compareAndSet} method is not a general
 237.180 + * replacement for locking.  It applies only when critical updates for an
 237.181 + * object are confined to a <em>single</em> variable.
 237.182 + *
 237.183 + * <p>Atomic classes are not general purpose replacements for
 237.184 + * {@code java.lang.Integer} and related classes.  They do <em>not</em>
 237.185 + * define methods such as {@code hashCode} and
 237.186 + * {@code compareTo}.  (Because atomic variables are expected to be
 237.187 + * mutated, they are poor choices for hash table keys.)  Additionally,
 237.188 + * classes are provided only for those types that are commonly useful in
 237.189 + * intended applications.  For example, there is no atomic class for
 237.190 + * representing {@code byte}.  In those infrequent cases where you would
 237.191 + * like to do so, you can use an {@code AtomicInteger} to hold
 237.192 + * {@code byte} values, and cast appropriately.
 237.193 + *
 237.194 + * You can also hold floats using
 237.195 + * {@link java.lang.Float#floatToIntBits} and
 237.196 + * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
 237.197 + * {@link java.lang.Double#doubleToLongBits} and
 237.198 + * {@link java.lang.Double#longBitsToDouble} conversions.
 237.199 + *
 237.200 + * @since 1.5
 237.201 + */
 237.202 +package java.util.concurrent.atomic;
   238.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   238.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/Level.java	Wed Apr 30 15:04:10 2014 +0200
   238.3 @@ -0,0 +1,372 @@
   238.4 +/*
   238.5 + * Copyright (c) 2000, 2010, 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 java.util.logging;
  238.30 +
  238.31 +/**
  238.32 + * The Level class defines a set of standard logging levels that
  238.33 + * can be used to control logging output.  The logging Level objects
  238.34 + * are ordered and are specified by ordered integers.  Enabling logging
  238.35 + * at a given level also enables logging at all higher levels.
  238.36 + * <p>
  238.37 + * Clients should normally use the predefined Level constants such
  238.38 + * as Level.SEVERE.
  238.39 + * <p>
  238.40 + * The levels in descending order are:
  238.41 + * <ul>
  238.42 + * <li>SEVERE (highest value)
  238.43 + * <li>WARNING
  238.44 + * <li>INFO
  238.45 + * <li>CONFIG
  238.46 + * <li>FINE
  238.47 + * <li>FINER
  238.48 + * <li>FINEST  (lowest value)
  238.49 + * </ul>
  238.50 + * In addition there is a level OFF that can be used to turn
  238.51 + * off logging, and a level ALL that can be used to enable
  238.52 + * logging of all messages.
  238.53 + * <p>
  238.54 + * It is possible for third parties to define additional logging
  238.55 + * levels by subclassing Level.  In such cases subclasses should
  238.56 + * take care to chose unique integer level values and to ensure that
  238.57 + * they maintain the Object uniqueness property across serialization
  238.58 + * by defining a suitable readResolve method.
  238.59 + *
  238.60 + * @since 1.4
  238.61 + */
  238.62 +
  238.63 +public class Level implements java.io.Serializable {
  238.64 +    private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
  238.65 +    private static String defaultBundle = "sun.util.logging.resources.logging";
  238.66 +
  238.67 +    /**
  238.68 +     * @serial  The non-localized name of the level.
  238.69 +     */
  238.70 +    private final String name;
  238.71 +
  238.72 +    /**
  238.73 +     * @serial  The integer value of the level.
  238.74 +     */
  238.75 +    private final int value;
  238.76 +
  238.77 +    /**
  238.78 +     * @serial The resource bundle name to be used in localizing the level name.
  238.79 +     */
  238.80 +    private final String resourceBundleName;
  238.81 +
  238.82 +    /**
  238.83 +     * OFF is a special level that can be used to turn off logging.
  238.84 +     * This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
  238.85 +     */
  238.86 +    public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
  238.87 +
  238.88 +    /**
  238.89 +     * SEVERE is a message level indicating a serious failure.
  238.90 +     * <p>
  238.91 +     * In general SEVERE messages should describe events that are
  238.92 +     * of considerable importance and which will prevent normal
  238.93 +     * program execution.   They should be reasonably intelligible
  238.94 +     * to end users and to system administrators.
  238.95 +     * This level is initialized to <CODE>1000</CODE>.
  238.96 +     */
  238.97 +    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
  238.98 +
  238.99 +    /**
 238.100 +     * WARNING is a message level indicating a potential problem.
 238.101 +     * <p>
 238.102 +     * In general WARNING messages should describe events that will
 238.103 +     * be of interest to end users or system managers, or which
 238.104 +     * indicate potential problems.
 238.105 +     * This level is initialized to <CODE>900</CODE>.
 238.106 +     */
 238.107 +    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
 238.108 +
 238.109 +    /**
 238.110 +     * INFO is a message level for informational messages.
 238.111 +     * <p>
 238.112 +     * Typically INFO messages will be written to the console
 238.113 +     * or its equivalent.  So the INFO level should only be
 238.114 +     * used for reasonably significant messages that will
 238.115 +     * make sense to end users and system administrators.
 238.116 +     * This level is initialized to <CODE>800</CODE>.
 238.117 +     */
 238.118 +    public static final Level INFO = new Level("INFO", 800, defaultBundle);
 238.119 +
 238.120 +    /**
 238.121 +     * CONFIG is a message level for static configuration messages.
 238.122 +     * <p>
 238.123 +     * CONFIG messages are intended to provide a variety of static
 238.124 +     * configuration information, to assist in debugging problems
 238.125 +     * that may be associated with particular configurations.
 238.126 +     * For example, CONFIG message might include the CPU type,
 238.127 +     * the graphics depth, the GUI look-and-feel, etc.
 238.128 +     * This level is initialized to <CODE>700</CODE>.
 238.129 +     */
 238.130 +    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
 238.131 +
 238.132 +    /**
 238.133 +     * FINE is a message level providing tracing information.
 238.134 +     * <p>
 238.135 +     * All of FINE, FINER, and FINEST are intended for relatively
 238.136 +     * detailed tracing.  The exact meaning of the three levels will
 238.137 +     * vary between subsystems, but in general, FINEST should be used
 238.138 +     * for the most voluminous detailed output, FINER for somewhat
 238.139 +     * less detailed output, and FINE for the  lowest volume (and
 238.140 +     * most important) messages.
 238.141 +     * <p>
 238.142 +     * In general the FINE level should be used for information
 238.143 +     * that will be broadly interesting to developers who do not have
 238.144 +     * a specialized interest in the specific subsystem.
 238.145 +     * <p>
 238.146 +     * FINE messages might include things like minor (recoverable)
 238.147 +     * failures.  Issues indicating potential performance problems
 238.148 +     * are also worth logging as FINE.
 238.149 +     * This level is initialized to <CODE>500</CODE>.
 238.150 +     */
 238.151 +    public static final Level FINE = new Level("FINE", 500, defaultBundle);
 238.152 +
 238.153 +    /**
 238.154 +     * FINER indicates a fairly detailed tracing message.
 238.155 +     * By default logging calls for entering, returning, or throwing
 238.156 +     * an exception are traced at this level.
 238.157 +     * This level is initialized to <CODE>400</CODE>.
 238.158 +     */
 238.159 +    public static final Level FINER = new Level("FINER", 400, defaultBundle);
 238.160 +
 238.161 +    /**
 238.162 +     * FINEST indicates a highly detailed tracing message.
 238.163 +     * This level is initialized to <CODE>300</CODE>.
 238.164 +     */
 238.165 +    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
 238.166 +
 238.167 +    /**
 238.168 +     * ALL indicates that all messages should be logged.
 238.169 +     * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
 238.170 +     */
 238.171 +    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
 238.172 +
 238.173 +    /**
 238.174 +     * Create a named Level with a given integer value.
 238.175 +     * <p>
 238.176 +     * Note that this constructor is "protected" to allow subclassing.
 238.177 +     * In general clients of logging should use one of the constant Level
 238.178 +     * objects such as SEVERE or FINEST.  However, if clients need to
 238.179 +     * add new logging levels, they may subclass Level and define new
 238.180 +     * constants.
 238.181 +     * @param name  the name of the Level, for example "SEVERE".
 238.182 +     * @param value an integer value for the level.
 238.183 +     * @throws NullPointerException if the name is null
 238.184 +     */
 238.185 +    protected Level(String name, int value) {
 238.186 +        this(name, value, null);
 238.187 +    }
 238.188 +
 238.189 +    /**
 238.190 +     * Create a named Level with a given integer value and a
 238.191 +     * given localization resource name.
 238.192 +     * <p>
 238.193 +     * @param name  the name of the Level, for example "SEVERE".
 238.194 +     * @param value an integer value for the level.
 238.195 +     * @param resourceBundleName name of a resource bundle to use in
 238.196 +     *    localizing the given name. If the resourceBundleName is null
 238.197 +     *    or an empty string, it is ignored.
 238.198 +     * @throws NullPointerException if the name is null
 238.199 +     */
 238.200 +    protected Level(String name, int value, String resourceBundleName) {
 238.201 +        if (name == null) {
 238.202 +            throw new NullPointerException();
 238.203 +        }
 238.204 +        this.name = name;
 238.205 +        this.value = value;
 238.206 +        this.resourceBundleName = resourceBundleName;
 238.207 +        synchronized (Level.class) {
 238.208 +            known.add(this);
 238.209 +        }
 238.210 +    }
 238.211 +
 238.212 +    /**
 238.213 +     * Return the level's localization resource bundle name, or
 238.214 +     * null if no localization bundle is defined.
 238.215 +     *
 238.216 +     * @return localization resource bundle name
 238.217 +     */
 238.218 +    public String getResourceBundleName() {
 238.219 +        return resourceBundleName;
 238.220 +    }
 238.221 +
 238.222 +    /**
 238.223 +     * Return the non-localized string name of the Level.
 238.224 +     *
 238.225 +     * @return non-localized name
 238.226 +     */
 238.227 +    public String getName() {
 238.228 +        return name;
 238.229 +    }
 238.230 +
 238.231 +    /**
 238.232 +     * Return the localized string name of the Level, for
 238.233 +     * the current default locale.
 238.234 +     * <p>
 238.235 +     * If no localization information is available, the
 238.236 +     * non-localized name is returned.
 238.237 +     *
 238.238 +     * @return localized name
 238.239 +     */
 238.240 +    public String getLocalizedName() {
 238.241 +        return getName();
 238.242 +    }
 238.243 +
 238.244 +    /**
 238.245 +     * Returns a string representation of this Level.
 238.246 +     *
 238.247 +     * @return the non-localized name of the Level, for example "INFO".
 238.248 +     */
 238.249 +    public final String toString() {
 238.250 +        return name;
 238.251 +    }
 238.252 +
 238.253 +    /**
 238.254 +     * Get the integer value for this level.  This integer value
 238.255 +     * can be used for efficient ordering comparisons between
 238.256 +     * Level objects.
 238.257 +     * @return the integer value for this level.
 238.258 +     */
 238.259 +    public final int intValue() {
 238.260 +        return value;
 238.261 +    }
 238.262 +
 238.263 +    private static final long serialVersionUID = -8176160795706313070L;
 238.264 +
 238.265 +    // Serialization magic to prevent "doppelgangers".
 238.266 +    // This is a performance optimization.
 238.267 +    private Object readResolve() {
 238.268 +        synchronized (Level.class) {
 238.269 +            for (int i = 0; i < known.size(); i++) {
 238.270 +                Level other = known.get(i);
 238.271 +                if (this.name.equals(other.name) && this.value == other.value
 238.272 +                        && (this.resourceBundleName == other.resourceBundleName ||
 238.273 +                            (this.resourceBundleName != null &&
 238.274 +                            this.resourceBundleName.equals(other.resourceBundleName)))) {
 238.275 +                    return other;
 238.276 +                }
 238.277 +            }
 238.278 +            // Woops.  Whoever sent us this object knows
 238.279 +            // about a new log level.  Add it to our list.
 238.280 +            known.add(this);
 238.281 +            return this;
 238.282 +        }
 238.283 +    }
 238.284 +
 238.285 +    /**
 238.286 +     * Parse a level name string into a Level.
 238.287 +     * <p>
 238.288 +     * The argument string may consist of either a level name
 238.289 +     * or an integer value.
 238.290 +     * <p>
 238.291 +     * For example:
 238.292 +     * <ul>
 238.293 +     * <li>     "SEVERE"
 238.294 +     * <li>     "1000"
 238.295 +     * </ul>
 238.296 +     * @param  name   string to be parsed
 238.297 +     * @throws NullPointerException if the name is null
 238.298 +     * @throws IllegalArgumentException if the value is not valid.
 238.299 +     * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
 238.300 +     * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
 238.301 +     * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
 238.302 +     * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
 238.303 +     * appropriate package access, or new levels defined or created
 238.304 +     * by subclasses.
 238.305 +     *
 238.306 +     * @return The parsed value. Passing an integer that corresponds to a known name
 238.307 +     * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
 238.308 +     * Passing an integer that does not (e.g., 1) will return a new level name
 238.309 +     * initialized to that value.
 238.310 +     */
 238.311 +    public static synchronized Level parse(String name) throws IllegalArgumentException {
 238.312 +        // Check that name is not null.
 238.313 +        name.length();
 238.314 +
 238.315 +        // Look for a known Level with the given non-localized name.
 238.316 +        for (int i = 0; i < known.size(); i++) {
 238.317 +            Level l = known.get(i);
 238.318 +            if (name.equals(l.name)) {
 238.319 +                return l;
 238.320 +            }
 238.321 +        }
 238.322 +
 238.323 +        // Now, check if the given name is an integer.  If so,
 238.324 +        // first look for a Level with the given value and then
 238.325 +        // if necessary create one.
 238.326 +        try {
 238.327 +            int x = Integer.parseInt(name);
 238.328 +            for (int i = 0; i < known.size(); i++) {
 238.329 +                Level l = known.get(i);
 238.330 +                if (l.value == x) {
 238.331 +                    return l;
 238.332 +                }
 238.333 +            }
 238.334 +            // Create a new Level.
 238.335 +            return new Level(name, x);
 238.336 +        } catch (NumberFormatException ex) {
 238.337 +            // Not an integer.
 238.338 +            // Drop through.
 238.339 +        }
 238.340 +
 238.341 +        // Finally, look for a known level with the given localized name,
 238.342 +        // in the current default locale.
 238.343 +        // This is relatively expensive, but not excessively so.
 238.344 +        for (int i = 0; i < known.size(); i++) {
 238.345 +            Level l =  known.get(i);
 238.346 +            if (name.equals(l.getLocalizedName())) {
 238.347 +                return l;
 238.348 +            }
 238.349 +        }
 238.350 +
 238.351 +        // OK, we've tried everything and failed
 238.352 +        throw new IllegalArgumentException("Bad level \"" + name + "\"");
 238.353 +    }
 238.354 +
 238.355 +    /**
 238.356 +     * Compare two objects for value equality.
 238.357 +     * @return true if and only if the two objects have the same level value.
 238.358 +     */
 238.359 +    public boolean equals(Object ox) {
 238.360 +        try {
 238.361 +            Level lx = (Level)ox;
 238.362 +            return (lx.value == this.value);
 238.363 +        } catch (Exception ex) {
 238.364 +            return false;
 238.365 +        }
 238.366 +    }
 238.367 +
 238.368 +    /**
 238.369 +     * Generate a hashcode.
 238.370 +     * @return a hashcode based on the level value
 238.371 +     */
 238.372 +    public int hashCode() {
 238.373 +        return this.value;
 238.374 +    }
 238.375 +}
   239.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   239.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/LogRecord.java	Wed Apr 30 15:04:10 2014 +0200
   239.3 @@ -0,0 +1,468 @@
   239.4 +/*
   239.5 + * Copyright (c) 2000, 2010, 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 +package java.util.logging;
  239.30 +import java.io.*;
  239.31 +
  239.32 +/**
  239.33 + * LogRecord objects are used to pass logging requests between
  239.34 + * the logging framework and individual log Handlers.
  239.35 + * <p>
  239.36 + * When a LogRecord is passed into the logging framework it
  239.37 + * logically belongs to the framework and should no longer be
  239.38 + * used or updated by the client application.
  239.39 + * <p>
  239.40 + * Note that if the client application has not specified an
  239.41 + * explicit source method name and source class name, then the
  239.42 + * LogRecord class will infer them automatically when they are
  239.43 + * first accessed (due to a call on getSourceMethodName or
  239.44 + * getSourceClassName) by analyzing the call stack.  Therefore,
  239.45 + * if a logging Handler wants to pass off a LogRecord to another
  239.46 + * thread, or to transmit it over RMI, and if it wishes to subsequently
  239.47 + * obtain method name or class name information it should call
  239.48 + * one of getSourceClassName or getSourceMethodName to force
  239.49 + * the values to be filled in.
  239.50 + * <p>
  239.51 + * <b> Serialization notes:</b>
  239.52 + * <ul>
  239.53 + * <li>The LogRecord class is serializable.
  239.54 + *
  239.55 + * <li> Because objects in the parameters array may not be serializable,
  239.56 + * during serialization all objects in the parameters array are
  239.57 + * written as the corresponding Strings (using Object.toString).
  239.58 + *
  239.59 + * <li> The ResourceBundle is not transmitted as part of the serialized
  239.60 + * form, but the resource bundle name is, and the recipient object's
  239.61 + * readObject method will attempt to locate a suitable resource bundle.
  239.62 + *
  239.63 + * </ul>
  239.64 + *
  239.65 + * @since 1.4
  239.66 + */
  239.67 +
  239.68 +public class LogRecord implements java.io.Serializable {
  239.69 +    private static long globalSequenceNumber = 0;
  239.70 +
  239.71 +    /**
  239.72 +     * The default value of threadID will be the current thread's
  239.73 +     * thread id, for ease of correlation, unless it is greater than
  239.74 +     * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
  239.75 +     * our promise to keep threadIDs unique by avoiding collisions due
  239.76 +     * to 32-bit wraparound.  Unfortunately, LogRecord.getThreadID()
  239.77 +     * returns int, while Thread.getId() returns long.
  239.78 +     */
  239.79 +    private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
  239.80 +
  239.81 +    /**
  239.82 +     * @serial Logging message level
  239.83 +     */
  239.84 +    private Level level;
  239.85 +
  239.86 +    /**
  239.87 +     * @serial Sequence number
  239.88 +     */
  239.89 +    private long sequenceNumber;
  239.90 +
  239.91 +    /**
  239.92 +     * @serial Class that issued logging call
  239.93 +     */
  239.94 +    private String sourceClassName;
  239.95 +
  239.96 +    /**
  239.97 +     * @serial Method that issued logging call
  239.98 +     */
  239.99 +    private String sourceMethodName;
 239.100 +
 239.101 +    /**
 239.102 +     * @serial Non-localized raw message text
 239.103 +     */
 239.104 +    private String message;
 239.105 +
 239.106 +    /**
 239.107 +     * @serial Thread ID for thread that issued logging call.
 239.108 +     */
 239.109 +    private int threadID;
 239.110 +
 239.111 +    /**
 239.112 +     * @serial Event time in milliseconds since 1970
 239.113 +     */
 239.114 +    private long millis;
 239.115 +
 239.116 +    /**
 239.117 +     * @serial The Throwable (if any) associated with log message
 239.118 +     */
 239.119 +    private Throwable thrown;
 239.120 +
 239.121 +    /**
 239.122 +     * @serial Name of the source Logger.
 239.123 +     */
 239.124 +    private String loggerName;
 239.125 +
 239.126 +    /**
 239.127 +     * @serial Resource bundle name to localized log message.
 239.128 +     */
 239.129 +    private String resourceBundleName;
 239.130 +
 239.131 +    private transient boolean needToInferCaller;
 239.132 +    private transient Object parameters[];
 239.133 +
 239.134 +    /**
 239.135 +     * Returns the default value for a new LogRecord's threadID.
 239.136 +     */
 239.137 +    private int defaultThreadID() {
 239.138 +        return 0;
 239.139 +    }
 239.140 +
 239.141 +    /**
 239.142 +     * Construct a LogRecord with the given level and message values.
 239.143 +     * <p>
 239.144 +     * The sequence property will be initialized with a new unique value.
 239.145 +     * These sequence values are allocated in increasing order within a VM.
 239.146 +     * <p>
 239.147 +     * The millis property will be initialized to the current time.
 239.148 +     * <p>
 239.149 +     * The thread ID property will be initialized with a unique ID for
 239.150 +     * the current thread.
 239.151 +     * <p>
 239.152 +     * All other properties will be initialized to "null".
 239.153 +     *
 239.154 +     * @param level  a logging level value
 239.155 +     * @param msg  the raw non-localized logging message (may be null)
 239.156 +     */
 239.157 +    public LogRecord(Level level, String msg) {
 239.158 +        // Make sure level isn't null, by calling random method.
 239.159 +        level.getClass();
 239.160 +        this.level = level;
 239.161 +        message = msg;
 239.162 +        // Assign a thread ID and a unique sequence number.
 239.163 +        sequenceNumber = globalSequenceNumber++;
 239.164 +        threadID = defaultThreadID();
 239.165 +        millis = System.currentTimeMillis();
 239.166 +        needToInferCaller = true;
 239.167 +   }
 239.168 +
 239.169 +    /**
 239.170 +     * Get the source Logger's name.
 239.171 +     *
 239.172 +     * @return source logger name (may be null)
 239.173 +     */
 239.174 +    public String getLoggerName() {
 239.175 +        return loggerName;
 239.176 +    }
 239.177 +
 239.178 +    /**
 239.179 +     * Set the source Logger's name.
 239.180 +     *
 239.181 +     * @param name   the source logger name (may be null)
 239.182 +     */
 239.183 +    public void setLoggerName(String name) {
 239.184 +        loggerName = name;
 239.185 +    }
 239.186 +
 239.187 +    /**
 239.188 +     * Get the localization resource bundle
 239.189 +     * <p>
 239.190 +     * This is the ResourceBundle that should be used to localize
 239.191 +     * the message string before formatting it.  The result may
 239.192 +     * be null if the message is not localizable, or if no suitable
 239.193 +     * ResourceBundle is available.
 239.194 +     */
 239.195 +//    public ResourceBundle getResourceBundle() {
 239.196 +//        return resourceBundle;
 239.197 +//    }
 239.198 +
 239.199 +    /**
 239.200 +     * Set the localization resource bundle.
 239.201 +     *
 239.202 +     * @param bundle  localization bundle (may be null)
 239.203 +     */
 239.204 +//    public void setResourceBundle(ResourceBundle bundle) {
 239.205 +//        resourceBundle = bundle;
 239.206 +//    }
 239.207 +
 239.208 +    /**
 239.209 +     * Get the localization resource bundle name
 239.210 +     * <p>
 239.211 +     * This is the name for the ResourceBundle that should be
 239.212 +     * used to localize the message string before formatting it.
 239.213 +     * The result may be null if the message is not localizable.
 239.214 +     */
 239.215 +    public String getResourceBundleName() {
 239.216 +        return resourceBundleName;
 239.217 +    }
 239.218 +
 239.219 +    /**
 239.220 +     * Set the localization resource bundle name.
 239.221 +     *
 239.222 +     * @param name  localization bundle name (may be null)
 239.223 +     */
 239.224 +    public void setResourceBundleName(String name) {
 239.225 +        resourceBundleName = name;
 239.226 +    }
 239.227 +
 239.228 +    /**
 239.229 +     * Get the logging message level, for example Level.SEVERE.
 239.230 +     * @return the logging message level
 239.231 +     */
 239.232 +    public Level getLevel() {
 239.233 +        return level;
 239.234 +    }
 239.235 +
 239.236 +    /**
 239.237 +     * Set the logging message level, for example Level.SEVERE.
 239.238 +     * @param level the logging message level
 239.239 +     */
 239.240 +    public void setLevel(Level level) {
 239.241 +        if (level == null) {
 239.242 +            throw new NullPointerException();
 239.243 +        }
 239.244 +        this.level = level;
 239.245 +    }
 239.246 +
 239.247 +    /**
 239.248 +     * Get the sequence number.
 239.249 +     * <p>
 239.250 +     * Sequence numbers are normally assigned in the LogRecord
 239.251 +     * constructor, which assigns unique sequence numbers to
 239.252 +     * each new LogRecord in increasing order.
 239.253 +     * @return the sequence number
 239.254 +     */
 239.255 +    public long getSequenceNumber() {
 239.256 +        return sequenceNumber;
 239.257 +    }
 239.258 +
 239.259 +    /**
 239.260 +     * Set the sequence number.
 239.261 +     * <p>
 239.262 +     * Sequence numbers are normally assigned in the LogRecord constructor,
 239.263 +     * so it should not normally be necessary to use this method.
 239.264 +     */
 239.265 +    public void setSequenceNumber(long seq) {
 239.266 +        sequenceNumber = seq;
 239.267 +    }
 239.268 +
 239.269 +    /**
 239.270 +     * Get the  name of the class that (allegedly) issued the logging request.
 239.271 +     * <p>
 239.272 +     * Note that this sourceClassName is not verified and may be spoofed.
 239.273 +     * This information may either have been provided as part of the
 239.274 +     * logging call, or it may have been inferred automatically by the
 239.275 +     * logging framework.  In the latter case, the information may only
 239.276 +     * be approximate and may in fact describe an earlier call on the
 239.277 +     * stack frame.
 239.278 +     * <p>
 239.279 +     * May be null if no information could be obtained.
 239.280 +     *
 239.281 +     * @return the source class name
 239.282 +     */
 239.283 +    public String getSourceClassName() {
 239.284 +        return sourceClassName;
 239.285 +    }
 239.286 +
 239.287 +    /**
 239.288 +     * Set the name of the class that (allegedly) issued the logging request.
 239.289 +     *
 239.290 +     * @param sourceClassName the source class name (may be null)
 239.291 +     */
 239.292 +    public void setSourceClassName(String sourceClassName) {
 239.293 +        this.sourceClassName = sourceClassName;
 239.294 +        needToInferCaller = false;
 239.295 +    }
 239.296 +
 239.297 +    /**
 239.298 +     * Get the  name of the method that (allegedly) issued the logging request.
 239.299 +     * <p>
 239.300 +     * Note that this sourceMethodName is not verified and may be spoofed.
 239.301 +     * This information may either have been provided as part of the
 239.302 +     * logging call, or it may have been inferred automatically by the
 239.303 +     * logging framework.  In the latter case, the information may only
 239.304 +     * be approximate and may in fact describe an earlier call on the
 239.305 +     * stack frame.
 239.306 +     * <p>
 239.307 +     * May be null if no information could be obtained.
 239.308 +     *
 239.309 +     * @return the source method name
 239.310 +     */
 239.311 +    public String getSourceMethodName() {
 239.312 +        return sourceMethodName;
 239.313 +    }
 239.314 +
 239.315 +    /**
 239.316 +     * Set the name of the method that (allegedly) issued the logging request.
 239.317 +     *
 239.318 +     * @param sourceMethodName the source method name (may be null)
 239.319 +     */
 239.320 +    public void setSourceMethodName(String sourceMethodName) {
 239.321 +        this.sourceMethodName = sourceMethodName;
 239.322 +        needToInferCaller = false;
 239.323 +    }
 239.324 +
 239.325 +    /**
 239.326 +     * Get the "raw" log message, before localization or formatting.
 239.327 +     * <p>
 239.328 +     * May be null, which is equivalent to the empty string "".
 239.329 +     * <p>
 239.330 +     * This message may be either the final text or a localization key.
 239.331 +     * <p>
 239.332 +     * During formatting, if the source logger has a localization
 239.333 +     * ResourceBundle and if that ResourceBundle has an entry for
 239.334 +     * this message string, then the message string is replaced
 239.335 +     * with the localized value.
 239.336 +     *
 239.337 +     * @return the raw message string
 239.338 +     */
 239.339 +    public String getMessage() {
 239.340 +        return message;
 239.341 +    }
 239.342 +
 239.343 +    /**
 239.344 +     * Set the "raw" log message, before localization or formatting.
 239.345 +     *
 239.346 +     * @param message the raw message string (may be null)
 239.347 +     */
 239.348 +    public void setMessage(String message) {
 239.349 +        this.message = message;
 239.350 +    }
 239.351 +
 239.352 +    /**
 239.353 +     * Get the parameters to the log message.
 239.354 +     *
 239.355 +     * @return the log message parameters.  May be null if
 239.356 +     *                  there are no parameters.
 239.357 +     */
 239.358 +    public Object[] getParameters() {
 239.359 +        return parameters;
 239.360 +    }
 239.361 +
 239.362 +    /**
 239.363 +     * Set the parameters to the log message.
 239.364 +     *
 239.365 +     * @param parameters the log message parameters. (may be null)
 239.366 +     */
 239.367 +    public void setParameters(Object parameters[]) {
 239.368 +        this.parameters = parameters;
 239.369 +    }
 239.370 +
 239.371 +    /**
 239.372 +     * Get an identifier for the thread where the message originated.
 239.373 +     * <p>
 239.374 +     * This is a thread identifier within the Java VM and may or
 239.375 +     * may not map to any operating system ID.
 239.376 +     *
 239.377 +     * @return thread ID
 239.378 +     */
 239.379 +    public int getThreadID() {
 239.380 +        return threadID;
 239.381 +    }
 239.382 +
 239.383 +    /**
 239.384 +     * Set an identifier for the thread where the message originated.
 239.385 +     * @param threadID  the thread ID
 239.386 +     */
 239.387 +    public void setThreadID(int threadID) {
 239.388 +        this.threadID = threadID;
 239.389 +    }
 239.390 +
 239.391 +    /**
 239.392 +     * Get event time in milliseconds since 1970.
 239.393 +     *
 239.394 +     * @return event time in millis since 1970
 239.395 +     */
 239.396 +    public long getMillis() {
 239.397 +        return millis;
 239.398 +    }
 239.399 +
 239.400 +    /**
 239.401 +     * Set event time.
 239.402 +     *
 239.403 +     * @param millis event time in millis since 1970
 239.404 +     */
 239.405 +    public void setMillis(long millis) {
 239.406 +        this.millis = millis;
 239.407 +    }
 239.408 +
 239.409 +    /**
 239.410 +     * Get any throwable associated with the log record.
 239.411 +     * <p>
 239.412 +     * If the event involved an exception, this will be the
 239.413 +     * exception object. Otherwise null.
 239.414 +     *
 239.415 +     * @return a throwable
 239.416 +     */
 239.417 +    public Throwable getThrown() {
 239.418 +        return thrown;
 239.419 +    }
 239.420 +
 239.421 +    /**
 239.422 +     * Set a throwable associated with the log event.
 239.423 +     *
 239.424 +     * @param thrown  a throwable (may be null)
 239.425 +     */
 239.426 +    public void setThrown(Throwable thrown) {
 239.427 +        this.thrown = thrown;
 239.428 +    }
 239.429 +
 239.430 +    private static final long serialVersionUID = 5372048053134512534L;
 239.431 +
 239.432 +    /**
 239.433 +     * @serialData Default fields, followed by a two byte version number
 239.434 +     * (major byte, followed by minor byte), followed by information on
 239.435 +     * the log record parameter array.  If there is no parameter array,
 239.436 +     * then -1 is written.  If there is a parameter array (possible of zero
 239.437 +     * length) then the array length is written as an integer, followed
 239.438 +     * by String values for each parameter.  If a parameter is null, then
 239.439 +     * a null String is written.  Otherwise the output of Object.toString()
 239.440 +     * is written.
 239.441 +     */
 239.442 +    private void writeObject(ObjectOutputStream out) throws IOException {
 239.443 +        // We have to call defaultWriteObject first.
 239.444 +        out.defaultWriteObject();
 239.445 +
 239.446 +        // Write our version number.
 239.447 +        out.writeByte(1);
 239.448 +        out.writeByte(0);
 239.449 +        if (parameters == null) {
 239.450 +            out.writeInt(-1);
 239.451 +            return;
 239.452 +        }
 239.453 +        out.writeInt(parameters.length);
 239.454 +        // Write string values for the parameters.
 239.455 +        for (int i = 0; i < parameters.length; i++) {
 239.456 +            if (parameters[i] == null) {
 239.457 +                out.writeObject(null);
 239.458 +            } else {
 239.459 +                out.writeObject(parameters[i].toString());
 239.460 +            }
 239.461 +        }
 239.462 +    }
 239.463 +
 239.464 +
 239.465 +    private boolean isLoggerImplFrame(String cname) {
 239.466 +        // the log record could be created for a platform logger
 239.467 +        return (cname.equals("java.util.logging.Logger") ||
 239.468 +                cname.startsWith("java.util.logging.LoggingProxyImpl") ||
 239.469 +                cname.startsWith("sun.util.logging."));
 239.470 +    }
 239.471 +}
   240.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   240.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/Logger.java	Wed Apr 30 15:04:10 2014 +0200
   240.3 @@ -0,0 +1,1264 @@
   240.4 +/*
   240.5 + * Copyright (c) 2000, 2011, 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 java.util.logging;
  240.31 +
  240.32 +import java.util.HashMap;
  240.33 +import java.util.Map;
  240.34 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  240.35 +
  240.36 +/**
  240.37 + * A Logger object is used to log messages for a specific
  240.38 + * system or application component.  Loggers are normally named,
  240.39 + * using a hierarchical dot-separated namespace.  Logger names
  240.40 + * can be arbitrary strings, but they should normally be based on
  240.41 + * the package name or class name of the logged component, such
  240.42 + * as java.net or javax.swing.  In addition it is possible to create
  240.43 + * "anonymous" Loggers that are not stored in the Logger namespace.
  240.44 + * <p>
  240.45 + * Logger objects may be obtained by calls on one of the getLogger
  240.46 + * factory methods.  These will either create a new Logger or
  240.47 + * return a suitable existing Logger. It is important to note that
  240.48 + * the Logger returned by one of the {@code getLogger} factory methods
  240.49 + * may be garbage collected at any time if a strong reference to the
  240.50 + * Logger is not kept.
  240.51 + * <p>
  240.52 + * Logging messages will be forwarded to registered Handler
  240.53 + * objects, which can forward the messages to a variety of
  240.54 + * destinations, including consoles, files, OS logs, etc.
  240.55 + * <p>
  240.56 + * Each Logger keeps track of a "parent" Logger, which is its
  240.57 + * nearest existing ancestor in the Logger namespace.
  240.58 + * <p>
  240.59 + * Each Logger has a "Level" associated with it.  This reflects
  240.60 + * a minimum Level that this logger cares about.  If a Logger's
  240.61 + * level is set to <tt>null</tt>, then its effective level is inherited
  240.62 + * from its parent, which may in turn obtain it recursively from its
  240.63 + * parent, and so on up the tree.
  240.64 + * <p>
  240.65 + * The log level can be configured based on the properties from the
  240.66 + * logging configuration file, as described in the description
  240.67 + * of the LogManager class.  However it may also be dynamically changed
  240.68 + * by calls on the Logger.setLevel method.  If a logger's level is
  240.69 + * changed the change may also affect child loggers, since any child
  240.70 + * logger that has <tt>null</tt> as its level will inherit its
  240.71 + * effective level from its parent.
  240.72 + * <p>
  240.73 + * On each logging call the Logger initially performs a cheap
  240.74 + * check of the request level (e.g., SEVERE or FINE) against the
  240.75 + * effective log level of the logger.  If the request level is
  240.76 + * lower than the log level, the logging call returns immediately.
  240.77 + * <p>
  240.78 + * After passing this initial (cheap) test, the Logger will allocate
  240.79 + * a LogRecord to describe the logging message.  It will then call a
  240.80 + * Filter (if present) to do a more detailed check on whether the
  240.81 + * record should be published.  If that passes it will then publish
  240.82 + * the LogRecord to its output Handlers.  By default, loggers also
  240.83 + * publish to their parent's Handlers, recursively up the tree.
  240.84 + * <p>
  240.85 + * Each Logger may have a ResourceBundle name associated with it.
  240.86 + * The named bundle will be used for localizing logging messages.
  240.87 + * If a Logger does not have its own ResourceBundle name, then
  240.88 + * it will inherit the ResourceBundle name from its parent,
  240.89 + * recursively up the tree.
  240.90 + * <p>
  240.91 + * Most of the logger output methods take a "msg" argument.  This
  240.92 + * msg argument may be either a raw value or a localization key.
  240.93 + * During formatting, if the logger has (or inherits) a localization
  240.94 + * ResourceBundle and if the ResourceBundle has a mapping for the msg
  240.95 + * string, then the msg string is replaced by the localized value.
  240.96 + * Otherwise the original msg string is used.  Typically, formatters use
  240.97 + * java.text.MessageFormat style formatting to format parameters, so
  240.98 + * for example a format string "{0} {1}" would format two parameters
  240.99 + * as strings.
 240.100 + * <p>
 240.101 + * When mapping ResourceBundle names to ResourceBundles, the Logger
 240.102 + * will first try to use the Thread's ContextClassLoader.  If that
 240.103 + * is null it will try the SystemClassLoader instead.  As a temporary
 240.104 + * transition feature in the initial implementation, if the Logger is
 240.105 + * unable to locate a ResourceBundle from the ContextClassLoader or
 240.106 + * SystemClassLoader the Logger will also search up the class stack
 240.107 + * and use successive calling ClassLoaders to try to locate a ResourceBundle.
 240.108 + * (This call stack search is to allow containers to transition to
 240.109 + * using ContextClassLoaders and is likely to be removed in future
 240.110 + * versions.)
 240.111 + * <p>
 240.112 + * Formatting (including localization) is the responsibility of
 240.113 + * the output Handler, which will typically call a Formatter.
 240.114 + * <p>
 240.115 + * Note that formatting need not occur synchronously.  It may be delayed
 240.116 + * until a LogRecord is actually written to an external sink.
 240.117 + * <p>
 240.118 + * The logging methods are grouped in five main categories:
 240.119 + * <ul>
 240.120 + * <li><p>
 240.121 + *     There are a set of "log" methods that take a log level, a message
 240.122 + *     string, and optionally some parameters to the message string.
 240.123 + * <li><p>
 240.124 + *     There are a set of "logp" methods (for "log precise") that are
 240.125 + *     like the "log" methods, but also take an explicit source class name
 240.126 + *     and method name.
 240.127 + * <li><p>
 240.128 + *     There are a set of "logrb" method (for "log with resource bundle")
 240.129 + *     that are like the "logp" method, but also take an explicit resource
 240.130 + *     bundle name for use in localizing the log message.
 240.131 + * <li><p>
 240.132 + *     There are convenience methods for tracing method entries (the
 240.133 + *     "entering" methods), method returns (the "exiting" methods) and
 240.134 + *     throwing exceptions (the "throwing" methods).
 240.135 + * <li><p>
 240.136 + *     Finally, there are a set of convenience methods for use in the
 240.137 + *     very simplest cases, when a developer simply wants to log a
 240.138 + *     simple string at a given log level.  These methods are named
 240.139 + *     after the standard Level names ("severe", "warning", "info", etc.)
 240.140 + *     and take a single argument, a message string.
 240.141 + * </ul>
 240.142 + * <p>
 240.143 + * For the methods that do not take an explicit source name and
 240.144 + * method name, the Logging framework will make a "best effort"
 240.145 + * to determine which class and method called into the logging method.
 240.146 + * However, it is important to realize that this automatically inferred
 240.147 + * information may only be approximate (or may even be quite wrong!).
 240.148 + * Virtual machines are allowed to do extensive optimizations when
 240.149 + * JITing and may entirely remove stack frames, making it impossible
 240.150 + * to reliably locate the calling class and method.
 240.151 + * <P>
 240.152 + * All methods on Logger are multi-thread safe.
 240.153 + * <p>
 240.154 + * <b>Subclassing Information:</b> Note that a LogManager class may
 240.155 + * provide its own implementation of named Loggers for any point in
 240.156 + * the namespace.  Therefore, any subclasses of Logger (unless they
 240.157 + * are implemented in conjunction with a new LogManager class) should
 240.158 + * take care to obtain a Logger instance from the LogManager class and
 240.159 + * should delegate operations such as "isLoggable" and "log(LogRecord)"
 240.160 + * to that instance.  Note that in order to intercept all logging
 240.161 + * output, subclasses need only override the log(LogRecord) method.
 240.162 + * All the other logging methods are implemented as calls on this
 240.163 + * log(LogRecord) method.
 240.164 + *
 240.165 + * @since 1.4
 240.166 + */
 240.167 +
 240.168 +
 240.169 +public class Logger {
 240.170 +    private static int offValue = Level.OFF.intValue();
 240.171 +    private static final Map<String,Logger> ALL = new HashMap<>();
 240.172 +    private String name;
 240.173 +
 240.174 +    private volatile int levelValue;  // current effective level value
 240.175 +    private Level levelObject;
 240.176 +    
 240.177 +    /**
 240.178 +     * GLOBAL_LOGGER_NAME is a name for the global logger.
 240.179 +     *
 240.180 +     * @since 1.6
 240.181 +     */
 240.182 +    public static final String GLOBAL_LOGGER_NAME = "global";
 240.183 +
 240.184 +    /**
 240.185 +     * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
 240.186 +     *
 240.187 +     * @return global logger object
 240.188 +     * @since 1.7
 240.189 +     */
 240.190 +    public static final Logger getGlobal() {
 240.191 +        return global;
 240.192 +    }
 240.193 +
 240.194 +    /**
 240.195 +     * The "global" Logger object is provided as a convenience to developers
 240.196 +     * who are making casual use of the Logging package.  Developers
 240.197 +     * who are making serious use of the logging package (for example
 240.198 +     * in products) should create and use their own Logger objects,
 240.199 +     * with appropriate names, so that logging can be controlled on a
 240.200 +     * suitable per-Logger granularity. Developers also need to keep a
 240.201 +     * strong reference to their Logger objects to prevent them from
 240.202 +     * being garbage collected.
 240.203 +     * <p>
 240.204 +     * @deprecated Initialization of this field is prone to deadlocks.
 240.205 +     * The field must be initialized by the Logger class initialization
 240.206 +     * which may cause deadlocks with the LogManager class initialization.
 240.207 +     * In such cases two class initialization wait for each other to complete.
 240.208 +     * The preferred way to get the global logger object is via the call
 240.209 +     * <code>Logger.getGlobal()</code>.
 240.210 +     * For compatibility with old JDK versions where the
 240.211 +     * <code>Logger.getGlobal()</code> is not available use the call
 240.212 +     * <code>Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)</code>
 240.213 +     * or <code>Logger.getLogger("global")</code>.
 240.214 +     */
 240.215 +    @Deprecated
 240.216 +    public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
 240.217 +
 240.218 +    /**
 240.219 +     * Protected method to construct a logger for a named subsystem.
 240.220 +     * <p>
 240.221 +     * The logger will be initially configured with a null Level
 240.222 +     * and with useParentHandlers set to true.
 240.223 +     *
 240.224 +     * @param   name    A name for the logger.  This should
 240.225 +     *                          be a dot-separated name and should normally
 240.226 +     *                          be based on the package name or class name
 240.227 +     *                          of the subsystem, such as java.net
 240.228 +     *                          or javax.swing.  It may be null for anonymous Loggers.
 240.229 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 240.230 +     *                          messages for this logger.  May be null if none
 240.231 +     *                          of the messages require localization.
 240.232 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 240.233 +     *             no corresponding resource can be found.
 240.234 +     */
 240.235 +    protected Logger(String name, String resourceBundleName) {
 240.236 +        this.name = name;
 240.237 +        levelValue = Level.INFO.intValue();
 240.238 +    }
 240.239 +
 240.240 +    // This constructor is used only to create the global Logger.
 240.241 +    // It is needed to break a cyclic dependence between the LogManager
 240.242 +    // and Logger static initializers causing deadlocks.
 240.243 +    private Logger(String name) {
 240.244 +        // The manager field is not initialized here.
 240.245 +        this.name = name;
 240.246 +        levelValue = Level.INFO.intValue();
 240.247 +    }
 240.248 +
 240.249 +    private void checkAccess() throws SecurityException {
 240.250 +        throw new SecurityException();
 240.251 +    }
 240.252 +
 240.253 +    /**
 240.254 +     * Find or create a logger for a named subsystem.  If a logger has
 240.255 +     * already been created with the given name it is returned.  Otherwise
 240.256 +     * a new logger is created.
 240.257 +     * <p>
 240.258 +     * If a new logger is created its log level will be configured
 240.259 +     * based on the LogManager configuration and it will configured
 240.260 +     * to also send logging output to its parent's Handlers.  It will
 240.261 +     * be registered in the LogManager global namespace.
 240.262 +     * <p>
 240.263 +     * Note: The LogManager may only retain a weak reference to the newly
 240.264 +     * created Logger. It is important to understand that a previously
 240.265 +     * created Logger with the given name may be garbage collected at any
 240.266 +     * time if there is no strong reference to the Logger. In particular,
 240.267 +     * this means that two back-to-back calls like
 240.268 +     * {@code getLogger("MyLogger").log(...)} may use different Logger
 240.269 +     * objects named "MyLogger" if there is no strong reference to the
 240.270 +     * Logger named "MyLogger" elsewhere in the program.
 240.271 +     *
 240.272 +     * @param   name            A name for the logger.  This should
 240.273 +     *                          be a dot-separated name and should normally
 240.274 +     *                          be based on the package name or class name
 240.275 +     *                          of the subsystem, such as java.net
 240.276 +     *                          or javax.swing
 240.277 +     * @return a suitable Logger
 240.278 +     * @throws NullPointerException if the name is null.
 240.279 +     */
 240.280 +
 240.281 +    // Synchronization is not required here. All synchronization for
 240.282 +    // adding a new Logger object is handled by LogManager.addLogger().
 240.283 +    public static Logger getLogger(String name) {
 240.284 +        return getLogger(name, null);
 240.285 +    }
 240.286 +
 240.287 +    /**
 240.288 +     * Find or create a logger for a named subsystem.  If a logger has
 240.289 +     * already been created with the given name it is returned.  Otherwise
 240.290 +     * a new logger is created.
 240.291 +     * <p>
 240.292 +     * If a new logger is created its log level will be configured
 240.293 +     * based on the LogManager and it will configured to also send logging
 240.294 +     * output to its parent's Handlers.  It will be registered in
 240.295 +     * the LogManager global namespace.
 240.296 +     * <p>
 240.297 +     * Note: The LogManager may only retain a weak reference to the newly
 240.298 +     * created Logger. It is important to understand that a previously
 240.299 +     * created Logger with the given name may be garbage collected at any
 240.300 +     * time if there is no strong reference to the Logger. In particular,
 240.301 +     * this means that two back-to-back calls like
 240.302 +     * {@code getLogger("MyLogger", ...).log(...)} may use different Logger
 240.303 +     * objects named "MyLogger" if there is no strong reference to the
 240.304 +     * Logger named "MyLogger" elsewhere in the program.
 240.305 +     * <p>
 240.306 +     * If the named Logger already exists and does not yet have a
 240.307 +     * localization resource bundle then the given resource bundle
 240.308 +     * name is used.  If the named Logger already exists and has
 240.309 +     * a different resource bundle name then an IllegalArgumentException
 240.310 +     * is thrown.
 240.311 +     * <p>
 240.312 +     * @param   name    A name for the logger.  This should
 240.313 +     *                          be a dot-separated name and should normally
 240.314 +     *                          be based on the package name or class name
 240.315 +     *                          of the subsystem, such as java.net
 240.316 +     *                          or javax.swing
 240.317 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 240.318 +     *                          messages for this logger. May be <CODE>null</CODE> if none of
 240.319 +     *                          the messages require localization.
 240.320 +     * @return a suitable Logger
 240.321 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 240.322 +     *             no corresponding resource can be found.
 240.323 +     * @throws IllegalArgumentException if the Logger already exists and uses
 240.324 +     *             a different resource bundle name.
 240.325 +     * @throws NullPointerException if the name is null.
 240.326 +     */
 240.327 +
 240.328 +    // Synchronization is not required here. All synchronization for
 240.329 +    // adding a new Logger object is handled by LogManager.addLogger().
 240.330 +    public static Logger getLogger(String name, String resourceBundleName) {
 240.331 +        Logger l = ALL.get(name);
 240.332 +        if (l == null) {
 240.333 +            l = new Logger(name, resourceBundleName);
 240.334 +            ALL.put(name, l);
 240.335 +        }
 240.336 +        return l;
 240.337 +    }
 240.338 +
 240.339 +
 240.340 +    /**
 240.341 +     * Create an anonymous Logger.  The newly created Logger is not
 240.342 +     * registered in the LogManager namespace.  There will be no
 240.343 +     * access checks on updates to the logger.
 240.344 +     * <p>
 240.345 +     * This factory method is primarily intended for use from applets.
 240.346 +     * Because the resulting Logger is anonymous it can be kept private
 240.347 +     * by the creating class.  This removes the need for normal security
 240.348 +     * checks, which in turn allows untrusted applet code to update
 240.349 +     * the control state of the Logger.  For example an applet can do
 240.350 +     * a setLevel or an addHandler on an anonymous Logger.
 240.351 +     * <p>
 240.352 +     * Even although the new logger is anonymous, it is configured
 240.353 +     * to have the root logger ("") as its parent.  This means that
 240.354 +     * by default it inherits its effective level and handlers
 240.355 +     * from the root logger.
 240.356 +     * <p>
 240.357 +     *
 240.358 +     * @return a newly created private Logger
 240.359 +     */
 240.360 +    public static Logger getAnonymousLogger() {
 240.361 +        return getAnonymousLogger(null);
 240.362 +    }
 240.363 +
 240.364 +    /**
 240.365 +     * Create an anonymous Logger.  The newly created Logger is not
 240.366 +     * registered in the LogManager namespace.  There will be no
 240.367 +     * access checks on updates to the logger.
 240.368 +     * <p>
 240.369 +     * This factory method is primarily intended for use from applets.
 240.370 +     * Because the resulting Logger is anonymous it can be kept private
 240.371 +     * by the creating class.  This removes the need for normal security
 240.372 +     * checks, which in turn allows untrusted applet code to update
 240.373 +     * the control state of the Logger.  For example an applet can do
 240.374 +     * a setLevel or an addHandler on an anonymous Logger.
 240.375 +     * <p>
 240.376 +     * Even although the new logger is anonymous, it is configured
 240.377 +     * to have the root logger ("") as its parent.  This means that
 240.378 +     * by default it inherits its effective level and handlers
 240.379 +     * from the root logger.
 240.380 +     * <p>
 240.381 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 240.382 +     *                          messages for this logger.
 240.383 +     *          May be null if none of the messages require localization.
 240.384 +     * @return a newly created private Logger
 240.385 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 240.386 +     *             no corresponding resource can be found.
 240.387 +     */
 240.388 +
 240.389 +    // Synchronization is not required here. All synchronization for
 240.390 +    // adding a new anonymous Logger object is handled by doSetParent().
 240.391 +    public static Logger getAnonymousLogger(String resourceBundleName) {
 240.392 +        return new Logger(null, resourceBundleName);
 240.393 +    }
 240.394 +
 240.395 +    /**
 240.396 +     * Retrieve the localization resource bundle for this
 240.397 +     * logger for the current default locale.  Note that if
 240.398 +     * the result is null, then the Logger will use a resource
 240.399 +     * bundle inherited from its parent.
 240.400 +     *
 240.401 +     * @return localization bundle (may be null)
 240.402 +     */
 240.403 +//    public ResourceBundle getResourceBundle() {
 240.404 +//        return findResourceBundle(getResourceBundleName());
 240.405 +//    }
 240.406 +
 240.407 +    /**
 240.408 +     * Retrieve the localization resource bundle name for this
 240.409 +     * logger.  Note that if the result is null, then the Logger
 240.410 +     * will use a resource bundle name inherited from its parent.
 240.411 +     *
 240.412 +     * @return localization bundle name (may be null)
 240.413 +     */
 240.414 +    public String getResourceBundleName() {
 240.415 +        return null;
 240.416 +    }
 240.417 +
 240.418 +    /**
 240.419 +     * Set a filter to control output on this Logger.
 240.420 +     * <P>
 240.421 +     * After passing the initial "level" check, the Logger will
 240.422 +     * call this Filter to check if a log record should really
 240.423 +     * be published.
 240.424 +     *
 240.425 +     * @param   newFilter  a filter object (may be null)
 240.426 +     * @exception  SecurityException  if a security manager exists and if
 240.427 +     *             the caller does not have LoggingPermission("control").
 240.428 +     */
 240.429 +//    public void setFilter(Filter newFilter) throws SecurityException {
 240.430 +//        checkAccess();
 240.431 +//    }
 240.432 +
 240.433 +    /**
 240.434 +     * Get the current filter for this Logger.
 240.435 +     *
 240.436 +     * @return  a filter object (may be null)
 240.437 +     */
 240.438 +//    public Filter getFilter() {
 240.439 +//        return filter;
 240.440 +//    }
 240.441 +
 240.442 +    /**
 240.443 +     * Log a LogRecord.
 240.444 +     * <p>
 240.445 +     * All the other logging methods in this class call through
 240.446 +     * this method to actually perform any logging.  Subclasses can
 240.447 +     * override this single method to capture all log activity.
 240.448 +     *
 240.449 +     * @param record the LogRecord to be published
 240.450 +     */
 240.451 +    public void log(LogRecord record) {
 240.452 +        if (record.getLevel().intValue() < levelValue) {
 240.453 +            return;
 240.454 +        }
 240.455 +        
 240.456 +        String method;
 240.457 +        switch (record.getLevel().toString()) {
 240.458 +            case "INFO": method = "info";  break;
 240.459 +            case "SEVERE": method = "error"; break;
 240.460 +            case "WARNING": method = "warn"; break;
 240.461 +            default: method = "log"; break;
 240.462 +        }
 240.463 +        
 240.464 +        String msg = record.getMessage();
 240.465 +        final Object[] params = record.getParameters();
 240.466 +        if (params != null && params.length != 0) {
 240.467 +            for (int i = 0; i < params.length; i++) {
 240.468 +                msg = msg.replace("{" + i + "}", params[i] == null ? "null" : params[i].toString());
 240.469 +            }
 240.470 +        }
 240.471 +
 240.472 +        consoleLog(
 240.473 +            method, 
 240.474 +            record.getLoggerName(), msg);
 240.475 +    }
 240.476 +    
 240.477 +    @JavaScriptBody(args = { "method", "logger", "msg" }, body = 
 240.478 +        "if (typeof console !== 'undefined') console[method]('[' + logger + ']: ' + msg);"
 240.479 +    )
 240.480 +    private static native void consoleLog(
 240.481 +        String method, String logger, String msg
 240.482 +    );
 240.483 +
 240.484 +    // private support method for logging.
 240.485 +    // We fill in the logger name, resource bundle name, and
 240.486 +    // resource bundle and then call "void log(LogRecord)".
 240.487 +    private void doLog(LogRecord lr) {
 240.488 +        doLog(lr, lr.getResourceBundleName());
 240.489 +    }
 240.490 +    private void doLog(LogRecord lr, String bundleName) {
 240.491 +        lr.setLoggerName(name);
 240.492 +        log(lr);
 240.493 +    }
 240.494 +
 240.495 +
 240.496 +    //================================================================
 240.497 +    // Start of convenience methods WITHOUT className and methodName
 240.498 +    //================================================================
 240.499 +
 240.500 +    /**
 240.501 +     * Log a message, with no arguments.
 240.502 +     * <p>
 240.503 +     * If the logger is currently enabled for the given message
 240.504 +     * level then the given message is forwarded to all the
 240.505 +     * registered output Handler objects.
 240.506 +     * <p>
 240.507 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.508 +     * @param   msg     The string message (or a key in the message catalog)
 240.509 +     */
 240.510 +    public void log(Level level, String msg) {
 240.511 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.512 +            return;
 240.513 +        }
 240.514 +        LogRecord lr = new LogRecord(level, msg);
 240.515 +        doLog(lr);
 240.516 +    }
 240.517 +
 240.518 +    /**
 240.519 +     * Log a message, with one object parameter.
 240.520 +     * <p>
 240.521 +     * If the logger is currently enabled for the given message
 240.522 +     * level then a corresponding LogRecord is created and forwarded
 240.523 +     * to all the registered output Handler objects.
 240.524 +     * <p>
 240.525 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.526 +     * @param   msg     The string message (or a key in the message catalog)
 240.527 +     * @param   param1  parameter to the message
 240.528 +     */
 240.529 +    public void log(Level level, String msg, Object param1) {
 240.530 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.531 +            return;
 240.532 +        }
 240.533 +        LogRecord lr = new LogRecord(level, msg);
 240.534 +        Object params[] = { param1 };
 240.535 +        lr.setParameters(params);
 240.536 +        doLog(lr);
 240.537 +    }
 240.538 +
 240.539 +    /**
 240.540 +     * Log a message, with an array of object arguments.
 240.541 +     * <p>
 240.542 +     * If the logger is currently enabled for the given message
 240.543 +     * level then a corresponding LogRecord is created and forwarded
 240.544 +     * to all the registered output Handler objects.
 240.545 +     * <p>
 240.546 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.547 +     * @param   msg     The string message (or a key in the message catalog)
 240.548 +     * @param   params  array of parameters to the message
 240.549 +     */
 240.550 +    public void log(Level level, String msg, Object params[]) {
 240.551 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.552 +            return;
 240.553 +        }
 240.554 +        LogRecord lr = new LogRecord(level, msg);
 240.555 +        lr.setParameters(params);
 240.556 +        doLog(lr);
 240.557 +    }
 240.558 +
 240.559 +    /**
 240.560 +     * Log a message, with associated Throwable information.
 240.561 +     * <p>
 240.562 +     * If the logger is currently enabled for the given message
 240.563 +     * level then the given arguments are stored in a LogRecord
 240.564 +     * which is forwarded to all registered output handlers.
 240.565 +     * <p>
 240.566 +     * Note that the thrown argument is stored in the LogRecord thrown
 240.567 +     * property, rather than the LogRecord parameters property.  Thus is it
 240.568 +     * processed specially by output Formatters and is not treated
 240.569 +     * as a formatting parameter to the LogRecord message property.
 240.570 +     * <p>
 240.571 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.572 +     * @param   msg     The string message (or a key in the message catalog)
 240.573 +     * @param   thrown  Throwable associated with log message.
 240.574 +     */
 240.575 +    public void log(Level level, String msg, Throwable thrown) {
 240.576 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.577 +            return;
 240.578 +        }
 240.579 +        LogRecord lr = new LogRecord(level, msg);
 240.580 +        lr.setThrown(thrown);
 240.581 +        doLog(lr);
 240.582 +    }
 240.583 +
 240.584 +    //================================================================
 240.585 +    // Start of convenience methods WITH className and methodName
 240.586 +    //================================================================
 240.587 +
 240.588 +    /**
 240.589 +     * Log a message, specifying source class and method,
 240.590 +     * with no arguments.
 240.591 +     * <p>
 240.592 +     * If the logger is currently enabled for the given message
 240.593 +     * level then the given message is forwarded to all the
 240.594 +     * registered output Handler objects.
 240.595 +     * <p>
 240.596 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.597 +     * @param   sourceClass    name of class that issued the logging request
 240.598 +     * @param   sourceMethod   name of method that issued the logging request
 240.599 +     * @param   msg     The string message (or a key in the message catalog)
 240.600 +     */
 240.601 +    public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
 240.602 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.603 +            return;
 240.604 +        }
 240.605 +        LogRecord lr = new LogRecord(level, msg);
 240.606 +        lr.setSourceClassName(sourceClass);
 240.607 +        lr.setSourceMethodName(sourceMethod);
 240.608 +        doLog(lr);
 240.609 +    }
 240.610 +
 240.611 +    /**
 240.612 +     * Log a message, specifying source class and method,
 240.613 +     * with a single object parameter to the log message.
 240.614 +     * <p>
 240.615 +     * If the logger is currently enabled for the given message
 240.616 +     * level then a corresponding LogRecord is created and forwarded
 240.617 +     * to all the registered output Handler objects.
 240.618 +     * <p>
 240.619 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.620 +     * @param   sourceClass    name of class that issued the logging request
 240.621 +     * @param   sourceMethod   name of method that issued the logging request
 240.622 +     * @param   msg      The string message (or a key in the message catalog)
 240.623 +     * @param   param1    Parameter to the log message.
 240.624 +     */
 240.625 +    public void logp(Level level, String sourceClass, String sourceMethod,
 240.626 +                                                String msg, Object param1) {
 240.627 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.628 +            return;
 240.629 +        }
 240.630 +        LogRecord lr = new LogRecord(level, msg);
 240.631 +        lr.setSourceClassName(sourceClass);
 240.632 +        lr.setSourceMethodName(sourceMethod);
 240.633 +        Object params[] = { param1 };
 240.634 +        lr.setParameters(params);
 240.635 +        doLog(lr);
 240.636 +    }
 240.637 +
 240.638 +    /**
 240.639 +     * Log a message, specifying source class and method,
 240.640 +     * with an array of object arguments.
 240.641 +     * <p>
 240.642 +     * If the logger is currently enabled for the given message
 240.643 +     * level then a corresponding LogRecord is created and forwarded
 240.644 +     * to all the registered output Handler objects.
 240.645 +     * <p>
 240.646 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.647 +     * @param   sourceClass    name of class that issued the logging request
 240.648 +     * @param   sourceMethod   name of method that issued the logging request
 240.649 +     * @param   msg     The string message (or a key in the message catalog)
 240.650 +     * @param   params  Array of parameters to the message
 240.651 +     */
 240.652 +    public void logp(Level level, String sourceClass, String sourceMethod,
 240.653 +                                                String msg, Object params[]) {
 240.654 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.655 +            return;
 240.656 +        }
 240.657 +        LogRecord lr = new LogRecord(level, msg);
 240.658 +        lr.setSourceClassName(sourceClass);
 240.659 +        lr.setSourceMethodName(sourceMethod);
 240.660 +        lr.setParameters(params);
 240.661 +        doLog(lr);
 240.662 +    }
 240.663 +
 240.664 +    /**
 240.665 +     * Log a message, specifying source class and method,
 240.666 +     * with associated Throwable information.
 240.667 +     * <p>
 240.668 +     * If the logger is currently enabled for the given message
 240.669 +     * level then the given arguments are stored in a LogRecord
 240.670 +     * which is forwarded to all registered output handlers.
 240.671 +     * <p>
 240.672 +     * Note that the thrown argument is stored in the LogRecord thrown
 240.673 +     * property, rather than the LogRecord parameters property.  Thus is it
 240.674 +     * processed specially by output Formatters and is not treated
 240.675 +     * as a formatting parameter to the LogRecord message property.
 240.676 +     * <p>
 240.677 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.678 +     * @param   sourceClass    name of class that issued the logging request
 240.679 +     * @param   sourceMethod   name of method that issued the logging request
 240.680 +     * @param   msg     The string message (or a key in the message catalog)
 240.681 +     * @param   thrown  Throwable associated with log message.
 240.682 +     */
 240.683 +    public void logp(Level level, String sourceClass, String sourceMethod,
 240.684 +                                                        String msg, Throwable thrown) {
 240.685 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.686 +            return;
 240.687 +        }
 240.688 +        LogRecord lr = new LogRecord(level, msg);
 240.689 +        lr.setSourceClassName(sourceClass);
 240.690 +        lr.setSourceMethodName(sourceMethod);
 240.691 +        lr.setThrown(thrown);
 240.692 +        doLog(lr);
 240.693 +    }
 240.694 +
 240.695 +
 240.696 +    //=========================================================================
 240.697 +    // Start of convenience methods WITH className, methodName and bundle name.
 240.698 +    //=========================================================================
 240.699 +
 240.700 +
 240.701 +    /**
 240.702 +     * Log a message, specifying source class, method, and resource bundle name
 240.703 +     * with no arguments.
 240.704 +     * <p>
 240.705 +     * If the logger is currently enabled for the given message
 240.706 +     * level then the given message is forwarded to all the
 240.707 +     * registered output Handler objects.
 240.708 +     * <p>
 240.709 +     * The msg string is localized using the named resource bundle.  If the
 240.710 +     * resource bundle name is null, or an empty String or invalid
 240.711 +     * then the msg string is not localized.
 240.712 +     * <p>
 240.713 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.714 +     * @param   sourceClass    name of class that issued the logging request
 240.715 +     * @param   sourceMethod   name of method that issued the logging request
 240.716 +     * @param   bundleName     name of resource bundle to localize msg,
 240.717 +     *                         can be null
 240.718 +     * @param   msg     The string message (or a key in the message catalog)
 240.719 +     */
 240.720 +
 240.721 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 240.722 +                                String bundleName, String msg) {
 240.723 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.724 +            return;
 240.725 +        }
 240.726 +        LogRecord lr = new LogRecord(level, msg);
 240.727 +        lr.setSourceClassName(sourceClass);
 240.728 +        lr.setSourceMethodName(sourceMethod);
 240.729 +        doLog(lr, bundleName);
 240.730 +    }
 240.731 +
 240.732 +    /**
 240.733 +     * Log a message, specifying source class, method, and resource bundle name,
 240.734 +     * with a single object parameter to the log message.
 240.735 +     * <p>
 240.736 +     * If the logger is currently enabled for the given message
 240.737 +     * level then a corresponding LogRecord is created and forwarded
 240.738 +     * to all the registered output Handler objects.
 240.739 +     * <p>
 240.740 +     * The msg string is localized using the named resource bundle.  If the
 240.741 +     * resource bundle name is null, or an empty String or invalid
 240.742 +     * then the msg string is not localized.
 240.743 +     * <p>
 240.744 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.745 +     * @param   sourceClass    name of class that issued the logging request
 240.746 +     * @param   sourceMethod   name of method that issued the logging request
 240.747 +     * @param   bundleName     name of resource bundle to localize msg,
 240.748 +     *                         can be null
 240.749 +     * @param   msg      The string message (or a key in the message catalog)
 240.750 +     * @param   param1    Parameter to the log message.
 240.751 +     */
 240.752 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 240.753 +                                String bundleName, String msg, Object param1) {
 240.754 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.755 +            return;
 240.756 +        }
 240.757 +        LogRecord lr = new LogRecord(level, msg);
 240.758 +        lr.setSourceClassName(sourceClass);
 240.759 +        lr.setSourceMethodName(sourceMethod);
 240.760 +        Object params[] = { param1 };
 240.761 +        lr.setParameters(params);
 240.762 +        doLog(lr, bundleName);
 240.763 +    }
 240.764 +
 240.765 +    /**
 240.766 +     * Log a message, specifying source class, method, and resource bundle name,
 240.767 +     * with an array of object arguments.
 240.768 +     * <p>
 240.769 +     * If the logger is currently enabled for the given message
 240.770 +     * level then a corresponding LogRecord is created and forwarded
 240.771 +     * to all the registered output Handler objects.
 240.772 +     * <p>
 240.773 +     * The msg string is localized using the named resource bundle.  If the
 240.774 +     * resource bundle name is null, or an empty String or invalid
 240.775 +     * then the msg string is not localized.
 240.776 +     * <p>
 240.777 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.778 +     * @param   sourceClass    name of class that issued the logging request
 240.779 +     * @param   sourceMethod   name of method that issued the logging request
 240.780 +     * @param   bundleName     name of resource bundle to localize msg,
 240.781 +     *                         can be null.
 240.782 +     * @param   msg     The string message (or a key in the message catalog)
 240.783 +     * @param   params  Array of parameters to the message
 240.784 +     */
 240.785 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 240.786 +                                String bundleName, String msg, Object params[]) {
 240.787 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.788 +            return;
 240.789 +        }
 240.790 +        LogRecord lr = new LogRecord(level, msg);
 240.791 +        lr.setSourceClassName(sourceClass);
 240.792 +        lr.setSourceMethodName(sourceMethod);
 240.793 +        lr.setParameters(params);
 240.794 +        doLog(lr, bundleName);
 240.795 +    }
 240.796 +
 240.797 +    /**
 240.798 +     * Log a message, specifying source class, method, and resource bundle name,
 240.799 +     * with associated Throwable information.
 240.800 +     * <p>
 240.801 +     * If the logger is currently enabled for the given message
 240.802 +     * level then the given arguments are stored in a LogRecord
 240.803 +     * which is forwarded to all registered output handlers.
 240.804 +     * <p>
 240.805 +     * The msg string is localized using the named resource bundle.  If the
 240.806 +     * resource bundle name is null, or an empty String or invalid
 240.807 +     * then the msg string is not localized.
 240.808 +     * <p>
 240.809 +     * Note that the thrown argument is stored in the LogRecord thrown
 240.810 +     * property, rather than the LogRecord parameters property.  Thus is it
 240.811 +     * processed specially by output Formatters and is not treated
 240.812 +     * as a formatting parameter to the LogRecord message property.
 240.813 +     * <p>
 240.814 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 240.815 +     * @param   sourceClass    name of class that issued the logging request
 240.816 +     * @param   sourceMethod   name of method that issued the logging request
 240.817 +     * @param   bundleName     name of resource bundle to localize msg,
 240.818 +     *                         can be null
 240.819 +     * @param   msg     The string message (or a key in the message catalog)
 240.820 +     * @param   thrown  Throwable associated with log message.
 240.821 +     */
 240.822 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 240.823 +                                        String bundleName, String msg, Throwable thrown) {
 240.824 +        if (level.intValue() < levelValue || levelValue == offValue) {
 240.825 +            return;
 240.826 +        }
 240.827 +        LogRecord lr = new LogRecord(level, msg);
 240.828 +        lr.setSourceClassName(sourceClass);
 240.829 +        lr.setSourceMethodName(sourceMethod);
 240.830 +        lr.setThrown(thrown);
 240.831 +        doLog(lr, bundleName);
 240.832 +    }
 240.833 +
 240.834 +
 240.835 +    //======================================================================
 240.836 +    // Start of convenience methods for logging method entries and returns.
 240.837 +    //======================================================================
 240.838 +
 240.839 +    /**
 240.840 +     * Log a method entry.
 240.841 +     * <p>
 240.842 +     * This is a convenience method that can be used to log entry
 240.843 +     * to a method.  A LogRecord with message "ENTRY", log level
 240.844 +     * FINER, and the given sourceMethod and sourceClass is logged.
 240.845 +     * <p>
 240.846 +     * @param   sourceClass    name of class that issued the logging request
 240.847 +     * @param   sourceMethod   name of method that is being entered
 240.848 +     */
 240.849 +    public void entering(String sourceClass, String sourceMethod) {
 240.850 +        if (Level.FINER.intValue() < levelValue) {
 240.851 +            return;
 240.852 +        }
 240.853 +        logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
 240.854 +    }
 240.855 +
 240.856 +    /**
 240.857 +     * Log a method entry, with one parameter.
 240.858 +     * <p>
 240.859 +     * This is a convenience method that can be used to log entry
 240.860 +     * to a method.  A LogRecord with message "ENTRY {0}", log level
 240.861 +     * FINER, and the given sourceMethod, sourceClass, and parameter
 240.862 +     * is logged.
 240.863 +     * <p>
 240.864 +     * @param   sourceClass    name of class that issued the logging request
 240.865 +     * @param   sourceMethod   name of method that is being entered
 240.866 +     * @param   param1         parameter to the method being entered
 240.867 +     */
 240.868 +    public void entering(String sourceClass, String sourceMethod, Object param1) {
 240.869 +        if (Level.FINER.intValue() < levelValue) {
 240.870 +            return;
 240.871 +        }
 240.872 +        Object params[] = { param1 };
 240.873 +        logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
 240.874 +    }
 240.875 +
 240.876 +    /**
 240.877 +     * Log a method entry, with an array of parameters.
 240.878 +     * <p>
 240.879 +     * This is a convenience method that can be used to log entry
 240.880 +     * to a method.  A LogRecord with message "ENTRY" (followed by a
 240.881 +     * format {N} indicator for each entry in the parameter array),
 240.882 +     * log level FINER, and the given sourceMethod, sourceClass, and
 240.883 +     * parameters is logged.
 240.884 +     * <p>
 240.885 +     * @param   sourceClass    name of class that issued the logging request
 240.886 +     * @param   sourceMethod   name of method that is being entered
 240.887 +     * @param   params         array of parameters to the method being entered
 240.888 +     */
 240.889 +    public void entering(String sourceClass, String sourceMethod, Object params[]) {
 240.890 +        if (Level.FINER.intValue() < levelValue) {
 240.891 +            return;
 240.892 +        }
 240.893 +        String msg = "ENTRY";
 240.894 +        if (params == null ) {
 240.895 +           logp(Level.FINER, sourceClass, sourceMethod, msg);
 240.896 +           return;
 240.897 +        }
 240.898 +        for (int i = 0; i < params.length; i++) {
 240.899 +            msg = msg + " {" + i + "}";
 240.900 +        }
 240.901 +        logp(Level.FINER, sourceClass, sourceMethod, msg, params);
 240.902 +    }
 240.903 +
 240.904 +    /**
 240.905 +     * Log a method return.
 240.906 +     * <p>
 240.907 +     * This is a convenience method that can be used to log returning
 240.908 +     * from a method.  A LogRecord with message "RETURN", log level
 240.909 +     * FINER, and the given sourceMethod and sourceClass is logged.
 240.910 +     * <p>
 240.911 +     * @param   sourceClass    name of class that issued the logging request
 240.912 +     * @param   sourceMethod   name of the method
 240.913 +     */
 240.914 +    public void exiting(String sourceClass, String sourceMethod) {
 240.915 +        if (Level.FINER.intValue() < levelValue) {
 240.916 +            return;
 240.917 +        }
 240.918 +        logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
 240.919 +    }
 240.920 +
 240.921 +
 240.922 +    /**
 240.923 +     * Log a method return, with result object.
 240.924 +     * <p>
 240.925 +     * This is a convenience method that can be used to log returning
 240.926 +     * from a method.  A LogRecord with message "RETURN {0}", log level
 240.927 +     * FINER, and the gives sourceMethod, sourceClass, and result
 240.928 +     * object is logged.
 240.929 +     * <p>
 240.930 +     * @param   sourceClass    name of class that issued the logging request
 240.931 +     * @param   sourceMethod   name of the method
 240.932 +     * @param   result  Object that is being returned
 240.933 +     */
 240.934 +    public void exiting(String sourceClass, String sourceMethod, Object result) {
 240.935 +        if (Level.FINER.intValue() < levelValue) {
 240.936 +            return;
 240.937 +        }
 240.938 +        Object params[] = { result };
 240.939 +        logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
 240.940 +    }
 240.941 +
 240.942 +    /**
 240.943 +     * Log throwing an exception.
 240.944 +     * <p>
 240.945 +     * This is a convenience method to log that a method is
 240.946 +     * terminating by throwing an exception.  The logging is done
 240.947 +     * using the FINER level.
 240.948 +     * <p>
 240.949 +     * If the logger is currently enabled for the given message
 240.950 +     * level then the given arguments are stored in a LogRecord
 240.951 +     * which is forwarded to all registered output handlers.  The
 240.952 +     * LogRecord's message is set to "THROW".
 240.953 +     * <p>
 240.954 +     * Note that the thrown argument is stored in the LogRecord thrown
 240.955 +     * property, rather than the LogRecord parameters property.  Thus is it
 240.956 +     * processed specially by output Formatters and is not treated
 240.957 +     * as a formatting parameter to the LogRecord message property.
 240.958 +     * <p>
 240.959 +     * @param   sourceClass    name of class that issued the logging request
 240.960 +     * @param   sourceMethod  name of the method.
 240.961 +     * @param   thrown  The Throwable that is being thrown.
 240.962 +     */
 240.963 +    public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
 240.964 +        if (Level.FINER.intValue() < levelValue || levelValue == offValue ) {
 240.965 +            return;
 240.966 +        }
 240.967 +        LogRecord lr = new LogRecord(Level.FINER, "THROW");
 240.968 +        lr.setSourceClassName(sourceClass);
 240.969 +        lr.setSourceMethodName(sourceMethod);
 240.970 +        lr.setThrown(thrown);
 240.971 +        doLog(lr);
 240.972 +    }
 240.973 +
 240.974 +    //=======================================================================
 240.975 +    // Start of simple convenience methods using level names as method names
 240.976 +    //=======================================================================
 240.977 +
 240.978 +    /**
 240.979 +     * Log a SEVERE message.
 240.980 +     * <p>
 240.981 +     * If the logger is currently enabled for the SEVERE message
 240.982 +     * level then the given message is forwarded to all the
 240.983 +     * registered output Handler objects.
 240.984 +     * <p>
 240.985 +     * @param   msg     The string message (or a key in the message catalog)
 240.986 +     */
 240.987 +    public void severe(String msg) {
 240.988 +        if (Level.SEVERE.intValue() < levelValue) {
 240.989 +            return;
 240.990 +        }
 240.991 +        log(Level.SEVERE, msg);
 240.992 +    }
 240.993 +
 240.994 +    /**
 240.995 +     * Log a WARNING message.
 240.996 +     * <p>
 240.997 +     * If the logger is currently enabled for the WARNING message
 240.998 +     * level then the given message is forwarded to all the
 240.999 +     * registered output Handler objects.
240.1000 +     * <p>
240.1001 +     * @param   msg     The string message (or a key in the message catalog)
240.1002 +     */
240.1003 +    public void warning(String msg) {
240.1004 +        if (Level.WARNING.intValue() < levelValue) {
240.1005 +            return;
240.1006 +        }
240.1007 +        log(Level.WARNING, msg);
240.1008 +    }
240.1009 +
240.1010 +    /**
240.1011 +     * Log an INFO message.
240.1012 +     * <p>
240.1013 +     * If the logger is currently enabled for the INFO message
240.1014 +     * level then the given message is forwarded to all the
240.1015 +     * registered output Handler objects.
240.1016 +     * <p>
240.1017 +     * @param   msg     The string message (or a key in the message catalog)
240.1018 +     */
240.1019 +    public void info(String msg) {
240.1020 +        if (Level.INFO.intValue() < levelValue) {
240.1021 +            return;
240.1022 +        }
240.1023 +        log(Level.INFO, msg);
240.1024 +    }
240.1025 +
240.1026 +    /**
240.1027 +     * Log a CONFIG message.
240.1028 +     * <p>
240.1029 +     * If the logger is currently enabled for the CONFIG message
240.1030 +     * level then the given message is forwarded to all the
240.1031 +     * registered output Handler objects.
240.1032 +     * <p>
240.1033 +     * @param   msg     The string message (or a key in the message catalog)
240.1034 +     */
240.1035 +    public void config(String msg) {
240.1036 +        if (Level.CONFIG.intValue() < levelValue) {
240.1037 +            return;
240.1038 +        }
240.1039 +        log(Level.CONFIG, msg);
240.1040 +    }
240.1041 +
240.1042 +    /**
240.1043 +     * Log a FINE message.
240.1044 +     * <p>
240.1045 +     * If the logger is currently enabled for the FINE message
240.1046 +     * level then the given message is forwarded to all the
240.1047 +     * registered output Handler objects.
240.1048 +     * <p>
240.1049 +     * @param   msg     The string message (or a key in the message catalog)
240.1050 +     */
240.1051 +    public void fine(String msg) {
240.1052 +        if (Level.FINE.intValue() < levelValue) {
240.1053 +            return;
240.1054 +        }
240.1055 +        log(Level.FINE, msg);
240.1056 +    }
240.1057 +
240.1058 +    /**
240.1059 +     * Log a FINER message.
240.1060 +     * <p>
240.1061 +     * If the logger is currently enabled for the FINER message
240.1062 +     * level then the given message is forwarded to all the
240.1063 +     * registered output Handler objects.
240.1064 +     * <p>
240.1065 +     * @param   msg     The string message (or a key in the message catalog)
240.1066 +     */
240.1067 +    public void finer(String msg) {
240.1068 +        if (Level.FINER.intValue() < levelValue) {
240.1069 +            return;
240.1070 +        }
240.1071 +        log(Level.FINER, msg);
240.1072 +    }
240.1073 +
240.1074 +    /**
240.1075 +     * Log a FINEST message.
240.1076 +     * <p>
240.1077 +     * If the logger is currently enabled for the FINEST message
240.1078 +     * level then the given message is forwarded to all the
240.1079 +     * registered output Handler objects.
240.1080 +     * <p>
240.1081 +     * @param   msg     The string message (or a key in the message catalog)
240.1082 +     */
240.1083 +    public void finest(String msg) {
240.1084 +        if (Level.FINEST.intValue() < levelValue) {
240.1085 +            return;
240.1086 +        }
240.1087 +        log(Level.FINEST, msg);
240.1088 +    }
240.1089 +
240.1090 +    //================================================================
240.1091 +    // End of convenience methods
240.1092 +    //================================================================
240.1093 +
240.1094 +    /**
240.1095 +     * Set the log level specifying which message levels will be
240.1096 +     * logged by this logger.  Message levels lower than this
240.1097 +     * value will be discarded.  The level value Level.OFF
240.1098 +     * can be used to turn off logging.
240.1099 +     * <p>
240.1100 +     * If the new level is null, it means that this node should
240.1101 +     * inherit its level from its nearest ancestor with a specific
240.1102 +     * (non-null) level value.
240.1103 +     *
240.1104 +     * @param newLevel   the new value for the log level (may be null)
240.1105 +     * @exception  SecurityException  if a security manager exists and if
240.1106 +     *             the caller does not have LoggingPermission("control").
240.1107 +     */
240.1108 +    public void setLevel(Level newLevel) throws SecurityException {
240.1109 +        levelValue = newLevel.intValue();
240.1110 +        levelObject = newLevel;
240.1111 +    }
240.1112 +
240.1113 +    /**
240.1114 +     * Get the log Level that has been specified for this Logger.
240.1115 +     * The result may be null, which means that this logger's
240.1116 +     * effective level will be inherited from its parent.
240.1117 +     *
240.1118 +     * @return  this Logger's level
240.1119 +     */
240.1120 +    public Level getLevel() {
240.1121 +        return levelObject;
240.1122 +    }
240.1123 +
240.1124 +    /**
240.1125 +     * Check if a message of the given level would actually be logged
240.1126 +     * by this logger.  This check is based on the Loggers effective level,
240.1127 +     * which may be inherited from its parent.
240.1128 +     *
240.1129 +     * @param   level   a message logging level
240.1130 +     * @return  true if the given message level is currently being logged.
240.1131 +     */
240.1132 +    public boolean isLoggable(Level level) {
240.1133 +        if (level.intValue() < levelValue || levelValue == offValue) {
240.1134 +            return false;
240.1135 +        }
240.1136 +        return true;
240.1137 +    }
240.1138 +
240.1139 +    /**
240.1140 +     * Get the name for this logger.
240.1141 +     * @return logger name.  Will be null for anonymous Loggers.
240.1142 +     */
240.1143 +    public String getName() {
240.1144 +        return name;
240.1145 +    }
240.1146 +
240.1147 +    /**
240.1148 +     * Add a log Handler to receive logging messages.
240.1149 +     * <p>
240.1150 +     * By default, Loggers also send their output to their parent logger.
240.1151 +     * Typically the root Logger is configured with a set of Handlers
240.1152 +     * that essentially act as default handlers for all loggers.
240.1153 +     *
240.1154 +     * @param   handler a logging Handler
240.1155 +     * @exception  SecurityException  if a security manager exists and if
240.1156 +     *             the caller does not have LoggingPermission("control").
240.1157 +     */
240.1158 +//    public void addHandler(Handler handler) throws SecurityException {
240.1159 +//        // Check for null handler
240.1160 +//        handler.getClass();
240.1161 +//        checkAccess();
240.1162 +//        handlers.add(handler);
240.1163 +//    }
240.1164 +
240.1165 +    /**
240.1166 +     * Remove a log Handler.
240.1167 +     * <P>
240.1168 +     * Returns silently if the given Handler is not found or is null
240.1169 +     *
240.1170 +     * @param   handler a logging Handler
240.1171 +     * @exception  SecurityException  if a security manager exists and if
240.1172 +     *             the caller does not have LoggingPermission("control").
240.1173 +     */
240.1174 +//    public void removeHandler(Handler handler) throws SecurityException {
240.1175 +//        checkAccess();
240.1176 +//        if (handler == null) {
240.1177 +//            return;
240.1178 +//        }
240.1179 +//        handlers.remove(handler);
240.1180 +//    }
240.1181 +
240.1182 +    /**
240.1183 +     * Get the Handlers associated with this logger.
240.1184 +     * <p>
240.1185 +     * @return  an array of all registered Handlers
240.1186 +     */
240.1187 +//    public Handler[] getHandlers() {
240.1188 +//        return handlers.toArray(emptyHandlers);
240.1189 +//    }
240.1190 +
240.1191 +    /**
240.1192 +     * Specify whether or not this logger should send its output
240.1193 +     * to its parent Logger.  This means that any LogRecords will
240.1194 +     * also be written to the parent's Handlers, and potentially
240.1195 +     * to its parent, recursively up the namespace.
240.1196 +     *
240.1197 +     * @param useParentHandlers   true if output is to be sent to the
240.1198 +     *          logger's parent.
240.1199 +     * @exception  SecurityException  if a security manager exists and if
240.1200 +     *             the caller does not have LoggingPermission("control").
240.1201 +     */
240.1202 +    public void setUseParentHandlers(boolean useParentHandlers) {
240.1203 +        checkAccess();
240.1204 +    }
240.1205 +
240.1206 +    /**
240.1207 +     * Discover whether or not this logger is sending its output
240.1208 +     * to its parent logger.
240.1209 +     *
240.1210 +     * @return  true if output is to be sent to the logger's parent
240.1211 +     */
240.1212 +    public boolean getUseParentHandlers() {
240.1213 +        return true;
240.1214 +    }
240.1215 +
240.1216 +    /**
240.1217 +     * Return the parent for this Logger.
240.1218 +     * <p>
240.1219 +     * This method returns the nearest extant parent in the namespace.
240.1220 +     * Thus if a Logger is called "a.b.c.d", and a Logger called "a.b"
240.1221 +     * has been created but no logger "a.b.c" exists, then a call of
240.1222 +     * getParent on the Logger "a.b.c.d" will return the Logger "a.b".
240.1223 +     * <p>
240.1224 +     * The result will be null if it is called on the root Logger
240.1225 +     * in the namespace.
240.1226 +     *
240.1227 +     * @return nearest existing parent Logger
240.1228 +     */
240.1229 +    public Logger getParent() {
240.1230 +        // Note: this used to be synchronized on treeLock.  However, this only
240.1231 +        // provided memory semantics, as there was no guarantee that the caller
240.1232 +        // would synchronize on treeLock (in fact, there is no way for external
240.1233 +        // callers to so synchronize).  Therefore, we have made parent volatile
240.1234 +        // instead.
240.1235 +        String n = getName();
240.1236 +        int at = n.length();
240.1237 +        for (;;) {
240.1238 +            int last = n.lastIndexOf('.', at - 1);
240.1239 +            if (last == -1) {
240.1240 +                return getGlobal();
240.1241 +            }
240.1242 +            Logger p = ALL.get(n.substring(0, last));
240.1243 +            if (p != null) {
240.1244 +                return p;
240.1245 +            }
240.1246 +            at = last;
240.1247 +        }
240.1248 +    }
240.1249 +
240.1250 +    /**
240.1251 +     * Set the parent for this Logger.  This method is used by
240.1252 +     * the LogManager to update a Logger when the namespace changes.
240.1253 +     * <p>
240.1254 +     * It should not be called from application code.
240.1255 +     * <p>
240.1256 +     * @param  parent   the new parent logger
240.1257 +     * @exception  SecurityException  if a security manager exists and if
240.1258 +     *             the caller does not have LoggingPermission("control").
240.1259 +     */
240.1260 +    public void setParent(Logger parent) {
240.1261 +        if (parent == null) {
240.1262 +            throw new NullPointerException();
240.1263 +        }
240.1264 +        checkAccess();
240.1265 +    }
240.1266 +
240.1267 +}
   241.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   241.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/ASCII.java	Wed Apr 30 15:04:10 2014 +0200
   241.3 @@ -0,0 +1,274 @@
   241.4 +/*
   241.5 + * Copyright (c) 1999, 2000, 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 java.util.regex;
  241.30 +
  241.31 +
  241.32 +/**
  241.33 + * Utility class that implements the standard C ctype functionality.
  241.34 + *
  241.35 + * @author Hong Zhang
  241.36 + */
  241.37 +
  241.38 +final class ASCII {
  241.39 +
  241.40 +    static final int UPPER   = 0x00000100;
  241.41 +
  241.42 +    static final int LOWER   = 0x00000200;
  241.43 +
  241.44 +    static final int DIGIT   = 0x00000400;
  241.45 +
  241.46 +    static final int SPACE   = 0x00000800;
  241.47 +
  241.48 +    static final int PUNCT   = 0x00001000;
  241.49 +
  241.50 +    static final int CNTRL   = 0x00002000;
  241.51 +
  241.52 +    static final int BLANK   = 0x00004000;
  241.53 +
  241.54 +    static final int HEX     = 0x00008000;
  241.55 +
  241.56 +    static final int UNDER   = 0x00010000;
  241.57 +
  241.58 +    static final int ASCII   = 0x0000FF00;
  241.59 +
  241.60 +    static final int ALPHA   = (UPPER|LOWER);
  241.61 +
  241.62 +    static final int ALNUM   = (UPPER|LOWER|DIGIT);
  241.63 +
  241.64 +    static final int GRAPH   = (PUNCT|UPPER|LOWER|DIGIT);
  241.65 +
  241.66 +    static final int WORD    = (UPPER|LOWER|UNDER|DIGIT);
  241.67 +
  241.68 +    static final int XDIGIT  = (HEX);
  241.69 +
  241.70 +    private static final int[] ctype = new int[] {
  241.71 +        CNTRL,                  /* 00 (NUL) */
  241.72 +        CNTRL,                  /* 01 (SOH) */
  241.73 +        CNTRL,                  /* 02 (STX) */
  241.74 +        CNTRL,                  /* 03 (ETX) */
  241.75 +        CNTRL,                  /* 04 (EOT) */
  241.76 +        CNTRL,                  /* 05 (ENQ) */
  241.77 +        CNTRL,                  /* 06 (ACK) */
  241.78 +        CNTRL,                  /* 07 (BEL) */
  241.79 +        CNTRL,                  /* 08 (BS)  */
  241.80 +        SPACE+CNTRL+BLANK,      /* 09 (HT)  */
  241.81 +        SPACE+CNTRL,            /* 0A (LF)  */
  241.82 +        SPACE+CNTRL,            /* 0B (VT)  */
  241.83 +        SPACE+CNTRL,            /* 0C (FF)  */
  241.84 +        SPACE+CNTRL,            /* 0D (CR)  */
  241.85 +        CNTRL,                  /* 0E (SI)  */
  241.86 +        CNTRL,                  /* 0F (SO)  */
  241.87 +        CNTRL,                  /* 10 (DLE) */
  241.88 +        CNTRL,                  /* 11 (DC1) */
  241.89 +        CNTRL,                  /* 12 (DC2) */
  241.90 +        CNTRL,                  /* 13 (DC3) */
  241.91 +        CNTRL,                  /* 14 (DC4) */
  241.92 +        CNTRL,                  /* 15 (NAK) */
  241.93 +        CNTRL,                  /* 16 (SYN) */
  241.94 +        CNTRL,                  /* 17 (ETB) */
  241.95 +        CNTRL,                  /* 18 (CAN) */
  241.96 +        CNTRL,                  /* 19 (EM)  */
  241.97 +        CNTRL,                  /* 1A (SUB) */
  241.98 +        CNTRL,                  /* 1B (ESC) */
  241.99 +        CNTRL,                  /* 1C (FS)  */
 241.100 +        CNTRL,                  /* 1D (GS)  */
 241.101 +        CNTRL,                  /* 1E (RS)  */
 241.102 +        CNTRL,                  /* 1F (US)  */
 241.103 +        SPACE+BLANK,            /* 20 SPACE */
 241.104 +        PUNCT,                  /* 21 !     */
 241.105 +        PUNCT,                  /* 22 "     */
 241.106 +        PUNCT,                  /* 23 #     */
 241.107 +        PUNCT,                  /* 24 $     */
 241.108 +        PUNCT,                  /* 25 %     */
 241.109 +        PUNCT,                  /* 26 &     */
 241.110 +        PUNCT,                  /* 27 '     */
 241.111 +        PUNCT,                  /* 28 (     */
 241.112 +        PUNCT,                  /* 29 )     */
 241.113 +        PUNCT,                  /* 2A *     */
 241.114 +        PUNCT,                  /* 2B +     */
 241.115 +        PUNCT,                  /* 2C ,     */
 241.116 +        PUNCT,                  /* 2D -     */
 241.117 +        PUNCT,                  /* 2E .     */
 241.118 +        PUNCT,                  /* 2F /     */
 241.119 +        DIGIT+HEX+0,            /* 30 0     */
 241.120 +        DIGIT+HEX+1,            /* 31 1     */
 241.121 +        DIGIT+HEX+2,            /* 32 2     */
 241.122 +        DIGIT+HEX+3,            /* 33 3     */
 241.123 +        DIGIT+HEX+4,            /* 34 4     */
 241.124 +        DIGIT+HEX+5,            /* 35 5     */
 241.125 +        DIGIT+HEX+6,            /* 36 6     */
 241.126 +        DIGIT+HEX+7,            /* 37 7     */
 241.127 +        DIGIT+HEX+8,            /* 38 8     */
 241.128 +        DIGIT+HEX+9,            /* 39 9     */
 241.129 +        PUNCT,                  /* 3A :     */
 241.130 +        PUNCT,                  /* 3B ;     */
 241.131 +        PUNCT,                  /* 3C <     */
 241.132 +        PUNCT,                  /* 3D =     */
 241.133 +        PUNCT,                  /* 3E >     */
 241.134 +        PUNCT,                  /* 3F ?     */
 241.135 +        PUNCT,                  /* 40 @     */
 241.136 +        UPPER+HEX+10,           /* 41 A     */
 241.137 +        UPPER+HEX+11,           /* 42 B     */
 241.138 +        UPPER+HEX+12,           /* 43 C     */
 241.139 +        UPPER+HEX+13,           /* 44 D     */
 241.140 +        UPPER+HEX+14,           /* 45 E     */
 241.141 +        UPPER+HEX+15,           /* 46 F     */
 241.142 +        UPPER+16,               /* 47 G     */
 241.143 +        UPPER+17,               /* 48 H     */
 241.144 +        UPPER+18,               /* 49 I     */
 241.145 +        UPPER+19,               /* 4A J     */
 241.146 +        UPPER+20,               /* 4B K     */
 241.147 +        UPPER+21,               /* 4C L     */
 241.148 +        UPPER+22,               /* 4D M     */
 241.149 +        UPPER+23,               /* 4E N     */
 241.150 +        UPPER+24,               /* 4F O     */
 241.151 +        UPPER+25,               /* 50 P     */
 241.152 +        UPPER+26,               /* 51 Q     */
 241.153 +        UPPER+27,               /* 52 R     */
 241.154 +        UPPER+28,               /* 53 S     */
 241.155 +        UPPER+29,               /* 54 T     */
 241.156 +        UPPER+30,               /* 55 U     */
 241.157 +        UPPER+31,               /* 56 V     */
 241.158 +        UPPER+32,               /* 57 W     */
 241.159 +        UPPER+33,               /* 58 X     */
 241.160 +        UPPER+34,               /* 59 Y     */
 241.161 +        UPPER+35,               /* 5A Z     */
 241.162 +        PUNCT,                  /* 5B [     */
 241.163 +        PUNCT,                  /* 5C \     */
 241.164 +        PUNCT,                  /* 5D ]     */
 241.165 +        PUNCT,                  /* 5E ^     */
 241.166 +        PUNCT|UNDER,            /* 5F _     */
 241.167 +        PUNCT,                  /* 60 `     */
 241.168 +        LOWER+HEX+10,           /* 61 a     */
 241.169 +        LOWER+HEX+11,           /* 62 b     */
 241.170 +        LOWER+HEX+12,           /* 63 c     */
 241.171 +        LOWER+HEX+13,           /* 64 d     */
 241.172 +        LOWER+HEX+14,           /* 65 e     */
 241.173 +        LOWER+HEX+15,           /* 66 f     */
 241.174 +        LOWER+16,               /* 67 g     */
 241.175 +        LOWER+17,               /* 68 h     */
 241.176 +        LOWER+18,               /* 69 i     */
 241.177 +        LOWER+19,               /* 6A j     */
 241.178 +        LOWER+20,               /* 6B k     */
 241.179 +        LOWER+21,               /* 6C l     */
 241.180 +        LOWER+22,               /* 6D m     */
 241.181 +        LOWER+23,               /* 6E n     */
 241.182 +        LOWER+24,               /* 6F o     */
 241.183 +        LOWER+25,               /* 70 p     */
 241.184 +        LOWER+26,               /* 71 q     */
 241.185 +        LOWER+27,               /* 72 r     */
 241.186 +        LOWER+28,               /* 73 s     */
 241.187 +        LOWER+29,               /* 74 t     */
 241.188 +        LOWER+30,               /* 75 u     */
 241.189 +        LOWER+31,               /* 76 v     */
 241.190 +        LOWER+32,               /* 77 w     */
 241.191 +        LOWER+33,               /* 78 x     */
 241.192 +        LOWER+34,               /* 79 y     */
 241.193 +        LOWER+35,               /* 7A z     */
 241.194 +        PUNCT,                  /* 7B {     */
 241.195 +        PUNCT,                  /* 7C |     */
 241.196 +        PUNCT,                  /* 7D }     */
 241.197 +        PUNCT,                  /* 7E ~     */
 241.198 +        CNTRL,                  /* 7F (DEL) */
 241.199 +    };
 241.200 +
 241.201 +    static int getType(int ch) {
 241.202 +        return ((ch & 0xFFFFFF80) == 0 ? ctype[ch] : 0);
 241.203 +    }
 241.204 +
 241.205 +    static boolean isType(int ch, int type) {
 241.206 +        return (getType(ch) & type) != 0;
 241.207 +    }
 241.208 +
 241.209 +    static boolean isAscii(int ch) {
 241.210 +        return ((ch & 0xFFFFFF80) == 0);
 241.211 +    }
 241.212 +
 241.213 +    static boolean isAlpha(int ch) {
 241.214 +        return isType(ch, ALPHA);
 241.215 +    }
 241.216 +
 241.217 +    static boolean isDigit(int ch) {
 241.218 +        return ((ch-'0')|('9'-ch)) >= 0;
 241.219 +    }
 241.220 +
 241.221 +    static boolean isAlnum(int ch) {
 241.222 +        return isType(ch, ALNUM);
 241.223 +    }
 241.224 +
 241.225 +    static boolean isGraph(int ch) {
 241.226 +        return isType(ch, GRAPH);
 241.227 +    }
 241.228 +
 241.229 +    static boolean isPrint(int ch) {
 241.230 +        return ((ch-0x20)|(0x7E-ch)) >= 0;
 241.231 +    }
 241.232 +
 241.233 +    static boolean isPunct(int ch) {
 241.234 +        return isType(ch, PUNCT);
 241.235 +    }
 241.236 +
 241.237 +    static boolean isSpace(int ch) {
 241.238 +        return isType(ch, SPACE);
 241.239 +    }
 241.240 +
 241.241 +    static boolean isHexDigit(int ch) {
 241.242 +        return isType(ch, HEX);
 241.243 +    }
 241.244 +
 241.245 +    static boolean isOctDigit(int ch) {
 241.246 +        return ((ch-'0')|('7'-ch)) >= 0;
 241.247 +    }
 241.248 +
 241.249 +    static boolean isCntrl(int ch) {
 241.250 +        return isType(ch, CNTRL);
 241.251 +    }
 241.252 +
 241.253 +    static boolean isLower(int ch) {
 241.254 +        return ((ch-'a')|('z'-ch)) >= 0;
 241.255 +    }
 241.256 +
 241.257 +    static boolean isUpper(int ch) {
 241.258 +        return ((ch-'A')|('Z'-ch)) >= 0;
 241.259 +    }
 241.260 +
 241.261 +    static boolean isWord(int ch) {
 241.262 +        return isType(ch, WORD);
 241.263 +    }
 241.264 +
 241.265 +    static int toDigit(int ch) {
 241.266 +        return (ctype[ch & 0x7F] & 0x3F);
 241.267 +    }
 241.268 +
 241.269 +    static int toLower(int ch) {
 241.270 +        return isUpper(ch) ? (ch + 0x20) : ch;
 241.271 +    }
 241.272 +
 241.273 +    static int toUpper(int ch) {
 241.274 +        return isLower(ch) ? (ch - 0x20) : ch;
 241.275 +    }
 241.276 +
 241.277 +}
   242.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   242.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/MatchResult.java	Wed Apr 30 15:04:10 2014 +0200
   242.3 @@ -0,0 +1,188 @@
   242.4 +/*
   242.5 + * Copyright (c) 2003, 2004, 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 +package java.util.regex;
  242.30 +
  242.31 +/**
  242.32 + * The result of a match operation.
  242.33 + *
  242.34 + * <p>This interface contains query methods used to determine the
  242.35 + * results of a match against a regular expression. The match boundaries,
  242.36 + * groups and group boundaries can be seen but not modified through
  242.37 + * a <code>MatchResult</code>.
  242.38 + *
  242.39 + * @author  Michael McCloskey
  242.40 + * @see Matcher
  242.41 + * @since 1.5
  242.42 + */
  242.43 +public interface MatchResult {
  242.44 +
  242.45 +    /**
  242.46 +     * Returns the start index of the match.
  242.47 +     *
  242.48 +     * @return  The index of the first character matched
  242.49 +     *
  242.50 +     * @throws  IllegalStateException
  242.51 +     *          If no match has yet been attempted,
  242.52 +     *          or if the previous match operation failed
  242.53 +     */
  242.54 +    public int start();
  242.55 +
  242.56 +    /**
  242.57 +     * Returns the start index of the subsequence captured by the given group
  242.58 +     * during this match.
  242.59 +     *
  242.60 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
  242.61 +     * to right, starting at one.  Group zero denotes the entire pattern, so
  242.62 +     * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
  242.63 +     * <i>m.</i><tt>start()</tt>.  </p>
  242.64 +     *
  242.65 +     * @param  group
  242.66 +     *         The index of a capturing group in this matcher's pattern
  242.67 +     *
  242.68 +     * @return  The index of the first character captured by the group,
  242.69 +     *          or <tt>-1</tt> if the match was successful but the group
  242.70 +     *          itself did not match anything
  242.71 +     *
  242.72 +     * @throws  IllegalStateException
  242.73 +     *          If no match has yet been attempted,
  242.74 +     *          or if the previous match operation failed
  242.75 +     *
  242.76 +     * @throws  IndexOutOfBoundsException
  242.77 +     *          If there is no capturing group in the pattern
  242.78 +     *          with the given index
  242.79 +     */
  242.80 +    public int start(int group);
  242.81 +
  242.82 +    /**
  242.83 +     * Returns the offset after the last character matched.  </p>
  242.84 +     *
  242.85 +     * @return  @return  The offset after the last character matched
  242.86 +     *
  242.87 +     * @throws  IllegalStateException
  242.88 +     *          If no match has yet been attempted,
  242.89 +     *          or if the previous match operation failed
  242.90 +     */
  242.91 +    public int end();
  242.92 +
  242.93 +    /**
  242.94 +     * Returns the offset after the last character of the subsequence
  242.95 +     * captured by the given group during this match.
  242.96 +     *
  242.97 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
  242.98 +     * to right, starting at one.  Group zero denotes the entire pattern, so
  242.99 +     * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
 242.100 +     * <i>m.</i><tt>end()</tt>.  </p>
 242.101 +     *
 242.102 +     * @param  group
 242.103 +     *         The index of a capturing group in this matcher's pattern
 242.104 +     *
 242.105 +     * @return  The offset after the last character captured by the group,
 242.106 +     *          or <tt>-1</tt> if the match was successful
 242.107 +     *          but the group itself did not match anything
 242.108 +     *
 242.109 +     * @throws  IllegalStateException
 242.110 +     *          If no match has yet been attempted,
 242.111 +     *          or if the previous match operation failed
 242.112 +     *
 242.113 +     * @throws  IndexOutOfBoundsException
 242.114 +     *          If there is no capturing group in the pattern
 242.115 +     *          with the given index
 242.116 +     */
 242.117 +    public int end(int group);
 242.118 +
 242.119 +    /**
 242.120 +     * Returns the input subsequence matched by the previous match.
 242.121 +     *
 242.122 +     * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
 242.123 +     * the expressions <i>m.</i><tt>group()</tt> and
 242.124 +     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt>&nbsp;<i>m.</i><tt>end())</tt>
 242.125 +     * are equivalent.  </p>
 242.126 +     *
 242.127 +     * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
 242.128 +     * string.  This method will return the empty string when the pattern
 242.129 +     * successfully matches the empty string in the input.  </p>
 242.130 +     *
 242.131 +     * @return The (possibly empty) subsequence matched by the previous match,
 242.132 +     *         in string form
 242.133 +     *
 242.134 +     * @throws  IllegalStateException
 242.135 +     *          If no match has yet been attempted,
 242.136 +     *          or if the previous match operation failed
 242.137 +     */
 242.138 +    public String group();
 242.139 +
 242.140 +    /**
 242.141 +     * Returns the input subsequence captured by the given group during the
 242.142 +     * previous match operation.
 242.143 +     *
 242.144 +     * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
 242.145 +     * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
 242.146 +     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt>&nbsp;<i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
 242.147 +     * are equivalent.  </p>
 242.148 +     *
 242.149 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
 242.150 +     * to right, starting at one.  Group zero denotes the entire pattern, so
 242.151 +     * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
 242.152 +     * </p>
 242.153 +     *
 242.154 +     * <p> If the match was successful but the group specified failed to match
 242.155 +     * any part of the input sequence, then <tt>null</tt> is returned. Note
 242.156 +     * that some groups, for example <tt>(a*)</tt>, match the empty string.
 242.157 +     * This method will return the empty string when such a group successfully
 242.158 +     * matches the empty string in the input.  </p>
 242.159 +     *
 242.160 +     * @param  group
 242.161 +     *         The index of a capturing group in this matcher's pattern
 242.162 +     *
 242.163 +     * @return  The (possibly empty) subsequence captured by the group
 242.164 +     *          during the previous match, or <tt>null</tt> if the group
 242.165 +     *          failed to match part of the input
 242.166 +     *
 242.167 +     * @throws  IllegalStateException
 242.168 +     *          If no match has yet been attempted,
 242.169 +     *          or if the previous match operation failed
 242.170 +     *
 242.171 +     * @throws  IndexOutOfBoundsException
 242.172 +     *          If there is no capturing group in the pattern
 242.173 +     *          with the given index
 242.174 +     */
 242.175 +    public String group(int group);
 242.176 +
 242.177 +    /**
 242.178 +     * Returns the number of capturing groups in this match result's pattern.
 242.179 +     *
 242.180 +     * <p> Group zero denotes the entire pattern by convention. It is not
 242.181 +     * included in this count.
 242.182 +     *
 242.183 +     * <p> Any non-negative integer smaller than or equal to the value
 242.184 +     * returned by this method is guaranteed to be a valid group index for
 242.185 +     * this matcher.  </p>
 242.186 +     *
 242.187 +     * @return The number of capturing groups in this matcher's pattern
 242.188 +     */
 242.189 +    public int groupCount();
 242.190 +
 242.191 +}
   243.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   243.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/Matcher.java	Wed Apr 30 15:04:10 2014 +0200
   243.3 @@ -0,0 +1,1256 @@
   243.4 +/*
   243.5 + * Copyright (c) 1999, 2009, 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 +package java.util.regex;
  243.30 +
  243.31 +
  243.32 +/**
  243.33 + * An engine that performs match operations on a {@link java.lang.CharSequence
  243.34 + * </code>character sequence<code>} by interpreting a {@link Pattern}.
  243.35 + *
  243.36 + * <p> A matcher is created from a pattern by invoking the pattern's {@link
  243.37 + * Pattern#matcher matcher} method.  Once created, a matcher can be used to
  243.38 + * perform three different kinds of match operations:
  243.39 + *
  243.40 + * <ul>
  243.41 + *
  243.42 + *   <li><p> The {@link #matches matches} method attempts to match the entire
  243.43 + *   input sequence against the pattern.  </p></li>
  243.44 + *
  243.45 + *   <li><p> The {@link #lookingAt lookingAt} method attempts to match the
  243.46 + *   input sequence, starting at the beginning, against the pattern.  </p></li>
  243.47 + *
  243.48 + *   <li><p> The {@link #find find} method scans the input sequence looking for
  243.49 + *   the next subsequence that matches the pattern.  </p></li>
  243.50 + *
  243.51 + * </ul>
  243.52 + *
  243.53 + * <p> Each of these methods returns a boolean indicating success or failure.
  243.54 + * More information about a successful match can be obtained by querying the
  243.55 + * state of the matcher.
  243.56 + *
  243.57 + * <p> A matcher finds matches in a subset of its input called the
  243.58 + * <i>region</i>. By default, the region contains all of the matcher's input.
  243.59 + * The region can be modified via the{@link #region region} method and queried
  243.60 + * via the {@link #regionStart regionStart} and {@link #regionEnd regionEnd}
  243.61 + * methods. The way that the region boundaries interact with some pattern
  243.62 + * constructs can be changed. See {@link #useAnchoringBounds
  243.63 + * useAnchoringBounds} and {@link #useTransparentBounds useTransparentBounds}
  243.64 + * for more details.
  243.65 + *
  243.66 + * <p> This class also defines methods for replacing matched subsequences with
  243.67 + * new strings whose contents can, if desired, be computed from the match
  243.68 + * result.  The {@link #appendReplacement appendReplacement} and {@link
  243.69 + * #appendTail appendTail} methods can be used in tandem in order to collect
  243.70 + * the result into an existing string buffer, or the more convenient {@link
  243.71 + * #replaceAll replaceAll} method can be used to create a string in which every
  243.72 + * matching subsequence in the input sequence is replaced.
  243.73 + *
  243.74 + * <p> The explicit state of a matcher includes the start and end indices of
  243.75 + * the most recent successful match.  It also includes the start and end
  243.76 + * indices of the input subsequence captured by each <a
  243.77 + * href="Pattern.html#cg">capturing group</a> in the pattern as well as a total
  243.78 + * count of such subsequences.  As a convenience, methods are also provided for
  243.79 + * returning these captured subsequences in string form.
  243.80 + *
  243.81 + * <p> The explicit state of a matcher is initially undefined; attempting to
  243.82 + * query any part of it before a successful match will cause an {@link
  243.83 + * IllegalStateException} to be thrown.  The explicit state of a matcher is
  243.84 + * recomputed by every match operation.
  243.85 + *
  243.86 + * <p> The implicit state of a matcher includes the input character sequence as
  243.87 + * well as the <i>append position</i>, which is initially zero and is updated
  243.88 + * by the {@link #appendReplacement appendReplacement} method.
  243.89 + *
  243.90 + * <p> A matcher may be reset explicitly by invoking its {@link #reset()}
  243.91 + * method or, if a new input sequence is desired, its {@link
  243.92 + * #reset(java.lang.CharSequence) reset(CharSequence)} method.  Resetting a
  243.93 + * matcher discards its explicit state information and sets the append position
  243.94 + * to zero.
  243.95 + *
  243.96 + * <p> Instances of this class are not safe for use by multiple concurrent
  243.97 + * threads. </p>
  243.98 + *
  243.99 + *
 243.100 + * @author      Mike McCloskey
 243.101 + * @author      Mark Reinhold
 243.102 + * @author      JSR-51 Expert Group
 243.103 + * @since       1.4
 243.104 + * @spec        JSR-51
 243.105 + */
 243.106 +
 243.107 +public final class Matcher implements MatchResult {
 243.108 +
 243.109 +    /**
 243.110 +     * The Pattern object that created this Matcher.
 243.111 +     */
 243.112 +    Pattern parentPattern;
 243.113 +
 243.114 +    /**
 243.115 +     * The storage used by groups. They may contain invalid values if
 243.116 +     * a group was skipped during the matching.
 243.117 +     */
 243.118 +    int[] groups;
 243.119 +
 243.120 +    /**
 243.121 +     * The range within the sequence that is to be matched. Anchors
 243.122 +     * will match at these "hard" boundaries. Changing the region
 243.123 +     * changes these values.
 243.124 +     */
 243.125 +    int from, to;
 243.126 +
 243.127 +    /**
 243.128 +     * Lookbehind uses this value to ensure that the subexpression
 243.129 +     * match ends at the point where the lookbehind was encountered.
 243.130 +     */
 243.131 +    int lookbehindTo;
 243.132 +
 243.133 +    /**
 243.134 +     * The original string being matched.
 243.135 +     */
 243.136 +    CharSequence text;
 243.137 +
 243.138 +    /**
 243.139 +     * Matcher state used by the last node. NOANCHOR is used when a
 243.140 +     * match does not have to consume all of the input. ENDANCHOR is
 243.141 +     * the mode used for matching all the input.
 243.142 +     */
 243.143 +    static final int ENDANCHOR = 1;
 243.144 +    static final int NOANCHOR = 0;
 243.145 +    int acceptMode = NOANCHOR;
 243.146 +
 243.147 +    /**
 243.148 +     * The range of string that last matched the pattern. If the last
 243.149 +     * match failed then first is -1; last initially holds 0 then it
 243.150 +     * holds the index of the end of the last match (which is where the
 243.151 +     * next search starts).
 243.152 +     */
 243.153 +    int first = -1, last = 0;
 243.154 +
 243.155 +    /**
 243.156 +     * The end index of what matched in the last match operation.
 243.157 +     */
 243.158 +    int oldLast = -1;
 243.159 +
 243.160 +    /**
 243.161 +     * The index of the last position appended in a substitution.
 243.162 +     */
 243.163 +    int lastAppendPosition = 0;
 243.164 +
 243.165 +    /**
 243.166 +     * Storage used by nodes to tell what repetition they are on in
 243.167 +     * a pattern, and where groups begin. The nodes themselves are stateless,
 243.168 +     * so they rely on this field to hold state during a match.
 243.169 +     */
 243.170 +    int[] locals;
 243.171 +
 243.172 +    /**
 243.173 +     * Boolean indicating whether or not more input could change
 243.174 +     * the results of the last match.
 243.175 +     *
 243.176 +     * If hitEnd is true, and a match was found, then more input
 243.177 +     * might cause a different match to be found.
 243.178 +     * If hitEnd is true and a match was not found, then more
 243.179 +     * input could cause a match to be found.
 243.180 +     * If hitEnd is false and a match was found, then more input
 243.181 +     * will not change the match.
 243.182 +     * If hitEnd is false and a match was not found, then more
 243.183 +     * input will not cause a match to be found.
 243.184 +     */
 243.185 +    boolean hitEnd;
 243.186 +
 243.187 +    /**
 243.188 +     * Boolean indicating whether or not more input could change
 243.189 +     * a positive match into a negative one.
 243.190 +     *
 243.191 +     * If requireEnd is true, and a match was found, then more
 243.192 +     * input could cause the match to be lost.
 243.193 +     * If requireEnd is false and a match was found, then more
 243.194 +     * input might change the match but the match won't be lost.
 243.195 +     * If a match was not found, then requireEnd has no meaning.
 243.196 +     */
 243.197 +    boolean requireEnd;
 243.198 +
 243.199 +    /**
 243.200 +     * If transparentBounds is true then the boundaries of this
 243.201 +     * matcher's region are transparent to lookahead, lookbehind,
 243.202 +     * and boundary matching constructs that try to see beyond them.
 243.203 +     */
 243.204 +    boolean transparentBounds = false;
 243.205 +
 243.206 +    /**
 243.207 +     * If anchoringBounds is true then the boundaries of this
 243.208 +     * matcher's region match anchors such as ^ and $.
 243.209 +     */
 243.210 +    boolean anchoringBounds = true;
 243.211 +
 243.212 +    /**
 243.213 +     * No default constructor.
 243.214 +     */
 243.215 +    Matcher() {
 243.216 +    }
 243.217 +
 243.218 +    /**
 243.219 +     * All matchers have the state used by Pattern during a match.
 243.220 +     */
 243.221 +    Matcher(Pattern parent, CharSequence text) {
 243.222 +        this.parentPattern = parent;
 243.223 +        this.text = text;
 243.224 +
 243.225 +        // Allocate state storage
 243.226 +        int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
 243.227 +        groups = new int[parentGroupCount * 2];
 243.228 +        locals = new int[parent.localCount];
 243.229 +
 243.230 +        // Put fields into initial states
 243.231 +        reset();
 243.232 +    }
 243.233 +
 243.234 +    /**
 243.235 +     * Returns the pattern that is interpreted by this matcher.
 243.236 +     *
 243.237 +     * @return  The pattern for which this matcher was created
 243.238 +     */
 243.239 +    public Pattern pattern() {
 243.240 +        return parentPattern;
 243.241 +    }
 243.242 +
 243.243 +    /**
 243.244 +     * Returns the match state of this matcher as a {@link MatchResult}.
 243.245 +     * The result is unaffected by subsequent operations performed upon this
 243.246 +     * matcher.
 243.247 +     *
 243.248 +     * @return  a <code>MatchResult</code> with the state of this matcher
 243.249 +     * @since 1.5
 243.250 +     */
 243.251 +    public MatchResult toMatchResult() {
 243.252 +        Matcher result = new Matcher(this.parentPattern, text.toString());
 243.253 +        result.first = this.first;
 243.254 +        result.last = this.last;
 243.255 +        result.groups = this.groups.clone();
 243.256 +        return result;
 243.257 +    }
 243.258 +
 243.259 +    /**
 243.260 +      * Changes the <tt>Pattern</tt> that this <tt>Matcher</tt> uses to
 243.261 +      * find matches with.
 243.262 +      *
 243.263 +      * <p> This method causes this matcher to lose information
 243.264 +      * about the groups of the last match that occurred. The
 243.265 +      * matcher's position in the input is maintained and its
 243.266 +      * last append position is unaffected.</p>
 243.267 +      *
 243.268 +      * @param  newPattern
 243.269 +      *         The new pattern used by this matcher
 243.270 +      * @return  This matcher
 243.271 +      * @throws  IllegalArgumentException
 243.272 +      *          If newPattern is <tt>null</tt>
 243.273 +      * @since 1.5
 243.274 +      */
 243.275 +    public Matcher usePattern(Pattern newPattern) {
 243.276 +        if (newPattern == null)
 243.277 +            throw new IllegalArgumentException("Pattern cannot be null");
 243.278 +        parentPattern = newPattern;
 243.279 +
 243.280 +        // Reallocate state storage
 243.281 +        int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10);
 243.282 +        groups = new int[parentGroupCount * 2];
 243.283 +        locals = new int[newPattern.localCount];
 243.284 +        for (int i = 0; i < groups.length; i++)
 243.285 +            groups[i] = -1;
 243.286 +        for (int i = 0; i < locals.length; i++)
 243.287 +            locals[i] = -1;
 243.288 +        return this;
 243.289 +    }
 243.290 +
 243.291 +    /**
 243.292 +     * Resets this matcher.
 243.293 +     *
 243.294 +     * <p> Resetting a matcher discards all of its explicit state information
 243.295 +     * and sets its append position to zero. The matcher's region is set to the
 243.296 +     * default region, which is its entire character sequence. The anchoring
 243.297 +     * and transparency of this matcher's region boundaries are unaffected.
 243.298 +     *
 243.299 +     * @return  This matcher
 243.300 +     */
 243.301 +    public Matcher reset() {
 243.302 +        first = -1;
 243.303 +        last = 0;
 243.304 +        oldLast = -1;
 243.305 +        for(int i=0; i<groups.length; i++)
 243.306 +            groups[i] = -1;
 243.307 +        for(int i=0; i<locals.length; i++)
 243.308 +            locals[i] = -1;
 243.309 +        lastAppendPosition = 0;
 243.310 +        from = 0;
 243.311 +        to = getTextLength();
 243.312 +        return this;
 243.313 +    }
 243.314 +
 243.315 +    /**
 243.316 +     * Resets this matcher with a new input sequence.
 243.317 +     *
 243.318 +     * <p> Resetting a matcher discards all of its explicit state information
 243.319 +     * and sets its append position to zero.  The matcher's region is set to
 243.320 +     * the default region, which is its entire character sequence.  The
 243.321 +     * anchoring and transparency of this matcher's region boundaries are
 243.322 +     * unaffected.
 243.323 +     *
 243.324 +     * @param  input
 243.325 +     *         The new input character sequence
 243.326 +     *
 243.327 +     * @return  This matcher
 243.328 +     */
 243.329 +    public Matcher reset(CharSequence input) {
 243.330 +        text = input;
 243.331 +        return reset();
 243.332 +    }
 243.333 +
 243.334 +    /**
 243.335 +     * Returns the start index of the previous match.  </p>
 243.336 +     *
 243.337 +     * @return  The index of the first character matched
 243.338 +     *
 243.339 +     * @throws  IllegalStateException
 243.340 +     *          If no match has yet been attempted,
 243.341 +     *          or if the previous match operation failed
 243.342 +     */
 243.343 +    public int start() {
 243.344 +        if (first < 0)
 243.345 +            throw new IllegalStateException("No match available");
 243.346 +        return first;
 243.347 +    }
 243.348 +
 243.349 +    /**
 243.350 +     * Returns the start index of the subsequence captured by the given group
 243.351 +     * during the previous match operation.
 243.352 +     *
 243.353 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
 243.354 +     * to right, starting at one.  Group zero denotes the entire pattern, so
 243.355 +     * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
 243.356 +     * <i>m.</i><tt>start()</tt>.  </p>
 243.357 +     *
 243.358 +     * @param  group
 243.359 +     *         The index of a capturing group in this matcher's pattern
 243.360 +     *
 243.361 +     * @return  The index of the first character captured by the group,
 243.362 +     *          or <tt>-1</tt> if the match was successful but the group
 243.363 +     *          itself did not match anything
 243.364 +     *
 243.365 +     * @throws  IllegalStateException
 243.366 +     *          If no match has yet been attempted,
 243.367 +     *          or if the previous match operation failed
 243.368 +     *
 243.369 +     * @throws  IndexOutOfBoundsException
 243.370 +     *          If there is no capturing group in the pattern
 243.371 +     *          with the given index
 243.372 +     */
 243.373 +    public int start(int group) {
 243.374 +        if (first < 0)
 243.375 +            throw new IllegalStateException("No match available");
 243.376 +        if (group > groupCount())
 243.377 +            throw new IndexOutOfBoundsException("No group " + group);
 243.378 +        return groups[group * 2];
 243.379 +    }
 243.380 +
 243.381 +    /**
 243.382 +     * Returns the offset after the last character matched.  </p>
 243.383 +     *
 243.384 +     * @return  The offset after the last character matched
 243.385 +     *
 243.386 +     * @throws  IllegalStateException
 243.387 +     *          If no match has yet been attempted,
 243.388 +     *          or if the previous match operation failed
 243.389 +     */
 243.390 +    public int end() {
 243.391 +        if (first < 0)
 243.392 +            throw new IllegalStateException("No match available");
 243.393 +        return last;
 243.394 +    }
 243.395 +
 243.396 +    /**
 243.397 +     * Returns the offset after the last character of the subsequence
 243.398 +     * captured by the given group during the previous match operation.
 243.399 +     *
 243.400 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
 243.401 +     * to right, starting at one.  Group zero denotes the entire pattern, so
 243.402 +     * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
 243.403 +     * <i>m.</i><tt>end()</tt>.  </p>
 243.404 +     *
 243.405 +     * @param  group
 243.406 +     *         The index of a capturing group in this matcher's pattern
 243.407 +     *
 243.408 +     * @return  The offset after the last character captured by the group,
 243.409 +     *          or <tt>-1</tt> if the match was successful
 243.410 +     *          but the group itself did not match anything
 243.411 +     *
 243.412 +     * @throws  IllegalStateException
 243.413 +     *          If no match has yet been attempted,
 243.414 +     *          or if the previous match operation failed
 243.415 +     *
 243.416 +     * @throws  IndexOutOfBoundsException
 243.417 +     *          If there is no capturing group in the pattern
 243.418 +     *          with the given index
 243.419 +     */
 243.420 +    public int end(int group) {
 243.421 +        if (first < 0)
 243.422 +            throw new IllegalStateException("No match available");
 243.423 +        if (group > groupCount())
 243.424 +            throw new IndexOutOfBoundsException("No group " + group);
 243.425 +        return groups[group * 2 + 1];
 243.426 +    }
 243.427 +
 243.428 +    /**
 243.429 +     * Returns the input subsequence matched by the previous match.
 243.430 +     *
 243.431 +     * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
 243.432 +     * the expressions <i>m.</i><tt>group()</tt> and
 243.433 +     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt>&nbsp;<i>m.</i><tt>end())</tt>
 243.434 +     * are equivalent.  </p>
 243.435 +     *
 243.436 +     * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
 243.437 +     * string.  This method will return the empty string when the pattern
 243.438 +     * successfully matches the empty string in the input.  </p>
 243.439 +     *
 243.440 +     * @return The (possibly empty) subsequence matched by the previous match,
 243.441 +     *         in string form
 243.442 +     *
 243.443 +     * @throws  IllegalStateException
 243.444 +     *          If no match has yet been attempted,
 243.445 +     *          or if the previous match operation failed
 243.446 +     */
 243.447 +    public String group() {
 243.448 +        return group(0);
 243.449 +    }
 243.450 +
 243.451 +    /**
 243.452 +     * Returns the input subsequence captured by the given group during the
 243.453 +     * previous match operation.
 243.454 +     *
 243.455 +     * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
 243.456 +     * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
 243.457 +     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt>&nbsp;<i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
 243.458 +     * are equivalent.  </p>
 243.459 +     *
 243.460 +     * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
 243.461 +     * to right, starting at one.  Group zero denotes the entire pattern, so
 243.462 +     * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
 243.463 +     * </p>
 243.464 +     *
 243.465 +     * <p> If the match was successful but the group specified failed to match
 243.466 +     * any part of the input sequence, then <tt>null</tt> is returned. Note
 243.467 +     * that some groups, for example <tt>(a*)</tt>, match the empty string.
 243.468 +     * This method will return the empty string when such a group successfully
 243.469 +     * matches the empty string in the input.  </p>
 243.470 +     *
 243.471 +     * @param  group
 243.472 +     *         The index of a capturing group in this matcher's pattern
 243.473 +     *
 243.474 +     * @return  The (possibly empty) subsequence captured by the group
 243.475 +     *          during the previous match, or <tt>null</tt> if the group
 243.476 +     *          failed to match part of the input
 243.477 +     *
 243.478 +     * @throws  IllegalStateException
 243.479 +     *          If no match has yet been attempted,
 243.480 +     *          or if the previous match operation failed
 243.481 +     *
 243.482 +     * @throws  IndexOutOfBoundsException
 243.483 +     *          If there is no capturing group in the pattern
 243.484 +     *          with the given index
 243.485 +     */
 243.486 +    public String group(int group) {
 243.487 +        if (first < 0)
 243.488 +            throw new IllegalStateException("No match found");
 243.489 +        if (group < 0 || group > groupCount())
 243.490 +            throw new IndexOutOfBoundsException("No group " + group);
 243.491 +        if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
 243.492 +            return null;
 243.493 +        return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
 243.494 +    }
 243.495 +
 243.496 +    /**
 243.497 +     * Returns the input subsequence captured by the given
 243.498 +     * <a href="Pattern.html#groupname">named-capturing group</a> during the previous
 243.499 +     * match operation.
 243.500 +     *
 243.501 +     * <p> If the match was successful but the group specified failed to match
 243.502 +     * any part of the input sequence, then <tt>null</tt> is returned. Note
 243.503 +     * that some groups, for example <tt>(a*)</tt>, match the empty string.
 243.504 +     * This method will return the empty string when such a group successfully
 243.505 +     * matches the empty string in the input.  </p>
 243.506 +     *
 243.507 +     * @param  name
 243.508 +     *         The name of a named-capturing group in this matcher's pattern
 243.509 +     *
 243.510 +     * @return  The (possibly empty) subsequence captured by the named group
 243.511 +     *          during the previous match, or <tt>null</tt> if the group
 243.512 +     *          failed to match part of the input
 243.513 +     *
 243.514 +     * @throws  IllegalStateException
 243.515 +     *          If no match has yet been attempted,
 243.516 +     *          or if the previous match operation failed
 243.517 +     *
 243.518 +     * @throws  IllegalArgumentException
 243.519 +     *          If there is no capturing group in the pattern
 243.520 +     *          with the given name
 243.521 +     */
 243.522 +    public String group(String name) {
 243.523 +        if (name == null)
 243.524 +            throw new NullPointerException("Null group name");
 243.525 +        if (first < 0)
 243.526 +            throw new IllegalStateException("No match found");
 243.527 +        if (!parentPattern.namedGroups().containsKey(name))
 243.528 +            throw new IllegalArgumentException("No group with name <" + name + ">");
 243.529 +        int group = parentPattern.namedGroups().get(name);
 243.530 +        if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
 243.531 +            return null;
 243.532 +        return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
 243.533 +    }
 243.534 +
 243.535 +    /**
 243.536 +     * Returns the number of capturing groups in this matcher's pattern.
 243.537 +     *
 243.538 +     * <p> Group zero denotes the entire pattern by convention. It is not
 243.539 +     * included in this count.
 243.540 +     *
 243.541 +     * <p> Any non-negative integer smaller than or equal to the value
 243.542 +     * returned by this method is guaranteed to be a valid group index for
 243.543 +     * this matcher.  </p>
 243.544 +     *
 243.545 +     * @return The number of capturing groups in this matcher's pattern
 243.546 +     */
 243.547 +    public int groupCount() {
 243.548 +        return parentPattern.capturingGroupCount - 1;
 243.549 +    }
 243.550 +
 243.551 +    /**
 243.552 +     * Attempts to match the entire region against the pattern.
 243.553 +     *
 243.554 +     * <p> If the match succeeds then more information can be obtained via the
 243.555 +     * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods.  </p>
 243.556 +     *
 243.557 +     * @return  <tt>true</tt> if, and only if, the entire region sequence
 243.558 +     *          matches this matcher's pattern
 243.559 +     */
 243.560 +    public boolean matches() {
 243.561 +        return match(from, ENDANCHOR);
 243.562 +    }
 243.563 +
 243.564 +    /**
 243.565 +     * Attempts to find the next subsequence of the input sequence that matches
 243.566 +     * the pattern.
 243.567 +     *
 243.568 +     * <p> This method starts at the beginning of this matcher's region, or, if
 243.569 +     * a previous invocation of the method was successful and the matcher has
 243.570 +     * not since been reset, at the first character not matched by the previous
 243.571 +     * match.
 243.572 +     *
 243.573 +     * <p> If the match succeeds then more information can be obtained via the
 243.574 +     * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods.  </p>
 243.575 +     *
 243.576 +     * @return  <tt>true</tt> if, and only if, a subsequence of the input
 243.577 +     *          sequence matches this matcher's pattern
 243.578 +     */
 243.579 +    public boolean find() {
 243.580 +        int nextSearchIndex = last;
 243.581 +        if (nextSearchIndex == first)
 243.582 +            nextSearchIndex++;
 243.583 +
 243.584 +        // If next search starts before region, start it at region
 243.585 +        if (nextSearchIndex < from)
 243.586 +            nextSearchIndex = from;
 243.587 +
 243.588 +        // If next search starts beyond region then it fails
 243.589 +        if (nextSearchIndex > to) {
 243.590 +            for (int i = 0; i < groups.length; i++)
 243.591 +                groups[i] = -1;
 243.592 +            return false;
 243.593 +        }
 243.594 +        return search(nextSearchIndex);
 243.595 +    }
 243.596 +
 243.597 +    /**
 243.598 +     * Resets this matcher and then attempts to find the next subsequence of
 243.599 +     * the input sequence that matches the pattern, starting at the specified
 243.600 +     * index.
 243.601 +     *
 243.602 +     * <p> If the match succeeds then more information can be obtained via the
 243.603 +     * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods, and subsequent
 243.604 +     * invocations of the {@link #find()} method will start at the first
 243.605 +     * character not matched by this match.  </p>
 243.606 +     *
 243.607 +     * @throws  IndexOutOfBoundsException
 243.608 +     *          If start is less than zero or if start is greater than the
 243.609 +     *          length of the input sequence.
 243.610 +     *
 243.611 +     * @return  <tt>true</tt> if, and only if, a subsequence of the input
 243.612 +     *          sequence starting at the given index matches this matcher's
 243.613 +     *          pattern
 243.614 +     */
 243.615 +    public boolean find(int start) {
 243.616 +        int limit = getTextLength();
 243.617 +        if ((start < 0) || (start > limit))
 243.618 +            throw new IndexOutOfBoundsException("Illegal start index");
 243.619 +        reset();
 243.620 +        return search(start);
 243.621 +    }
 243.622 +
 243.623 +    /**
 243.624 +     * Attempts to match the input sequence, starting at the beginning of the
 243.625 +     * region, against the pattern.
 243.626 +     *
 243.627 +     * <p> Like the {@link #matches matches} method, this method always starts
 243.628 +     * at the beginning of the region; unlike that method, it does not
 243.629 +     * require that the entire region be matched.
 243.630 +     *
 243.631 +     * <p> If the match succeeds then more information can be obtained via the
 243.632 +     * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods.  </p>
 243.633 +     *
 243.634 +     * @return  <tt>true</tt> if, and only if, a prefix of the input
 243.635 +     *          sequence matches this matcher's pattern
 243.636 +     */
 243.637 +    public boolean lookingAt() {
 243.638 +        return match(from, NOANCHOR);
 243.639 +    }
 243.640 +
 243.641 +    /**
 243.642 +     * Returns a literal replacement <code>String</code> for the specified
 243.643 +     * <code>String</code>.
 243.644 +     *
 243.645 +     * This method produces a <code>String</code> that will work
 243.646 +     * as a literal replacement <code>s</code> in the
 243.647 +     * <code>appendReplacement</code> method of the {@link Matcher} class.
 243.648 +     * The <code>String</code> produced will match the sequence of characters
 243.649 +     * in <code>s</code> treated as a literal sequence. Slashes ('\') and
 243.650 +     * dollar signs ('$') will be given no special meaning.
 243.651 +     *
 243.652 +     * @param  s The string to be literalized
 243.653 +     * @return  A literal string replacement
 243.654 +     * @since 1.5
 243.655 +     */
 243.656 +    public static String quoteReplacement(String s) {
 243.657 +        if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
 243.658 +            return s;
 243.659 +        StringBuilder sb = new StringBuilder();
 243.660 +        for (int i=0; i<s.length(); i++) {
 243.661 +            char c = s.charAt(i);
 243.662 +            if (c == '\\' || c == '$') {
 243.663 +                sb.append('\\');
 243.664 +            }
 243.665 +            sb.append(c);
 243.666 +        }
 243.667 +        return sb.toString();
 243.668 +    }
 243.669 +
 243.670 +    /**
 243.671 +     * Implements a non-terminal append-and-replace step.
 243.672 +     *
 243.673 +     * <p> This method performs the following actions: </p>
 243.674 +     *
 243.675 +     * <ol>
 243.676 +     *
 243.677 +     *   <li><p> It reads characters from the input sequence, starting at the
 243.678 +     *   append position, and appends them to the given string buffer.  It
 243.679 +     *   stops after reading the last character preceding the previous match,
 243.680 +     *   that is, the character at index {@link
 243.681 +     *   #start()}&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>.  </p></li>
 243.682 +     *
 243.683 +     *   <li><p> It appends the given replacement string to the string buffer.
 243.684 +     *   </p></li>
 243.685 +     *
 243.686 +     *   <li><p> It sets the append position of this matcher to the index of
 243.687 +     *   the last character matched, plus one, that is, to {@link #end()}.
 243.688 +     *   </p></li>
 243.689 +     *
 243.690 +     * </ol>
 243.691 +     *
 243.692 +     * <p> The replacement string may contain references to subsequences
 243.693 +     * captured during the previous match: Each occurrence of
 243.694 +     * <tt>${</tt><i>name</i><tt>}</tt> or <tt>$</tt><i>g</i>
 243.695 +     * will be replaced by the result of evaluating the corresponding
 243.696 +     * {@link #group(String) group(name)} or {@link #group(int) group(g)</tt>}
 243.697 +     * respectively. For  <tt>$</tt><i>g</i><tt></tt>,
 243.698 +     * the first number after the <tt>$</tt> is always treated as part of
 243.699 +     * the group reference. Subsequent numbers are incorporated into g if
 243.700 +     * they would form a legal group reference. Only the numerals '0'
 243.701 +     * through '9' are considered as potential components of the group
 243.702 +     * reference. If the second group matched the string <tt>"foo"</tt>, for
 243.703 +     * example, then passing the replacement string <tt>"$2bar"</tt> would
 243.704 +     * cause <tt>"foobar"</tt> to be appended to the string buffer. A dollar
 243.705 +     * sign (<tt>$</tt>) may be included as a literal in the replacement
 243.706 +     * string by preceding it with a backslash (<tt>\$</tt>).
 243.707 +     *
 243.708 +     * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
 243.709 +     * the replacement string may cause the results to be different than if it
 243.710 +     * were being treated as a literal replacement string. Dollar signs may be
 243.711 +     * treated as references to captured subsequences as described above, and
 243.712 +     * backslashes are used to escape literal characters in the replacement
 243.713 +     * string.
 243.714 +     *
 243.715 +     * <p> This method is intended to be used in a loop together with the
 243.716 +     * {@link #appendTail appendTail} and {@link #find find} methods.  The
 243.717 +     * following code, for example, writes <tt>one dog two dogs in the
 243.718 +     * yard</tt> to the standard-output stream: </p>
 243.719 +     *
 243.720 +     * <blockquote><pre>
 243.721 +     * Pattern p = Pattern.compile("cat");
 243.722 +     * Matcher m = p.matcher("one cat two cats in the yard");
 243.723 +     * StringBuffer sb = new StringBuffer();
 243.724 +     * while (m.find()) {
 243.725 +     *     m.appendReplacement(sb, "dog");
 243.726 +     * }
 243.727 +     * m.appendTail(sb);
 243.728 +     * System.out.println(sb.toString());</pre></blockquote>
 243.729 +     *
 243.730 +     * @param  sb
 243.731 +     *         The target string buffer
 243.732 +     *
 243.733 +     * @param  replacement
 243.734 +     *         The replacement string
 243.735 +     *
 243.736 +     * @return  This matcher
 243.737 +     *
 243.738 +     * @throws  IllegalStateException
 243.739 +     *          If no match has yet been attempted,
 243.740 +     *          or if the previous match operation failed
 243.741 +     *
 243.742 +     * @throws  IllegalArgumentException
 243.743 +     *          If the replacement string refers to a named-capturing
 243.744 +     *          group that does not exist in the pattern
 243.745 +     *
 243.746 +     * @throws  IndexOutOfBoundsException
 243.747 +     *          If the replacement string refers to a capturing group
 243.748 +     *          that does not exist in the pattern
 243.749 +     */
 243.750 +    public Matcher appendReplacement(StringBuffer sb, String replacement) {
 243.751 +
 243.752 +        // If no match, return error
 243.753 +        if (first < 0)
 243.754 +            throw new IllegalStateException("No match available");
 243.755 +
 243.756 +        // Process substitution string to replace group references with groups
 243.757 +        int cursor = 0;
 243.758 +        StringBuilder result = new StringBuilder();
 243.759 +
 243.760 +        while (cursor < replacement.length()) {
 243.761 +            char nextChar = replacement.charAt(cursor);
 243.762 +            if (nextChar == '\\') {
 243.763 +                cursor++;
 243.764 +                nextChar = replacement.charAt(cursor);
 243.765 +                result.append(nextChar);
 243.766 +                cursor++;
 243.767 +            } else if (nextChar == '$') {
 243.768 +                // Skip past $
 243.769 +                cursor++;
 243.770 +                // A StringIndexOutOfBoundsException is thrown if
 243.771 +                // this "$" is the last character in replacement
 243.772 +                // string in current implementation, a IAE might be
 243.773 +                // more appropriate.
 243.774 +                nextChar = replacement.charAt(cursor);
 243.775 +                int refNum = -1;
 243.776 +                if (nextChar == '{') {
 243.777 +                    cursor++;
 243.778 +                    StringBuilder gsb = new StringBuilder();
 243.779 +                    while (cursor < replacement.length()) {
 243.780 +                        nextChar = replacement.charAt(cursor);
 243.781 +                        if (ASCII.isLower(nextChar) ||
 243.782 +                            ASCII.isUpper(nextChar) ||
 243.783 +                            ASCII.isDigit(nextChar)) {
 243.784 +                            gsb.append(nextChar);
 243.785 +                            cursor++;
 243.786 +                        } else {
 243.787 +                            break;
 243.788 +                        }
 243.789 +                    }
 243.790 +                    if (gsb.length() == 0)
 243.791 +                        throw new IllegalArgumentException(
 243.792 +                            "named capturing group has 0 length name");
 243.793 +                    if (nextChar != '}')
 243.794 +                        throw new IllegalArgumentException(
 243.795 +                            "named capturing group is missing trailing '}'");
 243.796 +                    String gname = gsb.toString();
 243.797 +                    if (ASCII.isDigit(gname.charAt(0)))
 243.798 +                        throw new IllegalArgumentException(
 243.799 +                            "capturing group name {" + gname +
 243.800 +                            "} starts with digit character");
 243.801 +                    if (!parentPattern.namedGroups().containsKey(gname))
 243.802 +                        throw new IllegalArgumentException(
 243.803 +                            "No group with name {" + gname + "}");
 243.804 +                    refNum = parentPattern.namedGroups().get(gname);
 243.805 +                    cursor++;
 243.806 +                } else {
 243.807 +                    // The first number is always a group
 243.808 +                    refNum = (int)nextChar - '0';
 243.809 +                    if ((refNum < 0)||(refNum > 9))
 243.810 +                        throw new IllegalArgumentException(
 243.811 +                            "Illegal group reference");
 243.812 +                    cursor++;
 243.813 +                    // Capture the largest legal group string
 243.814 +                    boolean done = false;
 243.815 +                    while (!done) {
 243.816 +                        if (cursor >= replacement.length()) {
 243.817 +                            break;
 243.818 +                        }
 243.819 +                        int nextDigit = replacement.charAt(cursor) - '0';
 243.820 +                        if ((nextDigit < 0)||(nextDigit > 9)) { // not a number
 243.821 +                            break;
 243.822 +                        }
 243.823 +                        int newRefNum = (refNum * 10) + nextDigit;
 243.824 +                        if (groupCount() < newRefNum) {
 243.825 +                            done = true;
 243.826 +                        } else {
 243.827 +                            refNum = newRefNum;
 243.828 +                            cursor++;
 243.829 +                        }
 243.830 +                    }
 243.831 +                }
 243.832 +                // Append group
 243.833 +                if (start(refNum) != -1 && end(refNum) != -1)
 243.834 +                    result.append(text, start(refNum), end(refNum));
 243.835 +            } else {
 243.836 +                result.append(nextChar);
 243.837 +                cursor++;
 243.838 +            }
 243.839 +        }
 243.840 +        // Append the intervening text
 243.841 +        sb.append(text, lastAppendPosition, first);
 243.842 +        // Append the match substitution
 243.843 +        sb.append(result);
 243.844 +
 243.845 +        lastAppendPosition = last;
 243.846 +        return this;
 243.847 +    }
 243.848 +
 243.849 +    /**
 243.850 +     * Implements a terminal append-and-replace step.
 243.851 +     *
 243.852 +     * <p> This method reads characters from the input sequence, starting at
 243.853 +     * the append position, and appends them to the given string buffer.  It is
 243.854 +     * intended to be invoked after one or more invocations of the {@link
 243.855 +     * #appendReplacement appendReplacement} method in order to copy the
 243.856 +     * remainder of the input sequence.  </p>
 243.857 +     *
 243.858 +     * @param  sb
 243.859 +     *         The target string buffer
 243.860 +     *
 243.861 +     * @return  The target string buffer
 243.862 +     */
 243.863 +    public StringBuffer appendTail(StringBuffer sb) {
 243.864 +        sb.append(text, lastAppendPosition, getTextLength());
 243.865 +        return sb;
 243.866 +    }
 243.867 +
 243.868 +    /**
 243.869 +     * Replaces every subsequence of the input sequence that matches the
 243.870 +     * pattern with the given replacement string.
 243.871 +     *
 243.872 +     * <p> This method first resets this matcher.  It then scans the input
 243.873 +     * sequence looking for matches of the pattern.  Characters that are not
 243.874 +     * part of any match are appended directly to the result string; each match
 243.875 +     * is replaced in the result by the replacement string.  The replacement
 243.876 +     * string may contain references to captured subsequences as in the {@link
 243.877 +     * #appendReplacement appendReplacement} method.
 243.878 +     *
 243.879 +     * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
 243.880 +     * the replacement string may cause the results to be different than if it
 243.881 +     * were being treated as a literal replacement string. Dollar signs may be
 243.882 +     * treated as references to captured subsequences as described above, and
 243.883 +     * backslashes are used to escape literal characters in the replacement
 243.884 +     * string.
 243.885 +     *
 243.886 +     * <p> Given the regular expression <tt>a*b</tt>, the input
 243.887 +     * <tt>"aabfooaabfooabfoob"</tt>, and the replacement string
 243.888 +     * <tt>"-"</tt>, an invocation of this method on a matcher for that
 243.889 +     * expression would yield the string <tt>"-foo-foo-foo-"</tt>.
 243.890 +     *
 243.891 +     * <p> Invoking this method changes this matcher's state.  If the matcher
 243.892 +     * is to be used in further matching operations then it should first be
 243.893 +     * reset.  </p>
 243.894 +     *
 243.895 +     * @param  replacement
 243.896 +     *         The replacement string
 243.897 +     *
 243.898 +     * @return  The string constructed by replacing each matching subsequence
 243.899 +     *          by the replacement string, substituting captured subsequences
 243.900 +     *          as needed
 243.901 +     */
 243.902 +    public String replaceAll(String replacement) {
 243.903 +        reset();
 243.904 +        boolean result = find();
 243.905 +        if (result) {
 243.906 +            StringBuffer sb = new StringBuffer();
 243.907 +            do {
 243.908 +                appendReplacement(sb, replacement);
 243.909 +                result = find();
 243.910 +            } while (result);
 243.911 +            appendTail(sb);
 243.912 +            return sb.toString();
 243.913 +        }
 243.914 +        return text.toString();
 243.915 +    }
 243.916 +
 243.917 +    /**
 243.918 +     * Replaces the first subsequence of the input sequence that matches the
 243.919 +     * pattern with the given replacement string.
 243.920 +     *
 243.921 +     * <p> This method first resets this matcher.  It then scans the input
 243.922 +     * sequence looking for a match of the pattern.  Characters that are not
 243.923 +     * part of the match are appended directly to the result string; the match
 243.924 +     * is replaced in the result by the replacement string.  The replacement
 243.925 +     * string may contain references to captured subsequences as in the {@link
 243.926 +     * #appendReplacement appendReplacement} method.
 243.927 +     *
 243.928 +     * <p>Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
 243.929 +     * the replacement string may cause the results to be different than if it
 243.930 +     * were being treated as a literal replacement string. Dollar signs may be
 243.931 +     * treated as references to captured subsequences as described above, and
 243.932 +     * backslashes are used to escape literal characters in the replacement
 243.933 +     * string.
 243.934 +     *
 243.935 +     * <p> Given the regular expression <tt>dog</tt>, the input
 243.936 +     * <tt>"zzzdogzzzdogzzz"</tt>, and the replacement string
 243.937 +     * <tt>"cat"</tt>, an invocation of this method on a matcher for that
 243.938 +     * expression would yield the string <tt>"zzzcatzzzdogzzz"</tt>.  </p>
 243.939 +     *
 243.940 +     * <p> Invoking this method changes this matcher's state.  If the matcher
 243.941 +     * is to be used in further matching operations then it should first be
 243.942 +     * reset.  </p>
 243.943 +     *
 243.944 +     * @param  replacement
 243.945 +     *         The replacement string
 243.946 +     * @return  The string constructed by replacing the first matching
 243.947 +     *          subsequence by the replacement string, substituting captured
 243.948 +     *          subsequences as needed
 243.949 +     */
 243.950 +    public String replaceFirst(String replacement) {
 243.951 +        if (replacement == null)
 243.952 +            throw new NullPointerException("replacement");
 243.953 +        reset();
 243.954 +        if (!find())
 243.955 +            return text.toString();
 243.956 +        StringBuffer sb = new StringBuffer();
 243.957 +        appendReplacement(sb, replacement);
 243.958 +        appendTail(sb);
 243.959 +        return sb.toString();
 243.960 +    }
 243.961 +
 243.962 +    /**
 243.963 +     * Sets the limits of this matcher's region. The region is the part of the
 243.964 +     * input sequence that will be searched to find a match. Invoking this
 243.965 +     * method resets the matcher, and then sets the region to start at the
 243.966 +     * index specified by the <code>start</code> parameter and end at the
 243.967 +     * index specified by the <code>end</code> parameter.
 243.968 +     *
 243.969 +     * <p>Depending on the transparency and anchoring being used (see
 243.970 +     * {@link #useTransparentBounds useTransparentBounds} and
 243.971 +     * {@link #useAnchoringBounds useAnchoringBounds}), certain constructs such
 243.972 +     * as anchors may behave differently at or around the boundaries of the
 243.973 +     * region.
 243.974 +     *
 243.975 +     * @param  start
 243.976 +     *         The index to start searching at (inclusive)
 243.977 +     * @param  end
 243.978 +     *         The index to end searching at (exclusive)
 243.979 +     * @throws  IndexOutOfBoundsException
 243.980 +     *          If start or end is less than zero, if
 243.981 +     *          start is greater than the length of the input sequence, if
 243.982 +     *          end is greater than the length of the input sequence, or if
 243.983 +     *          start is greater than end.
 243.984 +     * @return  this matcher
 243.985 +     * @since 1.5
 243.986 +     */
 243.987 +    public Matcher region(int start, int end) {
 243.988 +        if ((start < 0) || (start > getTextLength()))
 243.989 +            throw new IndexOutOfBoundsException("start");
 243.990 +        if ((end < 0) || (end > getTextLength()))
 243.991 +            throw new IndexOutOfBoundsException("end");
 243.992 +        if (start > end)
 243.993 +            throw new IndexOutOfBoundsException("start > end");
 243.994 +        reset();
 243.995 +        from = start;
 243.996 +        to = end;
 243.997 +        return this;
 243.998 +    }
 243.999 +
243.1000 +    /**
243.1001 +     * Reports the start index of this matcher's region. The
243.1002 +     * searches this matcher conducts are limited to finding matches
243.1003 +     * within {@link #regionStart regionStart} (inclusive) and
243.1004 +     * {@link #regionEnd regionEnd} (exclusive).
243.1005 +     *
243.1006 +     * @return  The starting point of this matcher's region
243.1007 +     * @since 1.5
243.1008 +     */
243.1009 +    public int regionStart() {
243.1010 +        return from;
243.1011 +    }
243.1012 +
243.1013 +    /**
243.1014 +     * Reports the end index (exclusive) of this matcher's region.
243.1015 +     * The searches this matcher conducts are limited to finding matches
243.1016 +     * within {@link #regionStart regionStart} (inclusive) and
243.1017 +     * {@link #regionEnd regionEnd} (exclusive).
243.1018 +     *
243.1019 +     * @return  the ending point of this matcher's region
243.1020 +     * @since 1.5
243.1021 +     */
243.1022 +    public int regionEnd() {
243.1023 +        return to;
243.1024 +    }
243.1025 +
243.1026 +    /**
243.1027 +     * Queries the transparency of region bounds for this matcher.
243.1028 +     *
243.1029 +     * <p> This method returns <tt>true</tt> if this matcher uses
243.1030 +     * <i>transparent</i> bounds, <tt>false</tt> if it uses <i>opaque</i>
243.1031 +     * bounds.
243.1032 +     *
243.1033 +     * <p> See {@link #useTransparentBounds useTransparentBounds} for a
243.1034 +     * description of transparent and opaque bounds.
243.1035 +     *
243.1036 +     * <p> By default, a matcher uses opaque region boundaries.
243.1037 +     *
243.1038 +     * @return <tt>true</tt> iff this matcher is using transparent bounds,
243.1039 +     *         <tt>false</tt> otherwise.
243.1040 +     * @see java.util.regex.Matcher#useTransparentBounds(boolean)
243.1041 +     * @since 1.5
243.1042 +     */
243.1043 +    public boolean hasTransparentBounds() {
243.1044 +        return transparentBounds;
243.1045 +    }
243.1046 +
243.1047 +    /**
243.1048 +     * Sets the transparency of region bounds for this matcher.
243.1049 +     *
243.1050 +     * <p> Invoking this method with an argument of <tt>true</tt> will set this
243.1051 +     * matcher to use <i>transparent</i> bounds. If the boolean
243.1052 +     * argument is <tt>false</tt>, then <i>opaque</i> bounds will be used.
243.1053 +     *
243.1054 +     * <p> Using transparent bounds, the boundaries of this
243.1055 +     * matcher's region are transparent to lookahead, lookbehind,
243.1056 +     * and boundary matching constructs. Those constructs can see beyond the
243.1057 +     * boundaries of the region to see if a match is appropriate.
243.1058 +     *
243.1059 +     * <p> Using opaque bounds, the boundaries of this matcher's
243.1060 +     * region are opaque to lookahead, lookbehind, and boundary matching
243.1061 +     * constructs that may try to see beyond them. Those constructs cannot
243.1062 +     * look past the boundaries so they will fail to match anything outside
243.1063 +     * of the region.
243.1064 +     *
243.1065 +     * <p> By default, a matcher uses opaque bounds.
243.1066 +     *
243.1067 +     * @param  b a boolean indicating whether to use opaque or transparent
243.1068 +     *         regions
243.1069 +     * @return this matcher
243.1070 +     * @see java.util.regex.Matcher#hasTransparentBounds
243.1071 +     * @since 1.5
243.1072 +     */
243.1073 +    public Matcher useTransparentBounds(boolean b) {
243.1074 +        transparentBounds = b;
243.1075 +        return this;
243.1076 +    }
243.1077 +
243.1078 +    /**
243.1079 +     * Queries the anchoring of region bounds for this matcher.
243.1080 +     *
243.1081 +     * <p> This method returns <tt>true</tt> if this matcher uses
243.1082 +     * <i>anchoring</i> bounds, <tt>false</tt> otherwise.
243.1083 +     *
243.1084 +     * <p> See {@link #useAnchoringBounds useAnchoringBounds} for a
243.1085 +     * description of anchoring bounds.
243.1086 +     *
243.1087 +     * <p> By default, a matcher uses anchoring region boundaries.
243.1088 +     *
243.1089 +     * @return <tt>true</tt> iff this matcher is using anchoring bounds,
243.1090 +     *         <tt>false</tt> otherwise.
243.1091 +     * @see java.util.regex.Matcher#useAnchoringBounds(boolean)
243.1092 +     * @since 1.5
243.1093 +     */
243.1094 +    public boolean hasAnchoringBounds() {
243.1095 +        return anchoringBounds;
243.1096 +    }
243.1097 +
243.1098 +    /**
243.1099 +     * Sets the anchoring of region bounds for this matcher.
243.1100 +     *
243.1101 +     * <p> Invoking this method with an argument of <tt>true</tt> will set this
243.1102 +     * matcher to use <i>anchoring</i> bounds. If the boolean
243.1103 +     * argument is <tt>false</tt>, then <i>non-anchoring</i> bounds will be
243.1104 +     * used.
243.1105 +     *
243.1106 +     * <p> Using anchoring bounds, the boundaries of this
243.1107 +     * matcher's region match anchors such as ^ and $.
243.1108 +     *
243.1109 +     * <p> Without anchoring bounds, the boundaries of this
243.1110 +     * matcher's region will not match anchors such as ^ and $.
243.1111 +     *
243.1112 +     * <p> By default, a matcher uses anchoring region boundaries.
243.1113 +     *
243.1114 +     * @param  b a boolean indicating whether or not to use anchoring bounds.
243.1115 +     * @return this matcher
243.1116 +     * @see java.util.regex.Matcher#hasAnchoringBounds
243.1117 +     * @since 1.5
243.1118 +     */
243.1119 +    public Matcher useAnchoringBounds(boolean b) {
243.1120 +        anchoringBounds = b;
243.1121 +        return this;
243.1122 +    }
243.1123 +
243.1124 +    /**
243.1125 +     * <p>Returns the string representation of this matcher. The
243.1126 +     * string representation of a <code>Matcher</code> contains information
243.1127 +     * that may be useful for debugging. The exact format is unspecified.
243.1128 +     *
243.1129 +     * @return  The string representation of this matcher
243.1130 +     * @since 1.5
243.1131 +     */
243.1132 +    public String toString() {
243.1133 +        StringBuilder sb = new StringBuilder();
243.1134 +        sb.append("java.util.regex.Matcher");
243.1135 +        sb.append("[pattern=" + pattern());
243.1136 +        sb.append(" region=");
243.1137 +        sb.append(regionStart() + "," + regionEnd());
243.1138 +        sb.append(" lastmatch=");
243.1139 +        if ((first >= 0) && (group() != null)) {
243.1140 +            sb.append(group());
243.1141 +        }
243.1142 +        sb.append("]");
243.1143 +        return sb.toString();
243.1144 +    }
243.1145 +
243.1146 +    /**
243.1147 +     * <p>Returns true if the end of input was hit by the search engine in
243.1148 +     * the last match operation performed by this matcher.
243.1149 +     *
243.1150 +     * <p>When this method returns true, then it is possible that more input
243.1151 +     * would have changed the result of the last search.
243.1152 +     *
243.1153 +     * @return  true iff the end of input was hit in the last match; false
243.1154 +     *          otherwise
243.1155 +     * @since 1.5
243.1156 +     */
243.1157 +    public boolean hitEnd() {
243.1158 +        return hitEnd;
243.1159 +    }
243.1160 +
243.1161 +    /**
243.1162 +     * <p>Returns true if more input could change a positive match into a
243.1163 +     * negative one.
243.1164 +     *
243.1165 +     * <p>If this method returns true, and a match was found, then more
243.1166 +     * input could cause the match to be lost. If this method returns false
243.1167 +     * and a match was found, then more input might change the match but the
243.1168 +     * match won't be lost. If a match was not found, then requireEnd has no
243.1169 +     * meaning.
243.1170 +     *
243.1171 +     * @return  true iff more input could change a positive match into a
243.1172 +     *          negative one.
243.1173 +     * @since 1.5
243.1174 +     */
243.1175 +    public boolean requireEnd() {
243.1176 +        return requireEnd;
243.1177 +    }
243.1178 +
243.1179 +    /**
243.1180 +     * Initiates a search to find a Pattern within the given bounds.
243.1181 +     * The groups are filled with default values and the match of the root
243.1182 +     * of the state machine is called. The state machine will hold the state
243.1183 +     * of the match as it proceeds in this matcher.
243.1184 +     *
243.1185 +     * Matcher.from is not set here, because it is the "hard" boundary
243.1186 +     * of the start of the search which anchors will set to. The from param
243.1187 +     * is the "soft" boundary of the start of the search, meaning that the
243.1188 +     * regex tries to match at that index but ^ won't match there. Subsequent
243.1189 +     * calls to the search methods start at a new "soft" boundary which is
243.1190 +     * the end of the previous match.
243.1191 +     */
243.1192 +    boolean search(int from) {
243.1193 +        this.hitEnd = false;
243.1194 +        this.requireEnd = false;
243.1195 +        from        = from < 0 ? 0 : from;
243.1196 +        this.first  = from;
243.1197 +        this.oldLast = oldLast < 0 ? from : oldLast;
243.1198 +        for (int i = 0; i < groups.length; i++)
243.1199 +            groups[i] = -1;
243.1200 +        acceptMode = NOANCHOR;
243.1201 +        boolean result = parentPattern.root.match(this, from, text);
243.1202 +        if (!result)
243.1203 +            this.first = -1;
243.1204 +        this.oldLast = this.last;
243.1205 +        return result;
243.1206 +    }
243.1207 +
243.1208 +    /**
243.1209 +     * Initiates a search for an anchored match to a Pattern within the given
243.1210 +     * bounds. The groups are filled with default values and the match of the
243.1211 +     * root of the state machine is called. The state machine will hold the
243.1212 +     * state of the match as it proceeds in this matcher.
243.1213 +     */
243.1214 +    boolean match(int from, int anchor) {
243.1215 +        this.hitEnd = false;
243.1216 +        this.requireEnd = false;
243.1217 +        from        = from < 0 ? 0 : from;
243.1218 +        this.first  = from;
243.1219 +        this.oldLast = oldLast < 0 ? from : oldLast;
243.1220 +        for (int i = 0; i < groups.length; i++)
243.1221 +            groups[i] = -1;
243.1222 +        acceptMode = anchor;
243.1223 +        boolean result = parentPattern.matchRoot.match(this, from, text);
243.1224 +        if (!result)
243.1225 +            this.first = -1;
243.1226 +        this.oldLast = this.last;
243.1227 +        return result;
243.1228 +    }
243.1229 +
243.1230 +    /**
243.1231 +     * Returns the end index of the text.
243.1232 +     *
243.1233 +     * @return the index after the last character in the text
243.1234 +     */
243.1235 +    int getTextLength() {
243.1236 +        return text.length();
243.1237 +    }
243.1238 +
243.1239 +    /**
243.1240 +     * Generates a String from this Matcher's input in the specified range.
243.1241 +     *
243.1242 +     * @param  beginIndex   the beginning index, inclusive
243.1243 +     * @param  endIndex     the ending index, exclusive
243.1244 +     * @return A String generated from this Matcher's input
243.1245 +     */
243.1246 +    CharSequence getSubSequence(int beginIndex, int endIndex) {
243.1247 +        return text.subSequence(beginIndex, endIndex);
243.1248 +    }
243.1249 +
243.1250 +    /**
243.1251 +     * Returns this Matcher's input character at index i.
243.1252 +     *
243.1253 +     * @return A char from the specified index
243.1254 +     */
243.1255 +    char charAt(int i) {
243.1256 +        return text.charAt(i);
243.1257 +    }
243.1258 +
243.1259 +}
   244.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   244.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/Pattern.java	Wed Apr 30 15:04:10 2014 +0200
   244.3 @@ -0,0 +1,5657 @@
   244.4 +/*
   244.5 + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
   244.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   244.7 + *
   244.8 + * This code is free software; you can redistribute it and/or modify it
   244.9 + * under the terms of the GNU General Public License version 2 only, as
  244.10 + * published by the Free Software Foundation.  Oracle designates this
  244.11 + * particular file as subject to the "Classpath" exception as provided
  244.12 + * by Oracle in the LICENSE file that accompanied this code.
  244.13 + *
  244.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  244.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  244.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  244.17 + * version 2 for more details (a copy is included in the LICENSE file that
  244.18 + * accompanied this code).
  244.19 + *
  244.20 + * You should have received a copy of the GNU General Public License version
  244.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  244.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  244.23 + *
  244.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  244.25 + * or visit www.oracle.com if you need additional information or have any
  244.26 + * questions.
  244.27 + */
  244.28 +
  244.29 +package java.util.regex;
  244.30 +
  244.31 +import java.util.Locale;
  244.32 +import java.util.Map;
  244.33 +import java.util.ArrayList;
  244.34 +import java.util.HashMap;
  244.35 +import java.util.Arrays;
  244.36 +
  244.37 +
  244.38 +/**
  244.39 + * A compiled representation of a regular expression.
  244.40 + *
  244.41 + * <p> A regular expression, specified as a string, must first be compiled into
  244.42 + * an instance of this class.  The resulting pattern can then be used to create
  244.43 + * a {@link Matcher} object that can match arbitrary {@link
  244.44 + * java.lang.CharSequence </code>character sequences<code>} against the regular
  244.45 + * expression.  All of the state involved in performing a match resides in the
  244.46 + * matcher, so many matchers can share the same pattern.
  244.47 + *
  244.48 + * <p> A typical invocation sequence is thus
  244.49 + *
  244.50 + * <blockquote><pre>
  244.51 + * Pattern p = Pattern.{@link #compile compile}("a*b");
  244.52 + * Matcher m = p.{@link #matcher matcher}("aaaaab");
  244.53 + * boolean b = m.{@link Matcher#matches matches}();</pre></blockquote>
  244.54 + *
  244.55 + * <p> A {@link #matches matches} method is defined by this class as a
  244.56 + * convenience for when a regular expression is used just once.  This method
  244.57 + * compiles an expression and matches an input sequence against it in a single
  244.58 + * invocation.  The statement
  244.59 + *
  244.60 + * <blockquote><pre>
  244.61 + * boolean b = Pattern.matches("a*b", "aaaaab");</pre></blockquote>
  244.62 + *
  244.63 + * is equivalent to the three statements above, though for repeated matches it
  244.64 + * is less efficient since it does not allow the compiled pattern to be reused.
  244.65 + *
  244.66 + * <p> Instances of this class are immutable and are safe for use by multiple
  244.67 + * concurrent threads.  Instances of the {@link Matcher} class are not safe for
  244.68 + * such use.
  244.69 + *
  244.70 + *
  244.71 + * <a name="sum">
  244.72 + * <h4> Summary of regular-expression constructs </h4>
  244.73 + *
  244.74 + * <table border="0" cellpadding="1" cellspacing="0"
  244.75 + *  summary="Regular expression constructs, and what they match">
  244.76 + *
  244.77 + * <tr align="left">
  244.78 + * <th bgcolor="#CCCCFF" align="left" id="construct">Construct</th>
  244.79 + * <th bgcolor="#CCCCFF" align="left" id="matches">Matches</th>
  244.80 + * </tr>
  244.81 + *
  244.82 + * <tr><th>&nbsp;</th></tr>
  244.83 + * <tr align="left"><th colspan="2" id="characters">Characters</th></tr>
  244.84 + *
  244.85 + * <tr><td valign="top" headers="construct characters"><i>x</i></td>
  244.86 + *     <td headers="matches">The character <i>x</i></td></tr>
  244.87 + * <tr><td valign="top" headers="construct characters"><tt>\\</tt></td>
  244.88 + *     <td headers="matches">The backslash character</td></tr>
  244.89 + * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>n</i></td>
  244.90 + *     <td headers="matches">The character with octal value <tt>0</tt><i>n</i>
  244.91 + *         (0&nbsp;<tt>&lt;=</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;7)</td></tr>
  244.92 + * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>nn</i></td>
  244.93 + *     <td headers="matches">The character with octal value <tt>0</tt><i>nn</i>
  244.94 + *         (0&nbsp;<tt>&lt;=</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;7)</td></tr>
  244.95 + * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>mnn</i></td>
  244.96 + *     <td headers="matches">The character with octal value <tt>0</tt><i>mnn</i>
  244.97 + *         (0&nbsp;<tt>&lt;=</tt>&nbsp;<i>m</i>&nbsp;<tt>&lt;=</tt>&nbsp;3,
  244.98 + *         0&nbsp;<tt>&lt;=</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;7)</td></tr>
  244.99 + * <tr><td valign="top" headers="construct characters"><tt>\x</tt><i>hh</i></td>
 244.100 + *     <td headers="matches">The character with hexadecimal&nbsp;value&nbsp;<tt>0x</tt><i>hh</i></td></tr>
 244.101 + * <tr><td valign="top" headers="construct characters"><tt>&#92;u</tt><i>hhhh</i></td>
 244.102 + *     <td headers="matches">The character with hexadecimal&nbsp;value&nbsp;<tt>0x</tt><i>hhhh</i></td></tr>
 244.103 + * <tr><td valign="top" headers="construct characters"><tt>&#92;x</tt><i>{h...h}</i></td>
 244.104 + *     <td headers="matches">The character with hexadecimal&nbsp;value&nbsp;<tt>0x</tt><i>h...h</i>
 244.105 + *         ({@link java.lang.Character#MIN_CODE_POINT Character.MIN_CODE_POINT}
 244.106 + *         &nbsp;&lt;=&nbsp;<tt>0x</tt><i>h...h</i>&nbsp;&lt;=&nbsp
 244.107 + *          {@link java.lang.Character#MAX_CODE_POINT Character.MAX_CODE_POINT})</td></tr>
 244.108 + * <tr><td valign="top" headers="matches"><tt>\t</tt></td>
 244.109 + *     <td headers="matches">The tab character (<tt>'&#92;u0009'</tt>)</td></tr>
 244.110 + * <tr><td valign="top" headers="construct characters"><tt>\n</tt></td>
 244.111 + *     <td headers="matches">The newline (line feed) character (<tt>'&#92;u000A'</tt>)</td></tr>
 244.112 + * <tr><td valign="top" headers="construct characters"><tt>\r</tt></td>
 244.113 + *     <td headers="matches">The carriage-return character (<tt>'&#92;u000D'</tt>)</td></tr>
 244.114 + * <tr><td valign="top" headers="construct characters"><tt>\f</tt></td>
 244.115 + *     <td headers="matches">The form-feed character (<tt>'&#92;u000C'</tt>)</td></tr>
 244.116 + * <tr><td valign="top" headers="construct characters"><tt>\a</tt></td>
 244.117 + *     <td headers="matches">The alert (bell) character (<tt>'&#92;u0007'</tt>)</td></tr>
 244.118 + * <tr><td valign="top" headers="construct characters"><tt>\e</tt></td>
 244.119 + *     <td headers="matches">The escape character (<tt>'&#92;u001B'</tt>)</td></tr>
 244.120 + * <tr><td valign="top" headers="construct characters"><tt>\c</tt><i>x</i></td>
 244.121 + *     <td headers="matches">The control character corresponding to <i>x</i></td></tr>
 244.122 + *
 244.123 + * <tr><th>&nbsp;</th></tr>
 244.124 + * <tr align="left"><th colspan="2" id="classes">Character classes</th></tr>
 244.125 + *
 244.126 + * <tr><td valign="top" headers="construct classes"><tt>[abc]</tt></td>
 244.127 + *     <td headers="matches"><tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (simple class)</td></tr>
 244.128 + * <tr><td valign="top" headers="construct classes"><tt>[^abc]</tt></td>
 244.129 + *     <td headers="matches">Any character except <tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (negation)</td></tr>
 244.130 + * <tr><td valign="top" headers="construct classes"><tt>[a-zA-Z]</tt></td>
 244.131 + *     <td headers="matches"><tt>a</tt> through <tt>z</tt>
 244.132 + *         or <tt>A</tt> through <tt>Z</tt>, inclusive (range)</td></tr>
 244.133 + * <tr><td valign="top" headers="construct classes"><tt>[a-d[m-p]]</tt></td>
 244.134 + *     <td headers="matches"><tt>a</tt> through <tt>d</tt>,
 244.135 + *      or <tt>m</tt> through <tt>p</tt>: <tt>[a-dm-p]</tt> (union)</td></tr>
 244.136 + * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[def]]</tt></td>
 244.137 + *     <td headers="matches"><tt>d</tt>, <tt>e</tt>, or <tt>f</tt> (intersection)</tr>
 244.138 + * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^bc]]</tt></td>
 244.139 + *     <td headers="matches"><tt>a</tt> through <tt>z</tt>,
 244.140 + *         except for <tt>b</tt> and <tt>c</tt>: <tt>[ad-z]</tt> (subtraction)</td></tr>
 244.141 + * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^m-p]]</tt></td>
 244.142 + *     <td headers="matches"><tt>a</tt> through <tt>z</tt>,
 244.143 + *          and not <tt>m</tt> through <tt>p</tt>: <tt>[a-lq-z]</tt>(subtraction)</td></tr>
 244.144 + * <tr><th>&nbsp;</th></tr>
 244.145 + *
 244.146 + * <tr align="left"><th colspan="2" id="predef">Predefined character classes</th></tr>
 244.147 + *
 244.148 + * <tr><td valign="top" headers="construct predef"><tt>.</tt></td>
 244.149 + *     <td headers="matches">Any character (may or may not match <a href="#lt">line terminators</a>)</td></tr>
 244.150 + * <tr><td valign="top" headers="construct predef"><tt>\d</tt></td>
 244.151 + *     <td headers="matches">A digit: <tt>[0-9]</tt></td></tr>
 244.152 + * <tr><td valign="top" headers="construct predef"><tt>\D</tt></td>
 244.153 + *     <td headers="matches">A non-digit: <tt>[^0-9]</tt></td></tr>
 244.154 + * <tr><td valign="top" headers="construct predef"><tt>\s</tt></td>
 244.155 + *     <td headers="matches">A whitespace character: <tt>[ \t\n\x0B\f\r]</tt></td></tr>
 244.156 + * <tr><td valign="top" headers="construct predef"><tt>\S</tt></td>
 244.157 + *     <td headers="matches">A non-whitespace character: <tt>[^\s]</tt></td></tr>
 244.158 + * <tr><td valign="top" headers="construct predef"><tt>\w</tt></td>
 244.159 + *     <td headers="matches">A word character: <tt>[a-zA-Z_0-9]</tt></td></tr>
 244.160 + * <tr><td valign="top" headers="construct predef"><tt>\W</tt></td>
 244.161 + *     <td headers="matches">A non-word character: <tt>[^\w]</tt></td></tr>
 244.162 + *
 244.163 + * <tr><th>&nbsp;</th></tr>
 244.164 + * <tr align="left"><th colspan="2" id="posix">POSIX character classes</b> (US-ASCII only)<b></th></tr>
 244.165 + *
 244.166 + * <tr><td valign="top" headers="construct posix"><tt>\p{Lower}</tt></td>
 244.167 + *     <td headers="matches">A lower-case alphabetic character: <tt>[a-z]</tt></td></tr>
 244.168 + * <tr><td valign="top" headers="construct posix"><tt>\p{Upper}</tt></td>
 244.169 + *     <td headers="matches">An upper-case alphabetic character:<tt>[A-Z]</tt></td></tr>
 244.170 + * <tr><td valign="top" headers="construct posix"><tt>\p{ASCII}</tt></td>
 244.171 + *     <td headers="matches">All ASCII:<tt>[\x00-\x7F]</tt></td></tr>
 244.172 + * <tr><td valign="top" headers="construct posix"><tt>\p{Alpha}</tt></td>
 244.173 + *     <td headers="matches">An alphabetic character:<tt>[\p{Lower}\p{Upper}]</tt></td></tr>
 244.174 + * <tr><td valign="top" headers="construct posix"><tt>\p{Digit}</tt></td>
 244.175 + *     <td headers="matches">A decimal digit: <tt>[0-9]</tt></td></tr>
 244.176 + * <tr><td valign="top" headers="construct posix"><tt>\p{Alnum}</tt></td>
 244.177 + *     <td headers="matches">An alphanumeric character:<tt>[\p{Alpha}\p{Digit}]</tt></td></tr>
 244.178 + * <tr><td valign="top" headers="construct posix"><tt>\p{Punct}</tt></td>
 244.179 + *     <td headers="matches">Punctuation: One of <tt>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</tt></td></tr>
 244.180 + *     <!-- <tt>[\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]</tt>
 244.181 + *          <tt>[\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]</tt> -->
 244.182 + * <tr><td valign="top" headers="construct posix"><tt>\p{Graph}</tt></td>
 244.183 + *     <td headers="matches">A visible character: <tt>[\p{Alnum}\p{Punct}]</tt></td></tr>
 244.184 + * <tr><td valign="top" headers="construct posix"><tt>\p{Print}</tt></td>
 244.185 + *     <td headers="matches">A printable character: <tt>[\p{Graph}\x20]</tt></td></tr>
 244.186 + * <tr><td valign="top" headers="construct posix"><tt>\p{Blank}</tt></td>
 244.187 + *     <td headers="matches">A space or a tab: <tt>[ \t]</tt></td></tr>
 244.188 + * <tr><td valign="top" headers="construct posix"><tt>\p{Cntrl}</tt></td>
 244.189 + *     <td headers="matches">A control character: <tt>[\x00-\x1F\x7F]</tt></td></tr>
 244.190 + * <tr><td valign="top" headers="construct posix"><tt>\p{XDigit}</tt></td>
 244.191 + *     <td headers="matches">A hexadecimal digit: <tt>[0-9a-fA-F]</tt></td></tr>
 244.192 + * <tr><td valign="top" headers="construct posix"><tt>\p{Space}</tt></td>
 244.193 + *     <td headers="matches">A whitespace character: <tt>[ \t\n\x0B\f\r]</tt></td></tr>
 244.194 + *
 244.195 + * <tr><th>&nbsp;</th></tr>
 244.196 + * <tr align="left"><th colspan="2">java.lang.Character classes (simple <a href="#jcc">java character type</a>)</th></tr>
 244.197 + *
 244.198 + * <tr><td valign="top"><tt>\p{javaLowerCase}</tt></td>
 244.199 + *     <td>Equivalent to java.lang.Character.isLowerCase()</td></tr>
 244.200 + * <tr><td valign="top"><tt>\p{javaUpperCase}</tt></td>
 244.201 + *     <td>Equivalent to java.lang.Character.isUpperCase()</td></tr>
 244.202 + * <tr><td valign="top"><tt>\p{javaWhitespace}</tt></td>
 244.203 + *     <td>Equivalent to java.lang.Character.isWhitespace()</td></tr>
 244.204 + * <tr><td valign="top"><tt>\p{javaMirrored}</tt></td>
 244.205 + *     <td>Equivalent to java.lang.Character.isMirrored()</td></tr>
 244.206 + *
 244.207 + * <tr><th>&nbsp;</th></tr>
 244.208 + * <tr align="left"><th colspan="2" id="unicode">Classes for Unicode scripts, blocks, categories and binary properties</th></tr>
 244.209 + * * <tr><td valign="top" headers="construct unicode"><tt>\p{IsLatin}</tt></td>
 244.210 + *     <td headers="matches">A Latin&nbsp;script character (<a href="#usc">script</a>)</td></tr>
 244.211 + * <tr><td valign="top" headers="construct unicode"><tt>\p{InGreek}</tt></td>
 244.212 + *     <td headers="matches">A character in the Greek&nbsp;block (<a href="#ubc">block</a>)</td></tr>
 244.213 + * <tr><td valign="top" headers="construct unicode"><tt>\p{Lu}</tt></td>
 244.214 + *     <td headers="matches">An uppercase letter (<a href="#ucc">category</a>)</td></tr>
 244.215 + * <tr><td valign="top" headers="construct unicode"><tt>\p{IsAlphabetic}</tt></td>
 244.216 + *     <td headers="matches">An alphabetic character (<a href="#ubpc">binary property</a>)</td></tr>
 244.217 + * <tr><td valign="top" headers="construct unicode"><tt>\p{Sc}</tt></td>
 244.218 + *     <td headers="matches">A currency symbol</td></tr>
 244.219 + * <tr><td valign="top" headers="construct unicode"><tt>\P{InGreek}</tt></td>
 244.220 + *     <td headers="matches">Any character except one in the Greek block (negation)</td></tr>
 244.221 + * <tr><td valign="top" headers="construct unicode"><tt>[\p{L}&&[^\p{Lu}]]&nbsp;</tt></td>
 244.222 + *     <td headers="matches">Any letter except an uppercase letter (subtraction)</td></tr>
 244.223 + *
 244.224 + * <tr><th>&nbsp;</th></tr>
 244.225 + * <tr align="left"><th colspan="2" id="bounds">Boundary matchers</th></tr>
 244.226 + *
 244.227 + * <tr><td valign="top" headers="construct bounds"><tt>^</tt></td>
 244.228 + *     <td headers="matches">The beginning of a line</td></tr>
 244.229 + * <tr><td valign="top" headers="construct bounds"><tt>$</tt></td>
 244.230 + *     <td headers="matches">The end of a line</td></tr>
 244.231 + * <tr><td valign="top" headers="construct bounds"><tt>\b</tt></td>
 244.232 + *     <td headers="matches">A word boundary</td></tr>
 244.233 + * <tr><td valign="top" headers="construct bounds"><tt>\B</tt></td>
 244.234 + *     <td headers="matches">A non-word boundary</td></tr>
 244.235 + * <tr><td valign="top" headers="construct bounds"><tt>\A</tt></td>
 244.236 + *     <td headers="matches">The beginning of the input</td></tr>
 244.237 + * <tr><td valign="top" headers="construct bounds"><tt>\G</tt></td>
 244.238 + *     <td headers="matches">The end of the previous match</td></tr>
 244.239 + * <tr><td valign="top" headers="construct bounds"><tt>\Z</tt></td>
 244.240 + *     <td headers="matches">The end of the input but for the final
 244.241 + *         <a href="#lt">terminator</a>, if&nbsp;any</td></tr>
 244.242 + * <tr><td valign="top" headers="construct bounds"><tt>\z</tt></td>
 244.243 + *     <td headers="matches">The end of the input</td></tr>
 244.244 + *
 244.245 + * <tr><th>&nbsp;</th></tr>
 244.246 + * <tr align="left"><th colspan="2" id="greedy">Greedy quantifiers</th></tr>
 244.247 + *
 244.248 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>?</tt></td>
 244.249 + *     <td headers="matches"><i>X</i>, once or not at all</td></tr>
 244.250 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>*</tt></td>
 244.251 + *     <td headers="matches"><i>X</i>, zero or more times</td></tr>
 244.252 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>+</tt></td>
 244.253 + *     <td headers="matches"><i>X</i>, one or more times</td></tr>
 244.254 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>{</tt><i>n</i><tt>}</tt></td>
 244.255 + *     <td headers="matches"><i>X</i>, exactly <i>n</i> times</td></tr>
 244.256 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>{</tt><i>n</i><tt>,}</tt></td>
 244.257 + *     <td headers="matches"><i>X</i>, at least <i>n</i> times</td></tr>
 244.258 + * <tr><td valign="top" headers="construct greedy"><i>X</i><tt>{</tt><i>n</i><tt>,</tt><i>m</i><tt>}</tt></td>
 244.259 + *     <td headers="matches"><i>X</i>, at least <i>n</i> but not more than <i>m</i> times</td></tr>
 244.260 + *
 244.261 + * <tr><th>&nbsp;</th></tr>
 244.262 + * <tr align="left"><th colspan="2" id="reluc">Reluctant quantifiers</th></tr>
 244.263 + *
 244.264 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>??</tt></td>
 244.265 + *     <td headers="matches"><i>X</i>, once or not at all</td></tr>
 244.266 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>*?</tt></td>
 244.267 + *     <td headers="matches"><i>X</i>, zero or more times</td></tr>
 244.268 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>+?</tt></td>
 244.269 + *     <td headers="matches"><i>X</i>, one or more times</td></tr>
 244.270 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>{</tt><i>n</i><tt>}?</tt></td>
 244.271 + *     <td headers="matches"><i>X</i>, exactly <i>n</i> times</td></tr>
 244.272 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>{</tt><i>n</i><tt>,}?</tt></td>
 244.273 + *     <td headers="matches"><i>X</i>, at least <i>n</i> times</td></tr>
 244.274 + * <tr><td valign="top" headers="construct reluc"><i>X</i><tt>{</tt><i>n</i><tt>,</tt><i>m</i><tt>}?</tt></td>
 244.275 + *     <td headers="matches"><i>X</i>, at least <i>n</i> but not more than <i>m</i> times</td></tr>
 244.276 + *
 244.277 + * <tr><th>&nbsp;</th></tr>
 244.278 + * <tr align="left"><th colspan="2" id="poss">Possessive quantifiers</th></tr>
 244.279 + *
 244.280 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>?+</tt></td>
 244.281 + *     <td headers="matches"><i>X</i>, once or not at all</td></tr>
 244.282 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>*+</tt></td>
 244.283 + *     <td headers="matches"><i>X</i>, zero or more times</td></tr>
 244.284 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>++</tt></td>
 244.285 + *     <td headers="matches"><i>X</i>, one or more times</td></tr>
 244.286 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>{</tt><i>n</i><tt>}+</tt></td>
 244.287 + *     <td headers="matches"><i>X</i>, exactly <i>n</i> times</td></tr>
 244.288 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>{</tt><i>n</i><tt>,}+</tt></td>
 244.289 + *     <td headers="matches"><i>X</i>, at least <i>n</i> times</td></tr>
 244.290 + * <tr><td valign="top" headers="construct poss"><i>X</i><tt>{</tt><i>n</i><tt>,</tt><i>m</i><tt>}+</tt></td>
 244.291 + *     <td headers="matches"><i>X</i>, at least <i>n</i> but not more than <i>m</i> times</td></tr>
 244.292 + *
 244.293 + * <tr><th>&nbsp;</th></tr>
 244.294 + * <tr align="left"><th colspan="2" id="logical">Logical operators</th></tr>
 244.295 + *
 244.296 + * <tr><td valign="top" headers="construct logical"><i>XY</i></td>
 244.297 + *     <td headers="matches"><i>X</i> followed by <i>Y</i></td></tr>
 244.298 + * <tr><td valign="top" headers="construct logical"><i>X</i><tt>|</tt><i>Y</i></td>
 244.299 + *     <td headers="matches">Either <i>X</i> or <i>Y</i></td></tr>
 244.300 + * <tr><td valign="top" headers="construct logical"><tt>(</tt><i>X</i><tt>)</tt></td>
 244.301 + *     <td headers="matches">X, as a <a href="#cg">capturing group</a></td></tr>
 244.302 + *
 244.303 + * <tr><th>&nbsp;</th></tr>
 244.304 + * <tr align="left"><th colspan="2" id="backref">Back references</th></tr>
 244.305 + *
 244.306 + * <tr><td valign="bottom" headers="construct backref"><tt>\</tt><i>n</i></td>
 244.307 + *     <td valign="bottom" headers="matches">Whatever the <i>n</i><sup>th</sup>
 244.308 + *     <a href="#cg">capturing group</a> matched</td></tr>
 244.309 + *
 244.310 + * <tr><td valign="bottom" headers="construct backref"><tt>\</tt><i>k</i>&lt;<i>name</i>&gt;</td>
 244.311 + *     <td valign="bottom" headers="matches">Whatever the
 244.312 + *     <a href="#groupname">named-capturing group</a> "name" matched</td></tr>
 244.313 + *
 244.314 + * <tr><th>&nbsp;</th></tr>
 244.315 + * <tr align="left"><th colspan="2" id="quot">Quotation</th></tr>
 244.316 + *
 244.317 + * <tr><td valign="top" headers="construct quot"><tt>\</tt></td>
 244.318 + *     <td headers="matches">Nothing, but quotes the following character</td></tr>
 244.319 + * <tr><td valign="top" headers="construct quot"><tt>\Q</tt></td>
 244.320 + *     <td headers="matches">Nothing, but quotes all characters until <tt>\E</tt></td></tr>
 244.321 + * <tr><td valign="top" headers="construct quot"><tt>\E</tt></td>
 244.322 + *     <td headers="matches">Nothing, but ends quoting started by <tt>\Q</tt></td></tr>
 244.323 + *     <!-- Metachars: !$()*+.<>?[\]^{|} -->
 244.324 + *
 244.325 + * <tr><th>&nbsp;</th></tr>
 244.326 + * <tr align="left"><th colspan="2" id="special">Special constructs (named-capturing and non-capturing)</th></tr>
 244.327 + *
 244.328 + * <tr><td valign="top" headers="construct special"><tt>(?&lt;<a href="#groupname">name</a>&gt;</tt><i>X</i><tt>)</tt></td>
 244.329 + *     <td headers="matches"><i>X</i>, as a named-capturing group</td></tr>
 244.330 + * <tr><td valign="top" headers="construct special"><tt>(?:</tt><i>X</i><tt>)</tt></td>
 244.331 + *     <td headers="matches"><i>X</i>, as a non-capturing group</td></tr>
 244.332 + * <tr><td valign="top" headers="construct special"><tt>(?idmsuxU-idmsuxU)&nbsp;</tt></td>
 244.333 + *     <td headers="matches">Nothing, but turns match flags <a href="#CASE_INSENSITIVE">i</a>
 244.334 + * <a href="#UNIX_LINES">d</a> <a href="#MULTILINE">m</a> <a href="#DOTALL">s</a>
 244.335 + * <a href="#UNICODE_CASE">u</a> <a href="#COMMENTS">x</a> <a href="#UNICODE_CHARACTER_CLASS">U</a>
 244.336 + * on - off</td></tr>
 244.337 + * <tr><td valign="top" headers="construct special"><tt>(?idmsux-idmsux:</tt><i>X</i><tt>)</tt>&nbsp;&nbsp;</td>
 244.338 + *     <td headers="matches"><i>X</i>, as a <a href="#cg">non-capturing group</a> with the
 244.339 + *         given flags <a href="#CASE_INSENSITIVE">i</a> <a href="#UNIX_LINES">d</a>
 244.340 + * <a href="#MULTILINE">m</a> <a href="#DOTALL">s</a> <a href="#UNICODE_CASE">u</a >
 244.341 + * <a href="#COMMENTS">x</a> on - off</td></tr>
 244.342 + * <tr><td valign="top" headers="construct special"><tt>(?=</tt><i>X</i><tt>)</tt></td>
 244.343 + *     <td headers="matches"><i>X</i>, via zero-width positive lookahead</td></tr>
 244.344 + * <tr><td valign="top" headers="construct special"><tt>(?!</tt><i>X</i><tt>)</tt></td>
 244.345 + *     <td headers="matches"><i>X</i>, via zero-width negative lookahead</td></tr>
 244.346 + * <tr><td valign="top" headers="construct special"><tt>(?&lt;=</tt><i>X</i><tt>)</tt></td>
 244.347 + *     <td headers="matches"><i>X</i>, via zero-width positive lookbehind</td></tr>
 244.348 + * <tr><td valign="top" headers="construct special"><tt>(?&lt;!</tt><i>X</i><tt>)</tt></td>
 244.349 + *     <td headers="matches"><i>X</i>, via zero-width negative lookbehind</td></tr>
 244.350 + * <tr><td valign="top" headers="construct special"><tt>(?&gt;</tt><i>X</i><tt>)</tt></td>
 244.351 + *     <td headers="matches"><i>X</i>, as an independent, non-capturing group</td></tr>
 244.352 + *
 244.353 + * </table>
 244.354 + *
 244.355 + * <hr>
 244.356 + *
 244.357 + *
 244.358 + * <a name="bs">
 244.359 + * <h4> Backslashes, escapes, and quoting </h4>
 244.360 + *
 244.361 + * <p> The backslash character (<tt>'\'</tt>) serves to introduce escaped
 244.362 + * constructs, as defined in the table above, as well as to quote characters
 244.363 + * that otherwise would be interpreted as unescaped constructs.  Thus the
 244.364 + * expression <tt>\\</tt> matches a single backslash and <tt>\{</tt> matches a
 244.365 + * left brace.
 244.366 + *
 244.367 + * <p> It is an error to use a backslash prior to any alphabetic character that
 244.368 + * does not denote an escaped construct; these are reserved for future
 244.369 + * extensions to the regular-expression language.  A backslash may be used
 244.370 + * prior to a non-alphabetic character regardless of whether that character is
 244.371 + * part of an unescaped construct.
 244.372 + *
 244.373 + * <p> Backslashes within string literals in Java source code are interpreted
 244.374 + * as required by
 244.375 + * <cite>The Java&trade; Language Specification</cite>
 244.376 + * as either Unicode escapes (section 3.3) or other character escapes (section 3.10.6)
 244.377 + * It is therefore necessary to double backslashes in string
 244.378 + * literals that represent regular expressions to protect them from
 244.379 + * interpretation by the Java bytecode compiler.  The string literal
 244.380 + * <tt>"&#92;b"</tt>, for example, matches a single backspace character when
 244.381 + * interpreted as a regular expression, while <tt>"&#92;&#92;b"</tt> matches a
 244.382 + * word boundary.  The string literal <tt>"&#92;(hello&#92;)"</tt> is illegal
 244.383 + * and leads to a compile-time error; in order to match the string
 244.384 + * <tt>(hello)</tt> the string literal <tt>"&#92;&#92;(hello&#92;&#92;)"</tt>
 244.385 + * must be used.
 244.386 + *
 244.387 + * <a name="cc">
 244.388 + * <h4> Character Classes </h4>
 244.389 + *
 244.390 + *    <p> Character classes may appear within other character classes, and
 244.391 + *    may be composed by the union operator (implicit) and the intersection
 244.392 + *    operator (<tt>&amp;&amp;</tt>).
 244.393 + *    The union operator denotes a class that contains every character that is
 244.394 + *    in at least one of its operand classes.  The intersection operator
 244.395 + *    denotes a class that contains every character that is in both of its
 244.396 + *    operand classes.
 244.397 + *
 244.398 + *    <p> The precedence of character-class operators is as follows, from
 244.399 + *    highest to lowest:
 244.400 + *
 244.401 + *    <blockquote><table border="0" cellpadding="1" cellspacing="0"
 244.402 + *                 summary="Precedence of character class operators.">
 244.403 + *      <tr><th>1&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.404 + *        <td>Literal escape&nbsp;&nbsp;&nbsp;&nbsp;</td>
 244.405 + *        <td><tt>\x</tt></td></tr>
 244.406 + *     <tr><th>2&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.407 + *        <td>Grouping</td>
 244.408 + *        <td><tt>[...]</tt></td></tr>
 244.409 + *     <tr><th>3&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.410 + *        <td>Range</td>
 244.411 + *        <td><tt>a-z</tt></td></tr>
 244.412 + *      <tr><th>4&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.413 + *        <td>Union</td>
 244.414 + *        <td><tt>[a-e][i-u]</tt></td></tr>
 244.415 + *      <tr><th>5&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.416 + *        <td>Intersection</td>
 244.417 + *        <td><tt>[a-z&&[aeiou]]</tt></td></tr>
 244.418 + *    </table></blockquote>
 244.419 + *
 244.420 + *    <p> Note that a different set of metacharacters are in effect inside
 244.421 + *    a character class than outside a character class. For instance, the
 244.422 + *    regular expression <tt>.</tt> loses its special meaning inside a
 244.423 + *    character class, while the expression <tt>-</tt> becomes a range
 244.424 + *    forming metacharacter.
 244.425 + *
 244.426 + * <a name="lt">
 244.427 + * <h4> Line terminators </h4>
 244.428 + *
 244.429 + * <p> A <i>line terminator</i> is a one- or two-character sequence that marks
 244.430 + * the end of a line of the input character sequence.  The following are
 244.431 + * recognized as line terminators:
 244.432 + *
 244.433 + * <ul>
 244.434 + *
 244.435 + *   <li> A newline (line feed) character&nbsp;(<tt>'\n'</tt>),
 244.436 + *
 244.437 + *   <li> A carriage-return character followed immediately by a newline
 244.438 + *   character&nbsp;(<tt>"\r\n"</tt>),
 244.439 + *
 244.440 + *   <li> A standalone carriage-return character&nbsp;(<tt>'\r'</tt>),
 244.441 + *
 244.442 + *   <li> A next-line character&nbsp;(<tt>'&#92;u0085'</tt>),
 244.443 + *
 244.444 + *   <li> A line-separator character&nbsp;(<tt>'&#92;u2028'</tt>), or
 244.445 + *
 244.446 + *   <li> A paragraph-separator character&nbsp;(<tt>'&#92;u2029</tt>).
 244.447 + *
 244.448 + * </ul>
 244.449 + * <p>If {@link #UNIX_LINES} mode is activated, then the only line terminators
 244.450 + * recognized are newline characters.
 244.451 + *
 244.452 + * <p> The regular expression <tt>.</tt> matches any character except a line
 244.453 + * terminator unless the {@link #DOTALL} flag is specified.
 244.454 + *
 244.455 + * <p> By default, the regular expressions <tt>^</tt> and <tt>$</tt> ignore
 244.456 + * line terminators and only match at the beginning and the end, respectively,
 244.457 + * of the entire input sequence. If {@link #MULTILINE} mode is activated then
 244.458 + * <tt>^</tt> matches at the beginning of input and after any line terminator
 244.459 + * except at the end of input. When in {@link #MULTILINE} mode <tt>$</tt>
 244.460 + * matches just before a line terminator or the end of the input sequence.
 244.461 + *
 244.462 + * <a name="cg">
 244.463 + * <h4> Groups and capturing </h4>
 244.464 + *
 244.465 + * <a name="gnumber">
 244.466 + * <h5> Group number </h5>
 244.467 + * <p> Capturing groups are numbered by counting their opening parentheses from
 244.468 + * left to right.  In the expression <tt>((A)(B(C)))</tt>, for example, there
 244.469 + * are four such groups: </p>
 244.470 + *
 244.471 + * <blockquote><table cellpadding=1 cellspacing=0 summary="Capturing group numberings">
 244.472 + * <tr><th>1&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.473 + *     <td><tt>((A)(B(C)))</tt></td></tr>
 244.474 + * <tr><th>2&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.475 + *     <td><tt>(A)</tt></td></tr>
 244.476 + * <tr><th>3&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.477 + *     <td><tt>(B(C))</tt></td></tr>
 244.478 + * <tr><th>4&nbsp;&nbsp;&nbsp;&nbsp;</th>
 244.479 + *     <td><tt>(C)</tt></td></tr>
 244.480 + * </table></blockquote>
 244.481 + *
 244.482 + * <p> Group zero always stands for the entire expression.
 244.483 + *
 244.484 + * <p> Capturing groups are so named because, during a match, each subsequence
 244.485 + * of the input sequence that matches such a group is saved.  The captured
 244.486 + * subsequence may be used later in the expression, via a back reference, and
 244.487 + * may also be retrieved from the matcher once the match operation is complete.
 244.488 + *
 244.489 + * <a name="groupname">
 244.490 + * <h5> Group name </h5>
 244.491 + * <p>A capturing group can also be assigned a "name", a <tt>named-capturing group</tt>,
 244.492 + * and then be back-referenced later by the "name". Group names are composed of
 244.493 + * the following characters. The first character must be a <tt>letter</tt>.
 244.494 + *
 244.495 + * <ul>
 244.496 + *   <li> The uppercase letters <tt>'A'</tt> through <tt>'Z'</tt>
 244.497 + *        (<tt>'&#92;u0041'</tt>&nbsp;through&nbsp;<tt>'&#92;u005a'</tt>),
 244.498 + *   <li> The lowercase letters <tt>'a'</tt> through <tt>'z'</tt>
 244.499 + *        (<tt>'&#92;u0061'</tt>&nbsp;through&nbsp;<tt>'&#92;u007a'</tt>),
 244.500 + *   <li> The digits <tt>'0'</tt> through <tt>'9'</tt>
 244.501 + *        (<tt>'&#92;u0030'</tt>&nbsp;through&nbsp;<tt>'&#92;u0039'</tt>),
 244.502 + * </ul>
 244.503 + *
 244.504 + * <p> A <tt>named-capturing group</tt> is still numbered as described in
 244.505 + * <a href="#gnumber">Group number</a>.
 244.506 + *
 244.507 + * <p> The captured input associated with a group is always the subsequence
 244.508 + * that the group most recently matched.  If a group is evaluated a second time
 244.509 + * because of quantification then its previously-captured value, if any, will
 244.510 + * be retained if the second evaluation fails.  Matching the string
 244.511 + * <tt>"aba"</tt> against the expression <tt>(a(b)?)+</tt>, for example, leaves
 244.512 + * group two set to <tt>"b"</tt>.  All captured input is discarded at the
 244.513 + * beginning of each match.
 244.514 + *
 244.515 + * <p> Groups beginning with <tt>(?</tt> are either pure, <i>non-capturing</i> groups
 244.516 + * that do not capture text and do not count towards the group total, or
 244.517 + * <i>named-capturing</i> group.
 244.518 + *
 244.519 + * <h4> Unicode support </h4>
 244.520 + *
 244.521 + * <p> This class is in conformance with Level 1 of <a
 244.522 + * href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
 244.523 + * Standard #18: Unicode Regular Expression</i></a>, plus RL2.1
 244.524 + * Canonical Equivalents.
 244.525 + * <p>
 244.526 + * <b>Unicode escape sequences</b> such as <tt>&#92;u2014</tt> in Java source code
 244.527 + * are processed as described in section 3.3 of
 244.528 + * <cite>The Java&trade; Language Specification</cite>.
 244.529 + * Such escape sequences are also implemented directly by the regular-expression
 244.530 + * parser so that Unicode escapes can be used in expressions that are read from
 244.531 + * files or from the keyboard.  Thus the strings <tt>"&#92;u2014"</tt> and
 244.532 + * <tt>"\\u2014"</tt>, while not equal, compile into the same pattern, which
 244.533 + * matches the character with hexadecimal value <tt>0x2014</tt>.
 244.534 + * <p>
 244.535 + * A Unicode character can also be represented in a regular-expression by
 244.536 + * using its <b>Hex notation</b>(hexadecimal code point value) directly as described in construct
 244.537 + * <tt>&#92;x{...}</tt>, for example a supplementary character U+2011F
 244.538 + * can be specified as <tt>&#92;x{2011F}</tt>, instead of two consecutive
 244.539 + * Unicode escape sequences of the surrogate pair
 244.540 + * <tt>&#92;uD840</tt><tt>&#92;uDD1F</tt>.
 244.541 + * <p>
 244.542 + * Unicode scripts, blocks, categories and binary properties are written with
 244.543 + * the <tt>\p</tt> and <tt>\P</tt> constructs as in Perl.
 244.544 + * <tt>\p{</tt><i>prop</i><tt>}</tt> matches if
 244.545 + * the input has the property <i>prop</i>, while <tt>\P{</tt><i>prop</i><tt>}</tt>
 244.546 + * does not match if the input has that property.
 244.547 + * <p>
 244.548 + * Scripts, blocks, categories and binary properties can be used both inside
 244.549 + * and outside of a character class.
 244.550 + * <a name="usc">
 244.551 + * <p>
 244.552 + * <b>Scripts</b> are specified either with the prefix {@code Is}, as in
 244.553 + * {@code IsHiragana}, or by using  the {@code script} keyword (or its short
 244.554 + * form {@code sc})as in {@code script=Hiragana} or {@code sc=Hiragana}.
 244.555 + * <p>
 244.556 + * The script names supported by <code>Pattern</code> are the valid script names
 244.557 + * accepted and defined by
 244.558 + * {@link java.lang.Character.UnicodeScript#forName(String) UnicodeScript.forName}.
 244.559 + * <a name="ubc">
 244.560 + * <p>
 244.561 + * <b>Blocks</b> are specified with the prefix {@code In}, as in
 244.562 + * {@code InMongolian}, or by using the keyword {@code block} (or its short
 244.563 + * form {@code blk}) as in {@code block=Mongolian} or {@code blk=Mongolian}.
 244.564 + * <p>
 244.565 + * The block names supported by <code>Pattern</code> are the valid block names
 244.566 + * accepted and defined by
 244.567 + * {@link java.lang.Character.UnicodeBlock#forName(String) UnicodeBlock.forName}.
 244.568 + * <p>
 244.569 + * <a name="ucc">
 244.570 + * <b>Categories</b> may be specified with the optional prefix {@code Is}:
 244.571 + * Both {@code \p{L}} and {@code \p{IsL}} denote the category of Unicode
 244.572 + * letters. Same as scripts and blocks, categories can also be specified
 244.573 + * by using the keyword {@code general_category} (or its short form
 244.574 + * {@code gc}) as in {@code general_category=Lu} or {@code gc=Lu}.
 244.575 + * <p>
 244.576 + * The supported categories are those of
 244.577 + * <a href="http://www.unicode.org/unicode/standard/standard.html">
 244.578 + * <i>The Unicode Standard</i></a> in the version specified by the
 244.579 + * {@link java.lang.Character Character} class. The category names are those
 244.580 + * defined in the Standard, both normative and informative.
 244.581 + * <p>
 244.582 + * <a name="ubpc">
 244.583 + * <b>Binary properties</b> are specified with the prefix {@code Is}, as in
 244.584 + * {@code IsAlphabetic}. The supported binary properties by <code>Pattern</code>
 244.585 + * are
 244.586 + * <ul>
 244.587 + *   <li> Alphabetic
 244.588 + *   <li> Ideographic
 244.589 + *   <li> Letter
 244.590 + *   <li> Lowercase
 244.591 + *   <li> Uppercase
 244.592 + *   <li> Titlecase
 244.593 + *   <li> Punctuation
 244.594 + *   <Li> Control
 244.595 + *   <li> White_Space
 244.596 + *   <li> Digit
 244.597 + *   <li> Hex_Digit
 244.598 + *   <li> Noncharacter_Code_Point
 244.599 + *   <li> Assigned
 244.600 + * </ul>
 244.601 +
 244.602 +
 244.603 + * <p>
 244.604 + * <b>Predefined Character classes</b> and <b>POSIX character classes</b> are in
 244.605 + * conformance with the recommendation of <i>Annex C: Compatibility Properties</i>
 244.606 + * of <a href="http://www.unicode.org/reports/tr18/"><i>Unicode Regular Expression
 244.607 + * </i></a>, when {@link #UNICODE_CHARACTER_CLASS} flag is specified.
 244.608 + * <p>
 244.609 + * <table border="0" cellpadding="1" cellspacing="0"
 244.610 + *  summary="predefined and posix character classes in Unicode mode">
 244.611 + * <tr align="left">
 244.612 + * <th bgcolor="#CCCCFF" align="left" id="classes">Classes</th>
 244.613 + * <th bgcolor="#CCCCFF" align="left" id="matches">Matches</th>
 244.614 + *</tr>
 244.615 + * <tr><td><tt>\p{Lower}</tt></td>
 244.616 + *     <td>A lowercase character:<tt>\p{IsLowercase}</tt></td></tr>
 244.617 + * <tr><td><tt>\p{Upper}</tt></td>
 244.618 + *     <td>An uppercase character:<tt>\p{IsUppercase}</tt></td></tr>
 244.619 + * <tr><td><tt>\p{ASCII}</tt></td>
 244.620 + *     <td>All ASCII:<tt>[\x00-\x7F]</tt></td></tr>
 244.621 + * <tr><td><tt>\p{Alpha}</tt></td>
 244.622 + *     <td>An alphabetic character:<tt>\p{IsAlphabetic}</tt></td></tr>
 244.623 + * <tr><td><tt>\p{Digit}</tt></td>
 244.624 + *     <td>A decimal digit character:<tt>p{IsDigit}</tt></td></tr>
 244.625 + * <tr><td><tt>\p{Alnum}</tt></td>
 244.626 + *     <td>An alphanumeric character:<tt>[\p{IsAlphabetic}\p{IsDigit}]</tt></td></tr>
 244.627 + * <tr><td><tt>\p{Punct}</tt></td>
 244.628 + *     <td>A punctuation character:<tt>p{IsPunctuation}</tt></td></tr>
 244.629 + * <tr><td><tt>\p{Graph}</tt></td>
 244.630 + *     <td>A visible character: <tt>[^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]</tt></td></tr>
 244.631 + * <tr><td><tt>\p{Print}</tt></td>
 244.632 + *     <td>A printable character: <tt>[\p{Graph}\p{Blank}&&[^\p{Cntrl}]]</tt></td></tr>
 244.633 + * <tr><td><tt>\p{Blank}</tt></td>
 244.634 + *     <td>A space or a tab: <tt>[\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]</tt></td></tr>
 244.635 + * <tr><td><tt>\p{Cntrl}</tt></td>
 244.636 + *     <td>A control character: <tt>\p{gc=Cc}</tt></td></tr>
 244.637 + * <tr><td><tt>\p{XDigit}</tt></td>
 244.638 + *     <td>A hexadecimal digit: <tt>[\p{gc=Nd}\p{IsHex_Digit}]</tt></td></tr>
 244.639 + * <tr><td><tt>\p{Space}</tt></td>
 244.640 + *     <td>A whitespace character:<tt>\p{IsWhite_Space}</tt></td></tr>
 244.641 + * <tr><td><tt>\d</tt></td>
 244.642 + *     <td>A digit: <tt>\p{IsDigit}</tt></td></tr>
 244.643 + * <tr><td><tt>\D</tt></td>
 244.644 + *     <td>A non-digit: <tt>[^\d]</tt></td></tr>
 244.645 + * <tr><td><tt>\s</tt></td>
 244.646 + *     <td>A whitespace character: <tt>\p{IsWhite_Space}</tt></td></tr>
 244.647 + * <tr><td><tt>\S</tt></td>
 244.648 + *     <td>A non-whitespace character: <tt>[^\s]</tt></td></tr>
 244.649 + * <tr><td><tt>\w</tt></td>
 244.650 + *     <td>A word character: <tt>[\p{Alpha}\p{gc=Mn}\p{gc=Me}\p{gc=Mc}\p{Digit}\p{gc=Pc}]</tt></td></tr>
 244.651 + * <tr><td><tt>\W</tt></td>
 244.652 + *     <td>A non-word character: <tt>[^\w]</tt></td></tr>
 244.653 + * </table>
 244.654 + * <p>
 244.655 + * <a name="jcc">
 244.656 + * Categories that behave like the java.lang.Character
 244.657 + * boolean is<i>methodname</i> methods (except for the deprecated ones) are
 244.658 + * available through the same <tt>\p{</tt><i>prop</i><tt>}</tt> syntax where
 244.659 + * the specified property has the name <tt>java<i>methodname</i></tt>.
 244.660 + *
 244.661 + * <h4> Comparison to Perl 5 </h4>
 244.662 + *
 244.663 + * <p>The <code>Pattern</code> engine performs traditional NFA-based matching
 244.664 + * with ordered alternation as occurs in Perl 5.
 244.665 + *
 244.666 + * <p> Perl constructs not supported by this class: </p>
 244.667 + *
 244.668 + * <ul>
 244.669 + *    <li><p> Predefined character classes (Unicode character)
 244.670 + *    <p><tt>\h&nbsp;&nbsp;&nbsp;&nbsp;</tt>A horizontal whitespace
 244.671 + *    <p><tt>\H&nbsp;&nbsp;&nbsp;&nbsp;</tt>A non horizontal whitespace
 244.672 + *    <p><tt>\v&nbsp;&nbsp;&nbsp;&nbsp;</tt>A vertical whitespace
 244.673 + *    <p><tt>\V&nbsp;&nbsp;&nbsp;&nbsp;</tt>A non vertical whitespace
 244.674 + *    <p><tt>\R&nbsp;&nbsp;&nbsp;&nbsp;</tt>Any Unicode linebreak sequence
 244.675 + *    <tt>\u005cu000D\u005cu000A|[\u005cu000A\u005cu000B\u005cu000C\u005cu000D\u005cu0085\u005cu2028\u005cu2029]</tt>
 244.676 + *    <p><tt>\X&nbsp;&nbsp;&nbsp;&nbsp;</tt>Match Unicode
 244.677 + *    <a href="http://www.unicode.org/reports/tr18/#Default_Grapheme_Clusters">
 244.678 + *    <i>extended grapheme cluster</i></a>
 244.679 + *    </p></li>
 244.680 + *
 244.681 + *    <li><p> The backreference constructs, <tt>\g{</tt><i>n</i><tt>}</tt> for
 244.682 + *    the <i>n</i><sup>th</sup><a href="#cg">capturing group</a> and
 244.683 + *    <tt>\g{</tt><i>name</i><tt>}</tt> for
 244.684 + *    <a href="#groupname">named-capturing group</a>.
 244.685 + *    </p></li>
 244.686 + *
 244.687 + *    <li><p> The named character construct, <tt>\N{</tt><i>name</i><tt>}</tt>
 244.688 + *    for a Unicode character by its name.
 244.689 + *    </p></li>
 244.690 + *
 244.691 + *    <li><p> The conditional constructs
 244.692 + *    <tt>(?(</tt><i>condition</i><tt>)</tt><i>X</i><tt>)</tt> and
 244.693 + *    <tt>(?(</tt><i>condition</i><tt>)</tt><i>X</i><tt>|</tt><i>Y</i><tt>)</tt>,
 244.694 + *    </p></li>
 244.695 + *
 244.696 + *    <li><p> The embedded code constructs <tt>(?{</tt><i>code</i><tt>})</tt>
 244.697 + *    and <tt>(??{</tt><i>code</i><tt>})</tt>,</p></li>
 244.698 + *
 244.699 + *    <li><p> The embedded comment syntax <tt>(?#comment)</tt>, and </p></li>
 244.700 + *
 244.701 + *    <li><p> The preprocessing operations <tt>\l</tt> <tt>&#92;u</tt>,
 244.702 + *    <tt>\L</tt>, and <tt>\U</tt>.  </p></li>
 244.703 + *
 244.704 + * </ul>
 244.705 + *
 244.706 + * <p> Constructs supported by this class but not by Perl: </p>
 244.707 + *
 244.708 + * <ul>
 244.709 + *
 244.710 + *    <li><p> Character-class union and intersection as described
 244.711 + *    <a href="#cc">above</a>.</p></li>
 244.712 + *
 244.713 + * </ul>
 244.714 + *
 244.715 + * <p> Notable differences from Perl: </p>
 244.716 + *
 244.717 + * <ul>
 244.718 + *
 244.719 + *    <li><p> In Perl, <tt>\1</tt> through <tt>\9</tt> are always interpreted
 244.720 + *    as back references; a backslash-escaped number greater than <tt>9</tt> is
 244.721 + *    treated as a back reference if at least that many subexpressions exist,
 244.722 + *    otherwise it is interpreted, if possible, as an octal escape.  In this
 244.723 + *    class octal escapes must always begin with a zero. In this class,
 244.724 + *    <tt>\1</tt> through <tt>\9</tt> are always interpreted as back
 244.725 + *    references, and a larger number is accepted as a back reference if at
 244.726 + *    least that many subexpressions exist at that point in the regular
 244.727 + *    expression, otherwise the parser will drop digits until the number is
 244.728 + *    smaller or equal to the existing number of groups or it is one digit.
 244.729 + *    </p></li>
 244.730 + *
 244.731 + *    <li><p> Perl uses the <tt>g</tt> flag to request a match that resumes
 244.732 + *    where the last match left off.  This functionality is provided implicitly
 244.733 + *    by the {@link Matcher} class: Repeated invocations of the {@link
 244.734 + *    Matcher#find find} method will resume where the last match left off,
 244.735 + *    unless the matcher is reset.  </p></li>
 244.736 + *
 244.737 + *    <li><p> In Perl, embedded flags at the top level of an expression affect
 244.738 + *    the whole expression.  In this class, embedded flags always take effect
 244.739 + *    at the point at which they appear, whether they are at the top level or
 244.740 + *    within a group; in the latter case, flags are restored at the end of the
 244.741 + *    group just as in Perl.  </p></li>
 244.742 + *
 244.743 + * </ul>
 244.744 + *
 244.745 + *
 244.746 + * <p> For a more precise description of the behavior of regular expression
 244.747 + * constructs, please see <a href="http://www.oreilly.com/catalog/regex3/">
 244.748 + * <i>Mastering Regular Expressions, 3nd Edition</i>, Jeffrey E. F. Friedl,
 244.749 + * O'Reilly and Associates, 2006.</a>
 244.750 + * </p>
 244.751 + *
 244.752 + * @see java.lang.String#split(String, int)
 244.753 + * @see java.lang.String#split(String)
 244.754 + *
 244.755 + * @author      Mike McCloskey
 244.756 + * @author      Mark Reinhold
 244.757 + * @author      JSR-51 Expert Group
 244.758 + * @since       1.4
 244.759 + * @spec        JSR-51
 244.760 + */
 244.761 +
 244.762 +public final class Pattern
 244.763 +    implements java.io.Serializable
 244.764 +{
 244.765 +
 244.766 +    /**
 244.767 +     * Regular expression modifier values.  Instead of being passed as
 244.768 +     * arguments, they can also be passed as inline modifiers.
 244.769 +     * For example, the following statements have the same effect.
 244.770 +     * <pre>
 244.771 +     * RegExp r1 = RegExp.compile("abc", Pattern.I|Pattern.M);
 244.772 +     * RegExp r2 = RegExp.compile("(?im)abc", 0);
 244.773 +     * </pre>
 244.774 +     *
 244.775 +     * The flags are duplicated so that the familiar Perl match flag
 244.776 +     * names are available.
 244.777 +     */
 244.778 +
 244.779 +    /**
 244.780 +     * Enables Unix lines mode.
 244.781 +     *
 244.782 +     * <p> In this mode, only the <tt>'\n'</tt> line terminator is recognized
 244.783 +     * in the behavior of <tt>.</tt>, <tt>^</tt>, and <tt>$</tt>.
 244.784 +     *
 244.785 +     * <p> Unix lines mode can also be enabled via the embedded flag
 244.786 +     * expression&nbsp;<tt>(?d)</tt>.
 244.787 +     */
 244.788 +    public static final int UNIX_LINES = 0x01;
 244.789 +
 244.790 +    /**
 244.791 +     * Enables case-insensitive matching.
 244.792 +     *
 244.793 +     * <p> By default, case-insensitive matching assumes that only characters
 244.794 +     * in the US-ASCII charset are being matched.  Unicode-aware
 244.795 +     * case-insensitive matching can be enabled by specifying the {@link
 244.796 +     * #UNICODE_CASE} flag in conjunction with this flag.
 244.797 +     *
 244.798 +     * <p> Case-insensitive matching can also be enabled via the embedded flag
 244.799 +     * expression&nbsp;<tt>(?i)</tt>.
 244.800 +     *
 244.801 +     * <p> Specifying this flag may impose a slight performance penalty.  </p>
 244.802 +     */
 244.803 +    public static final int CASE_INSENSITIVE = 0x02;
 244.804 +
 244.805 +    /**
 244.806 +     * Permits whitespace and comments in pattern.
 244.807 +     *
 244.808 +     * <p> In this mode, whitespace is ignored, and embedded comments starting
 244.809 +     * with <tt>#</tt> are ignored until the end of a line.
 244.810 +     *
 244.811 +     * <p> Comments mode can also be enabled via the embedded flag
 244.812 +     * expression&nbsp;<tt>(?x)</tt>.
 244.813 +     */
 244.814 +    public static final int COMMENTS = 0x04;
 244.815 +
 244.816 +    /**
 244.817 +     * Enables multiline mode.
 244.818 +     *
 244.819 +     * <p> In multiline mode the expressions <tt>^</tt> and <tt>$</tt> match
 244.820 +     * just after or just before, respectively, a line terminator or the end of
 244.821 +     * the input sequence.  By default these expressions only match at the
 244.822 +     * beginning and the end of the entire input sequence.
 244.823 +     *
 244.824 +     * <p> Multiline mode can also be enabled via the embedded flag
 244.825 +     * expression&nbsp;<tt>(?m)</tt>.  </p>
 244.826 +     */
 244.827 +    public static final int MULTILINE = 0x08;
 244.828 +
 244.829 +    /**
 244.830 +     * Enables literal parsing of the pattern.
 244.831 +     *
 244.832 +     * <p> When this flag is specified then the input string that specifies
 244.833 +     * the pattern is treated as a sequence of literal characters.
 244.834 +     * Metacharacters or escape sequences in the input sequence will be
 244.835 +     * given no special meaning.
 244.836 +     *
 244.837 +     * <p>The flags CASE_INSENSITIVE and UNICODE_CASE retain their impact on
 244.838 +     * matching when used in conjunction with this flag. The other flags
 244.839 +     * become superfluous.
 244.840 +     *
 244.841 +     * <p> There is no embedded flag character for enabling literal parsing.
 244.842 +     * @since 1.5
 244.843 +     */
 244.844 +    public static final int LITERAL = 0x10;
 244.845 +
 244.846 +    /**
 244.847 +     * Enables dotall mode.
 244.848 +     *
 244.849 +     * <p> In dotall mode, the expression <tt>.</tt> matches any character,
 244.850 +     * including a line terminator.  By default this expression does not match
 244.851 +     * line terminators.
 244.852 +     *
 244.853 +     * <p> Dotall mode can also be enabled via the embedded flag
 244.854 +     * expression&nbsp;<tt>(?s)</tt>.  (The <tt>s</tt> is a mnemonic for
 244.855 +     * "single-line" mode, which is what this is called in Perl.)  </p>
 244.856 +     */
 244.857 +    public static final int DOTALL = 0x20;
 244.858 +
 244.859 +    /**
 244.860 +     * Enables Unicode-aware case folding.
 244.861 +     *
 244.862 +     * <p> When this flag is specified then case-insensitive matching, when
 244.863 +     * enabled by the {@link #CASE_INSENSITIVE} flag, is done in a manner
 244.864 +     * consistent with the Unicode Standard.  By default, case-insensitive
 244.865 +     * matching assumes that only characters in the US-ASCII charset are being
 244.866 +     * matched.
 244.867 +     *
 244.868 +     * <p> Unicode-aware case folding can also be enabled via the embedded flag
 244.869 +     * expression&nbsp;<tt>(?u)</tt>.
 244.870 +     *
 244.871 +     * <p> Specifying this flag may impose a performance penalty.  </p>
 244.872 +     */
 244.873 +    public static final int UNICODE_CASE = 0x40;
 244.874 +
 244.875 +    /**
 244.876 +     * Enables canonical equivalence.
 244.877 +     *
 244.878 +     * <p> When this flag is specified then two characters will be considered
 244.879 +     * to match if, and only if, their full canonical decompositions match.
 244.880 +     * The expression <tt>"a&#92;u030A"</tt>, for example, will match the
 244.881 +     * string <tt>"&#92;u00E5"</tt> when this flag is specified.  By default,
 244.882 +     * matching does not take canonical equivalence into account.
 244.883 +     *
 244.884 +     * <p> There is no embedded flag character for enabling canonical
 244.885 +     * equivalence.
 244.886 +     *
 244.887 +     * <p> Specifying this flag may impose a performance penalty.  </p>
 244.888 +     */
 244.889 +    public static final int CANON_EQ = 0x80;
 244.890 +
 244.891 +    /**
 244.892 +     * Enables the Unicode version of <i>Predefined character classes</i> and
 244.893 +     * <i>POSIX character classes</i>.
 244.894 +     *
 244.895 +     * <p> When this flag is specified then the (US-ASCII only)
 244.896 +     * <i>Predefined character classes</i> and <i>POSIX character classes</i>
 244.897 +     * are in conformance with
 244.898 +     * <a href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
 244.899 +     * Standard #18: Unicode Regular Expression</i></a>
 244.900 +     * <i>Annex C: Compatibility Properties</i>.
 244.901 +     * <p>
 244.902 +     * The UNICODE_CHARACTER_CLASS mode can also be enabled via the embedded
 244.903 +     * flag expression&nbsp;<tt>(?U)</tt>.
 244.904 +     * <p>
 244.905 +     * The flag implies UNICODE_CASE, that is, it enables Unicode-aware case
 244.906 +     * folding.
 244.907 +     * <p>
 244.908 +     * Specifying this flag may impose a performance penalty.  </p>
 244.909 +     * @since 1.7
 244.910 +     */
 244.911 +    public static final int UNICODE_CHARACTER_CLASS = 0x100;
 244.912 +
 244.913 +    /* Pattern has only two serialized components: The pattern string
 244.914 +     * and the flags, which are all that is needed to recompile the pattern
 244.915 +     * when it is deserialized.
 244.916 +     */
 244.917 +
 244.918 +    /** use serialVersionUID from Merlin b59 for interoperability */
 244.919 +    private static final long serialVersionUID = 5073258162644648461L;
 244.920 +
 244.921 +    /**
 244.922 +     * The original regular-expression pattern string.
 244.923 +     *
 244.924 +     * @serial
 244.925 +     */
 244.926 +    private String pattern;
 244.927 +
 244.928 +    /**
 244.929 +     * The original pattern flags.
 244.930 +     *
 244.931 +     * @serial
 244.932 +     */
 244.933 +    private int flags;
 244.934 +
 244.935 +    /**
 244.936 +     * Boolean indicating this Pattern is compiled; this is necessary in order
 244.937 +     * to lazily compile deserialized Patterns.
 244.938 +     */
 244.939 +    private transient volatile boolean compiled = false;
 244.940 +
 244.941 +    /**
 244.942 +     * The normalized pattern string.
 244.943 +     */
 244.944 +    private transient String normalizedPattern;
 244.945 +
 244.946 +    /**
 244.947 +     * The starting point of state machine for the find operation.  This allows
 244.948 +     * a match to start anywhere in the input.
 244.949 +     */
 244.950 +    transient Node root;
 244.951 +
 244.952 +    /**
 244.953 +     * The root of object tree for a match operation.  The pattern is matched
 244.954 +     * at the beginning.  This may include a find that uses BnM or a First
 244.955 +     * node.
 244.956 +     */
 244.957 +    transient Node matchRoot;
 244.958 +
 244.959 +    /**
 244.960 +     * Temporary storage used by parsing pattern slice.
 244.961 +     */
 244.962 +    transient int[] buffer;
 244.963 +
 244.964 +    /**
 244.965 +     * Map the "name" of the "named capturing group" to its group id
 244.966 +     * node.
 244.967 +     */
 244.968 +    transient volatile Map<String, Integer> namedGroups;
 244.969 +
 244.970 +    /**
 244.971 +     * Temporary storage used while parsing group references.
 244.972 +     */
 244.973 +    transient GroupHead[] groupNodes;
 244.974 +
 244.975 +    /**
 244.976 +     * Temporary null terminated code point array used by pattern compiling.
 244.977 +     */
 244.978 +    private transient int[] temp;
 244.979 +
 244.980 +    /**
 244.981 +     * The number of capturing groups in this Pattern. Used by matchers to
 244.982 +     * allocate storage needed to perform a match.
 244.983 +     */
 244.984 +    transient int capturingGroupCount;
 244.985 +
 244.986 +    /**
 244.987 +     * The local variable count used by parsing tree. Used by matchers to
 244.988 +     * allocate storage needed to perform a match.
 244.989 +     */
 244.990 +    transient int localCount;
 244.991 +
 244.992 +    /**
 244.993 +     * Index into the pattern string that keeps track of how much has been
 244.994 +     * parsed.
 244.995 +     */
 244.996 +    private transient int cursor;
 244.997 +
 244.998 +    /**
 244.999 +     * Holds the length of the pattern string.
244.1000 +     */
244.1001 +    private transient int patternLength;
244.1002 +
244.1003 +    /**
244.1004 +     * If the Start node might possibly match supplementary characters.
244.1005 +     * It is set to true during compiling if
244.1006 +     * (1) There is supplementary char in pattern, or
244.1007 +     * (2) There is complement node of Category or Block
244.1008 +     */
244.1009 +    private transient boolean hasSupplementary;
244.1010 +
244.1011 +    /**
244.1012 +     * Compiles the given regular expression into a pattern.  </p>
244.1013 +     *
244.1014 +     * @param  regex
244.1015 +     *         The expression to be compiled
244.1016 +     *
244.1017 +     * @throws  PatternSyntaxException
244.1018 +     *          If the expression's syntax is invalid
244.1019 +     */
244.1020 +    public static Pattern compile(String regex) {
244.1021 +        return new Pattern(regex, 0);
244.1022 +    }
244.1023 +
244.1024 +    /**
244.1025 +     * Compiles the given regular expression into a pattern with the given
244.1026 +     * flags.  </p>
244.1027 +     *
244.1028 +     * @param  regex
244.1029 +     *         The expression to be compiled
244.1030 +     *
244.1031 +     * @param  flags
244.1032 +     *         Match flags, a bit mask that may include
244.1033 +     *         {@link #CASE_INSENSITIVE}, {@link #MULTILINE}, {@link #DOTALL},
244.1034 +     *         {@link #UNICODE_CASE}, {@link #CANON_EQ}, {@link #UNIX_LINES},
244.1035 +     *         {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
244.1036 +     *         and {@link #COMMENTS}
244.1037 +     *
244.1038 +     * @throws  IllegalArgumentException
244.1039 +     *          If bit values other than those corresponding to the defined
244.1040 +     *          match flags are set in <tt>flags</tt>
244.1041 +     *
244.1042 +     * @throws  PatternSyntaxException
244.1043 +     *          If the expression's syntax is invalid
244.1044 +     */
244.1045 +    public static Pattern compile(String regex, int flags) {
244.1046 +        return new Pattern(regex, flags);
244.1047 +    }
244.1048 +
244.1049 +    /**
244.1050 +     * Returns the regular expression from which this pattern was compiled.
244.1051 +     * </p>
244.1052 +     *
244.1053 +     * @return  The source of this pattern
244.1054 +     */
244.1055 +    public String pattern() {
244.1056 +        return pattern;
244.1057 +    }
244.1058 +
244.1059 +    /**
244.1060 +     * <p>Returns the string representation of this pattern. This
244.1061 +     * is the regular expression from which this pattern was
244.1062 +     * compiled.</p>
244.1063 +     *
244.1064 +     * @return  The string representation of this pattern
244.1065 +     * @since 1.5
244.1066 +     */
244.1067 +    public String toString() {
244.1068 +        return pattern;
244.1069 +    }
244.1070 +
244.1071 +    /**
244.1072 +     * Creates a matcher that will match the given input against this pattern.
244.1073 +     * </p>
244.1074 +     *
244.1075 +     * @param  input
244.1076 +     *         The character sequence to be matched
244.1077 +     *
244.1078 +     * @return  A new matcher for this pattern
244.1079 +     */
244.1080 +    public Matcher matcher(CharSequence input) {
244.1081 +        if (!compiled) {
244.1082 +            synchronized(this) {
244.1083 +                if (!compiled)
244.1084 +                    compile();
244.1085 +            }
244.1086 +        }
244.1087 +        Matcher m = new Matcher(this, input);
244.1088 +        return m;
244.1089 +    }
244.1090 +
244.1091 +    /**
244.1092 +     * Returns this pattern's match flags.  </p>
244.1093 +     *
244.1094 +     * @return  The match flags specified when this pattern was compiled
244.1095 +     */
244.1096 +    public int flags() {
244.1097 +        return flags;
244.1098 +    }
244.1099 +
244.1100 +    /**
244.1101 +     * Compiles the given regular expression and attempts to match the given
244.1102 +     * input against it.
244.1103 +     *
244.1104 +     * <p> An invocation of this convenience method of the form
244.1105 +     *
244.1106 +     * <blockquote><pre>
244.1107 +     * Pattern.matches(regex, input);</pre></blockquote>
244.1108 +     *
244.1109 +     * behaves in exactly the same way as the expression
244.1110 +     *
244.1111 +     * <blockquote><pre>
244.1112 +     * Pattern.compile(regex).matcher(input).matches()</pre></blockquote>
244.1113 +     *
244.1114 +     * <p> If a pattern is to be used multiple times, compiling it once and reusing
244.1115 +     * it will be more efficient than invoking this method each time.  </p>
244.1116 +     *
244.1117 +     * @param  regex
244.1118 +     *         The expression to be compiled
244.1119 +     *
244.1120 +     * @param  input
244.1121 +     *         The character sequence to be matched
244.1122 +     *
244.1123 +     * @throws  PatternSyntaxException
244.1124 +     *          If the expression's syntax is invalid
244.1125 +     */
244.1126 +    public static boolean matches(String regex, CharSequence input) {
244.1127 +        Pattern p = Pattern.compile(regex);
244.1128 +        Matcher m = p.matcher(input);
244.1129 +        return m.matches();
244.1130 +    }
244.1131 +
244.1132 +    /**
244.1133 +     * Splits the given input sequence around matches of this pattern.
244.1134 +     *
244.1135 +     * <p> The array returned by this method contains each substring of the
244.1136 +     * input sequence that is terminated by another subsequence that matches
244.1137 +     * this pattern or is terminated by the end of the input sequence.  The
244.1138 +     * substrings in the array are in the order in which they occur in the
244.1139 +     * input.  If this pattern does not match any subsequence of the input then
244.1140 +     * the resulting array has just one element, namely the input sequence in
244.1141 +     * string form.
244.1142 +     *
244.1143 +     * <p> The <tt>limit</tt> parameter controls the number of times the
244.1144 +     * pattern is applied and therefore affects the length of the resulting
244.1145 +     * array.  If the limit <i>n</i> is greater than zero then the pattern
244.1146 +     * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
244.1147 +     * length will be no greater than <i>n</i>, and the array's last entry
244.1148 +     * will contain all input beyond the last matched delimiter.  If <i>n</i>
244.1149 +     * is non-positive then the pattern will be applied as many times as
244.1150 +     * possible and the array can have any length.  If <i>n</i> is zero then
244.1151 +     * the pattern will be applied as many times as possible, the array can
244.1152 +     * have any length, and trailing empty strings will be discarded.
244.1153 +     *
244.1154 +     * <p> The input <tt>"boo:and:foo"</tt>, for example, yields the following
244.1155 +     * results with these parameters:
244.1156 +     *
244.1157 +     * <blockquote><table cellpadding=1 cellspacing=0
244.1158 +     *              summary="Split examples showing regex, limit, and result">
244.1159 +     * <tr><th><P align="left"><i>Regex&nbsp;&nbsp;&nbsp;&nbsp;</i></th>
244.1160 +     *     <th><P align="left"><i>Limit&nbsp;&nbsp;&nbsp;&nbsp;</i></th>
244.1161 +     *     <th><P align="left"><i>Result&nbsp;&nbsp;&nbsp;&nbsp;</i></th></tr>
244.1162 +     * <tr><td align=center>:</td>
244.1163 +     *     <td align=center>2</td>
244.1164 +     *     <td><tt>{ "boo", "and:foo" }</tt></td></tr>
244.1165 +     * <tr><td align=center>:</td>
244.1166 +     *     <td align=center>5</td>
244.1167 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
244.1168 +     * <tr><td align=center>:</td>
244.1169 +     *     <td align=center>-2</td>
244.1170 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
244.1171 +     * <tr><td align=center>o</td>
244.1172 +     *     <td align=center>5</td>
244.1173 +     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
244.1174 +     * <tr><td align=center>o</td>
244.1175 +     *     <td align=center>-2</td>
244.1176 +     *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
244.1177 +     * <tr><td align=center>o</td>
244.1178 +     *     <td align=center>0</td>
244.1179 +     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
244.1180 +     * </table></blockquote>
244.1181 +     *
244.1182 +     *
244.1183 +     * @param  input
244.1184 +     *         The character sequence to be split
244.1185 +     *
244.1186 +     * @param  limit
244.1187 +     *         The result threshold, as described above
244.1188 +     *
244.1189 +     * @return  The array of strings computed by splitting the input
244.1190 +     *          around matches of this pattern
244.1191 +     */
244.1192 +    public String[] split(CharSequence input, int limit) {
244.1193 +        int index = 0;
244.1194 +        boolean matchLimited = limit > 0;
244.1195 +        ArrayList<String> matchList = new ArrayList<>();
244.1196 +        Matcher m = matcher(input);
244.1197 +
244.1198 +        // Add segments before each match found
244.1199 +        while(m.find()) {
244.1200 +            if (!matchLimited || matchList.size() < limit - 1) {
244.1201 +                String match = input.subSequence(index, m.start()).toString();
244.1202 +                matchList.add(match);
244.1203 +                index = m.end();
244.1204 +            } else if (matchList.size() == limit - 1) { // last one
244.1205 +                String match = input.subSequence(index,
244.1206 +                                                 input.length()).toString();
244.1207 +                matchList.add(match);
244.1208 +                index = m.end();
244.1209 +            }
244.1210 +        }
244.1211 +
244.1212 +        // If no match was found, return this
244.1213 +        if (index == 0)
244.1214 +            return new String[] {input.toString()};
244.1215 +
244.1216 +        // Add remaining segment
244.1217 +        if (!matchLimited || matchList.size() < limit)
244.1218 +            matchList.add(input.subSequence(index, input.length()).toString());
244.1219 +
244.1220 +        // Construct result
244.1221 +        int resultSize = matchList.size();
244.1222 +        if (limit == 0)
244.1223 +            while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
244.1224 +                resultSize--;
244.1225 +        String[] result = new String[resultSize];
244.1226 +        return matchList.subList(0, resultSize).toArray(result);
244.1227 +    }
244.1228 +
244.1229 +    /**
244.1230 +     * Splits the given input sequence around matches of this pattern.
244.1231 +     *
244.1232 +     * <p> This method works as if by invoking the two-argument {@link
244.1233 +     * #split(java.lang.CharSequence, int) split} method with the given input
244.1234 +     * sequence and a limit argument of zero.  Trailing empty strings are
244.1235 +     * therefore not included in the resulting array. </p>
244.1236 +     *
244.1237 +     * <p> The input <tt>"boo:and:foo"</tt>, for example, yields the following
244.1238 +     * results with these expressions:
244.1239 +     *
244.1240 +     * <blockquote><table cellpadding=1 cellspacing=0
244.1241 +     *              summary="Split examples showing regex and result">
244.1242 +     * <tr><th><P align="left"><i>Regex&nbsp;&nbsp;&nbsp;&nbsp;</i></th>
244.1243 +     *     <th><P align="left"><i>Result</i></th></tr>
244.1244 +     * <tr><td align=center>:</td>
244.1245 +     *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
244.1246 +     * <tr><td align=center>o</td>
244.1247 +     *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
244.1248 +     * </table></blockquote>
244.1249 +     *
244.1250 +     *
244.1251 +     * @param  input
244.1252 +     *         The character sequence to be split
244.1253 +     *
244.1254 +     * @return  The array of strings computed by splitting the input
244.1255 +     *          around matches of this pattern
244.1256 +     */
244.1257 +    public String[] split(CharSequence input) {
244.1258 +        return split(input, 0);
244.1259 +    }
244.1260 +
244.1261 +    /**
244.1262 +     * Returns a literal pattern <code>String</code> for the specified
244.1263 +     * <code>String</code>.
244.1264 +     *
244.1265 +     * <p>This method produces a <code>String</code> that can be used to
244.1266 +     * create a <code>Pattern</code> that would match the string
244.1267 +     * <code>s</code> as if it were a literal pattern.</p> Metacharacters
244.1268 +     * or escape sequences in the input sequence will be given no special
244.1269 +     * meaning.
244.1270 +     *
244.1271 +     * @param  s The string to be literalized
244.1272 +     * @return  A literal string replacement
244.1273 +     * @since 1.5
244.1274 +     */
244.1275 +    public static String quote(String s) {
244.1276 +        int slashEIndex = s.indexOf("\\E");
244.1277 +        if (slashEIndex == -1)
244.1278 +            return "\\Q" + s + "\\E";
244.1279 +
244.1280 +        StringBuilder sb = new StringBuilder(s.length() * 2);
244.1281 +        sb.append("\\Q");
244.1282 +        slashEIndex = 0;
244.1283 +        int current = 0;
244.1284 +        while ((slashEIndex = s.indexOf("\\E", current)) != -1) {
244.1285 +            sb.append(s.substring(current, slashEIndex));
244.1286 +            current = slashEIndex + 2;
244.1287 +            sb.append("\\E\\\\E\\Q");
244.1288 +        }
244.1289 +        sb.append(s.substring(current, s.length()));
244.1290 +        sb.append("\\E");
244.1291 +        return sb.toString();
244.1292 +    }
244.1293 +
244.1294 +    /**
244.1295 +     * Recompile the Pattern instance from a stream.  The original pattern
244.1296 +     * string is read in and the object tree is recompiled from it.
244.1297 +     */
244.1298 +    private void readObject(java.io.ObjectInputStream s)
244.1299 +        throws java.io.IOException, ClassNotFoundException {
244.1300 +
244.1301 +        // Read in all fields
244.1302 +        s.defaultReadObject();
244.1303 +
244.1304 +        // Initialize counts
244.1305 +        capturingGroupCount = 1;
244.1306 +        localCount = 0;
244.1307 +
244.1308 +        // if length > 0, the Pattern is lazily compiled
244.1309 +        compiled = false;
244.1310 +        if (pattern.length() == 0) {
244.1311 +            root = new Start(lastAccept);
244.1312 +            matchRoot = lastAccept;
244.1313 +            compiled = true;
244.1314 +        }
244.1315 +    }
244.1316 +
244.1317 +    /**
244.1318 +     * This private constructor is used to create all Patterns. The pattern
244.1319 +     * string and match flags are all that is needed to completely describe
244.1320 +     * a Pattern. An empty pattern string results in an object tree with
244.1321 +     * only a Start node and a LastNode node.
244.1322 +     */
244.1323 +    private Pattern(String p, int f) {
244.1324 +        pattern = p;
244.1325 +        flags = f;
244.1326 +
244.1327 +        // to use UNICODE_CASE if UNICODE_CHARACTER_CLASS present
244.1328 +        if ((flags & UNICODE_CHARACTER_CLASS) != 0)
244.1329 +            flags |= UNICODE_CASE;
244.1330 +
244.1331 +        // Reset group index count
244.1332 +        capturingGroupCount = 1;
244.1333 +        localCount = 0;
244.1334 +
244.1335 +        if (pattern.length() > 0) {
244.1336 +            compile();
244.1337 +        } else {
244.1338 +            root = new Start(lastAccept);
244.1339 +            matchRoot = lastAccept;
244.1340 +        }
244.1341 +    }
244.1342 +
244.1343 +    /**
244.1344 +     * The pattern is converted to normalizedD form and then a pure group
244.1345 +     * is constructed to match canonical equivalences of the characters.
244.1346 +     */
244.1347 +    private void normalize() {
244.1348 +        boolean inCharClass = false;
244.1349 +        int lastCodePoint = -1;
244.1350 +
244.1351 +        // Convert pattern into normalizedD form
244.1352 +        normalizedPattern = Normalizer.normalize(pattern, Normalizer.NFD);
244.1353 +        patternLength = normalizedPattern.length();
244.1354 +
244.1355 +        // Modify pattern to match canonical equivalences
244.1356 +        StringBuilder newPattern = new StringBuilder(patternLength);
244.1357 +        for(int i=0; i<patternLength; ) {
244.1358 +            int c = normalizedPattern.codePointAt(i);
244.1359 +            StringBuilder sequenceBuffer;
244.1360 +            if ((Character.getType(c) == Character.NON_SPACING_MARK)
244.1361 +                && (lastCodePoint != -1)) {
244.1362 +                sequenceBuffer = new StringBuilder();
244.1363 +                sequenceBuffer.appendCodePoint(lastCodePoint);
244.1364 +                sequenceBuffer.appendCodePoint(c);
244.1365 +                while(Character.getType(c) == Character.NON_SPACING_MARK) {
244.1366 +                    i += Character.charCount(c);
244.1367 +                    if (i >= patternLength)
244.1368 +                        break;
244.1369 +                    c = normalizedPattern.codePointAt(i);
244.1370 +                    sequenceBuffer.appendCodePoint(c);
244.1371 +                }
244.1372 +                String ea = produceEquivalentAlternation(
244.1373 +                                               sequenceBuffer.toString());
244.1374 +                newPattern.setLength(newPattern.length()-Character.charCount(lastCodePoint));
244.1375 +                newPattern.append("(?:").append(ea).append(")");
244.1376 +            } else if (c == '[' && lastCodePoint != '\\') {
244.1377 +                i = normalizeCharClass(newPattern, i);
244.1378 +            } else {
244.1379 +                newPattern.appendCodePoint(c);
244.1380 +            }
244.1381 +            lastCodePoint = c;
244.1382 +            i += Character.charCount(c);
244.1383 +        }
244.1384 +        normalizedPattern = newPattern.toString();
244.1385 +    }
244.1386 +
244.1387 +    /**
244.1388 +     * Complete the character class being parsed and add a set
244.1389 +     * of alternations to it that will match the canonical equivalences
244.1390 +     * of the characters within the class.
244.1391 +     */
244.1392 +    private int normalizeCharClass(StringBuilder newPattern, int i) {
244.1393 +        StringBuilder charClass = new StringBuilder();
244.1394 +        StringBuilder eq = null;
244.1395 +        int lastCodePoint = -1;
244.1396 +        String result;
244.1397 +
244.1398 +        i++;
244.1399 +        charClass.append("[");
244.1400 +        while(true) {
244.1401 +            int c = normalizedPattern.codePointAt(i);
244.1402 +            StringBuilder sequenceBuffer;
244.1403 +
244.1404 +            if (c == ']' && lastCodePoint != '\\') {
244.1405 +                charClass.append((char)c);
244.1406 +                break;
244.1407 +            } else if (Character.getType(c) == Character.NON_SPACING_MARK) {
244.1408 +                sequenceBuffer = new StringBuilder();
244.1409 +                sequenceBuffer.appendCodePoint(lastCodePoint);
244.1410 +                while(Character.getType(c) == Character.NON_SPACING_MARK) {
244.1411 +                    sequenceBuffer.appendCodePoint(c);
244.1412 +                    i += Character.charCount(c);
244.1413 +                    if (i >= normalizedPattern.length())
244.1414 +                        break;
244.1415 +                    c = normalizedPattern.codePointAt(i);
244.1416 +                }
244.1417 +                String ea = produceEquivalentAlternation(
244.1418 +                                                  sequenceBuffer.toString());
244.1419 +
244.1420 +                charClass.setLength(charClass.length()-Character.charCount(lastCodePoint));
244.1421 +                if (eq == null)
244.1422 +                    eq = new StringBuilder();
244.1423 +                eq.append('|');
244.1424 +                eq.append(ea);
244.1425 +            } else {
244.1426 +                charClass.appendCodePoint(c);
244.1427 +                i++;
244.1428 +            }
244.1429 +            if (i == normalizedPattern.length())
244.1430 +                throw error("Unclosed character class");
244.1431 +            lastCodePoint = c;
244.1432 +        }
244.1433 +
244.1434 +        if (eq != null) {
244.1435 +            result = "(?:"+charClass.toString()+eq.toString()+")";
244.1436 +        } else {
244.1437 +            result = charClass.toString();
244.1438 +        }
244.1439 +
244.1440 +        newPattern.append(result);
244.1441 +        return i;
244.1442 +    }
244.1443 +
244.1444 +    /**
244.1445 +     * Given a specific sequence composed of a regular character and
244.1446 +     * combining marks that follow it, produce the alternation that will
244.1447 +     * match all canonical equivalences of that sequence.
244.1448 +     */
244.1449 +    private String produceEquivalentAlternation(String source) {
244.1450 +        int len = countChars(source, 0, 1);
244.1451 +        if (source.length() == len)
244.1452 +            // source has one character.
244.1453 +            return source;
244.1454 +
244.1455 +        String base = source.substring(0,len);
244.1456 +        String combiningMarks = source.substring(len);
244.1457 +
244.1458 +        String[] perms = producePermutations(combiningMarks);
244.1459 +        StringBuilder result = new StringBuilder(source);
244.1460 +
244.1461 +        // Add combined permutations
244.1462 +        for(int x=0; x<perms.length; x++) {
244.1463 +            String next = base + perms[x];
244.1464 +            if (x>0)
244.1465 +                result.append("|"+next);
244.1466 +            next = composeOneStep(next);
244.1467 +            if (next != null)
244.1468 +                result.append("|"+produceEquivalentAlternation(next));
244.1469 +        }
244.1470 +        return result.toString();
244.1471 +    }
244.1472 +
244.1473 +    /**
244.1474 +     * Returns an array of strings that have all the possible
244.1475 +     * permutations of the characters in the input string.
244.1476 +     * This is used to get a list of all possible orderings
244.1477 +     * of a set of combining marks. Note that some of the permutations
244.1478 +     * are invalid because of combining class collisions, and these
244.1479 +     * possibilities must be removed because they are not canonically
244.1480 +     * equivalent.
244.1481 +     */
244.1482 +    private String[] producePermutations(String input) {
244.1483 +        if (input.length() == countChars(input, 0, 1))
244.1484 +            return new String[] {input};
244.1485 +
244.1486 +        if (input.length() == countChars(input, 0, 2)) {
244.1487 +            int c0 = Character.codePointAt(input, 0);
244.1488 +            int c1 = Character.codePointAt(input, Character.charCount(c0));
244.1489 +            if (getClass(c1) == getClass(c0)) {
244.1490 +                return new String[] {input};
244.1491 +            }
244.1492 +            String[] result = new String[2];
244.1493 +            result[0] = input;
244.1494 +            StringBuilder sb = new StringBuilder(2);
244.1495 +            sb.appendCodePoint(c1);
244.1496 +            sb.appendCodePoint(c0);
244.1497 +            result[1] = sb.toString();
244.1498 +            return result;
244.1499 +        }
244.1500 +
244.1501 +        int length = 1;
244.1502 +        int nCodePoints = countCodePoints(input);
244.1503 +        for(int x=1; x<nCodePoints; x++)
244.1504 +            length = length * (x+1);
244.1505 +
244.1506 +        String[] temp = new String[length];
244.1507 +
244.1508 +        int combClass[] = new int[nCodePoints];
244.1509 +        for(int x=0, i=0; x<nCodePoints; x++) {
244.1510 +            int c = Character.codePointAt(input, i);
244.1511 +            combClass[x] = getClass(c);
244.1512 +            i +=  Character.charCount(c);
244.1513 +        }
244.1514 +
244.1515 +        // For each char, take it out and add the permutations
244.1516 +        // of the remaining chars
244.1517 +        int index = 0;
244.1518 +        int len;
244.1519 +        // offset maintains the index in code units.
244.1520 +loop:   for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
244.1521 +            len = countChars(input, offset, 1);
244.1522 +            boolean skip = false;
244.1523 +            for(int y=x-1; y>=0; y--) {
244.1524 +                if (combClass[y] == combClass[x]) {
244.1525 +                    continue loop;
244.1526 +                }
244.1527 +            }
244.1528 +            StringBuilder sb = new StringBuilder(input);
244.1529 +            String otherChars = sb.delete(offset, offset+len).toString();
244.1530 +            String[] subResult = producePermutations(otherChars);
244.1531 +
244.1532 +            String prefix = input.substring(offset, offset+len);
244.1533 +            for(int y=0; y<subResult.length; y++)
244.1534 +                temp[index++] =  prefix + subResult[y];
244.1535 +        }
244.1536 +        String[] result = new String[index];
244.1537 +        for (int x=0; x<index; x++)
244.1538 +            result[x] = temp[x];
244.1539 +        return result;
244.1540 +    }
244.1541 +
244.1542 +    private int getClass(int c) {
244.1543 +        return Normalizer.getCombiningClass(c);
244.1544 +    }
244.1545 +
244.1546 +    /**
244.1547 +     * Attempts to compose input by combining the first character
244.1548 +     * with the first combining mark following it. Returns a String
244.1549 +     * that is the composition of the leading character with its first
244.1550 +     * combining mark followed by the remaining combining marks. Returns
244.1551 +     * null if the first two characters cannot be further composed.
244.1552 +     */
244.1553 +    private String composeOneStep(String input) {
244.1554 +        int len = countChars(input, 0, 2);
244.1555 +        String firstTwoCharacters = input.substring(0, len);
244.1556 +        String result = Normalizer.normalize(firstTwoCharacters, Normalizer.NFC);
244.1557 +
244.1558 +        if (result.equals(firstTwoCharacters))
244.1559 +            return null;
244.1560 +        else {
244.1561 +            String remainder = input.substring(len);
244.1562 +            return result + remainder;
244.1563 +        }
244.1564 +    }
244.1565 +
244.1566 +    /**
244.1567 +     * Preprocess any \Q...\E sequences in `temp', meta-quoting them.
244.1568 +     * See the description of `quotemeta' in perlfunc(1).
244.1569 +     */
244.1570 +    private void RemoveQEQuoting() {
244.1571 +        final int pLen = patternLength;
244.1572 +        int i = 0;
244.1573 +        while (i < pLen-1) {
244.1574 +            if (temp[i] != '\\')
244.1575 +                i += 1;
244.1576 +            else if (temp[i + 1] != 'Q')
244.1577 +                i += 2;
244.1578 +            else
244.1579 +                break;
244.1580 +        }
244.1581 +        if (i >= pLen - 1)    // No \Q sequence found
244.1582 +            return;
244.1583 +        int j = i;
244.1584 +        i += 2;
244.1585 +        int[] newtemp = new int[j + 2*(pLen-i) + 2];
244.1586 +        System.arraycopy(temp, 0, newtemp, 0, j);
244.1587 +
244.1588 +        boolean inQuote = true;
244.1589 +        while (i < pLen) {
244.1590 +            int c = temp[i++];
244.1591 +            if (! ASCII.isAscii(c) || ASCII.isAlnum(c)) {
244.1592 +                newtemp[j++] = c;
244.1593 +            } else if (c != '\\') {
244.1594 +                if (inQuote) newtemp[j++] = '\\';
244.1595 +                newtemp[j++] = c;
244.1596 +            } else if (inQuote) {
244.1597 +                if (temp[i] == 'E') {
244.1598 +                    i++;
244.1599 +                    inQuote = false;
244.1600 +                } else {
244.1601 +                    newtemp[j++] = '\\';
244.1602 +                    newtemp[j++] = '\\';
244.1603 +                }
244.1604 +            } else {
244.1605 +                if (temp[i] == 'Q') {
244.1606 +                    i++;
244.1607 +                    inQuote = true;
244.1608 +                } else {
244.1609 +                    newtemp[j++] = c;
244.1610 +                    if (i != pLen)
244.1611 +                        newtemp[j++] = temp[i++];
244.1612 +                }
244.1613 +            }
244.1614 +        }
244.1615 +
244.1616 +        patternLength = j;
244.1617 +        temp = Arrays.copyOf(newtemp, j + 2); // double zero termination
244.1618 +    }
244.1619 +
244.1620 +    /**
244.1621 +     * Copies regular expression to an int array and invokes the parsing
244.1622 +     * of the expression which will create the object tree.
244.1623 +     */
244.1624 +    private void compile() {
244.1625 +        // Handle canonical equivalences
244.1626 +        if (has(CANON_EQ) && !has(LITERAL)) {
244.1627 +            normalize();
244.1628 +        } else {
244.1629 +            normalizedPattern = pattern;
244.1630 +        }
244.1631 +        patternLength = normalizedPattern.length();
244.1632 +
244.1633 +        // Copy pattern to int array for convenience
244.1634 +        // Use double zero to terminate pattern
244.1635 +        temp = new int[patternLength + 2];
244.1636 +
244.1637 +        hasSupplementary = false;
244.1638 +        int c, count = 0;
244.1639 +        // Convert all chars into code points
244.1640 +        for (int x = 0; x < patternLength; x += Character.charCount(c)) {
244.1641 +            c = normalizedPattern.codePointAt(x);
244.1642 +            if (isSupplementary(c)) {
244.1643 +                hasSupplementary = true;
244.1644 +            }
244.1645 +            temp[count++] = c;
244.1646 +        }
244.1647 +
244.1648 +        patternLength = count;   // patternLength now in code points
244.1649 +
244.1650 +        if (! has(LITERAL))
244.1651 +            RemoveQEQuoting();
244.1652 +
244.1653 +        // Allocate all temporary objects here.
244.1654 +        buffer = new int[32];
244.1655 +        groupNodes = new GroupHead[10];
244.1656 +        namedGroups = null;
244.1657 +
244.1658 +        if (has(LITERAL)) {
244.1659 +            // Literal pattern handling
244.1660 +            matchRoot = newSlice(temp, patternLength, hasSupplementary);
244.1661 +            matchRoot.next = lastAccept;
244.1662 +        } else {
244.1663 +            // Start recursive descent parsing
244.1664 +            matchRoot = expr(lastAccept);
244.1665 +            // Check extra pattern characters
244.1666 +            if (patternLength != cursor) {
244.1667 +                if (peek() == ')') {
244.1668 +                    throw error("Unmatched closing ')'");
244.1669 +                } else {
244.1670 +                    throw error("Unexpected internal error");
244.1671 +                }
244.1672 +            }
244.1673 +        }
244.1674 +
244.1675 +        // Peephole optimization
244.1676 +        if (matchRoot instanceof Slice) {
244.1677 +            root = BnM.optimize(matchRoot);
244.1678 +            if (root == matchRoot) {
244.1679 +                root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot);
244.1680 +            }
244.1681 +        } else if (matchRoot instanceof Begin || matchRoot instanceof First) {
244.1682 +            root = matchRoot;
244.1683 +        } else {
244.1684 +            root = hasSupplementary ? new StartS(matchRoot) : new Start(matchRoot);
244.1685 +        }
244.1686 +
244.1687 +        // Release temporary storage
244.1688 +        temp = null;
244.1689 +        buffer = null;
244.1690 +        groupNodes = null;
244.1691 +        patternLength = 0;
244.1692 +        compiled = true;
244.1693 +    }
244.1694 +
244.1695 +    Map<String, Integer> namedGroups() {
244.1696 +        if (namedGroups == null)
244.1697 +            namedGroups = new HashMap<>(2);
244.1698 +        return namedGroups;
244.1699 +    }
244.1700 +
244.1701 +    /**
244.1702 +     * Used to print out a subtree of the Pattern to help with debugging.
244.1703 +     */
244.1704 +    private static void printObjectTree(Node node) {
244.1705 +        while(node != null) {
244.1706 +            if (node instanceof Prolog) {
244.1707 +                System.out.println(node);
244.1708 +                printObjectTree(((Prolog)node).loop);
244.1709 +                System.out.println("**** end contents prolog loop");
244.1710 +            } else if (node instanceof Loop) {
244.1711 +                System.out.println(node);
244.1712 +                printObjectTree(((Loop)node).body);
244.1713 +                System.out.println("**** end contents Loop body");
244.1714 +            } else if (node instanceof Curly) {
244.1715 +                System.out.println(node);
244.1716 +                printObjectTree(((Curly)node).atom);
244.1717 +                System.out.println("**** end contents Curly body");
244.1718 +            } else if (node instanceof GroupCurly) {
244.1719 +                System.out.println(node);
244.1720 +                printObjectTree(((GroupCurly)node).atom);
244.1721 +                System.out.println("**** end contents GroupCurly body");
244.1722 +            } else if (node instanceof GroupTail) {
244.1723 +                System.out.println(node);
244.1724 +                System.out.println("Tail next is "+node.next);
244.1725 +                return;
244.1726 +            } else {
244.1727 +                System.out.println(node);
244.1728 +            }
244.1729 +            node = node.next;
244.1730 +            if (node != null)
244.1731 +                System.out.println("->next:");
244.1732 +            if (node == Pattern.accept) {
244.1733 +                System.out.println("Accept Node");
244.1734 +                node = null;
244.1735 +            }
244.1736 +       }
244.1737 +    }
244.1738 +
244.1739 +    /**
244.1740 +     * Used to accumulate information about a subtree of the object graph
244.1741 +     * so that optimizations can be applied to the subtree.
244.1742 +     */
244.1743 +    static final class TreeInfo {
244.1744 +        int minLength;
244.1745 +        int maxLength;
244.1746 +        boolean maxValid;
244.1747 +        boolean deterministic;
244.1748 +
244.1749 +        TreeInfo() {
244.1750 +            reset();
244.1751 +        }
244.1752 +        void reset() {
244.1753 +            minLength = 0;
244.1754 +            maxLength = 0;
244.1755 +            maxValid = true;
244.1756 +            deterministic = true;
244.1757 +        }
244.1758 +    }
244.1759 +
244.1760 +    /*
244.1761 +     * The following private methods are mainly used to improve the
244.1762 +     * readability of the code. In order to let the Java compiler easily
244.1763 +     * inline them, we should not put many assertions or error checks in them.
244.1764 +     */
244.1765 +
244.1766 +    /**
244.1767 +     * Indicates whether a particular flag is set or not.
244.1768 +     */
244.1769 +    private boolean has(int f) {
244.1770 +        return (flags & f) != 0;
244.1771 +    }
244.1772 +
244.1773 +    /**
244.1774 +     * Match next character, signal error if failed.
244.1775 +     */
244.1776 +    private void accept(int ch, String s) {
244.1777 +        int testChar = temp[cursor++];
244.1778 +        if (has(COMMENTS))
244.1779 +            testChar = parsePastWhitespace(testChar);
244.1780 +        if (ch != testChar) {
244.1781 +            throw error(s);
244.1782 +        }
244.1783 +    }
244.1784 +
244.1785 +    /**
244.1786 +     * Mark the end of pattern with a specific character.
244.1787 +     */
244.1788 +    private void mark(int c) {
244.1789 +        temp[patternLength] = c;
244.1790 +    }
244.1791 +
244.1792 +    /**
244.1793 +     * Peek the next character, and do not advance the cursor.
244.1794 +     */
244.1795 +    private int peek() {
244.1796 +        int ch = temp[cursor];
244.1797 +        if (has(COMMENTS))
244.1798 +            ch = peekPastWhitespace(ch);
244.1799 +        return ch;
244.1800 +    }
244.1801 +
244.1802 +    /**
244.1803 +     * Read the next character, and advance the cursor by one.
244.1804 +     */
244.1805 +    private int read() {
244.1806 +        int ch = temp[cursor++];
244.1807 +        if (has(COMMENTS))
244.1808 +            ch = parsePastWhitespace(ch);
244.1809 +        return ch;
244.1810 +    }
244.1811 +
244.1812 +    /**
244.1813 +     * Read the next character, and advance the cursor by one,
244.1814 +     * ignoring the COMMENTS setting
244.1815 +     */
244.1816 +    private int readEscaped() {
244.1817 +        int ch = temp[cursor++];
244.1818 +        return ch;
244.1819 +    }
244.1820 +
244.1821 +    /**
244.1822 +     * Advance the cursor by one, and peek the next character.
244.1823 +     */
244.1824 +    private int next() {
244.1825 +        int ch = temp[++cursor];
244.1826 +        if (has(COMMENTS))
244.1827 +            ch = peekPastWhitespace(ch);
244.1828 +        return ch;
244.1829 +    }
244.1830 +
244.1831 +    /**
244.1832 +     * Advance the cursor by one, and peek the next character,
244.1833 +     * ignoring the COMMENTS setting
244.1834 +     */
244.1835 +    private int nextEscaped() {
244.1836 +        int ch = temp[++cursor];
244.1837 +        return ch;
244.1838 +    }
244.1839 +
244.1840 +    /**
244.1841 +     * If in xmode peek past whitespace and comments.
244.1842 +     */
244.1843 +    private int peekPastWhitespace(int ch) {
244.1844 +        while (ASCII.isSpace(ch) || ch == '#') {
244.1845 +            while (ASCII.isSpace(ch))
244.1846 +                ch = temp[++cursor];
244.1847 +            if (ch == '#') {
244.1848 +                ch = peekPastLine();
244.1849 +            }
244.1850 +        }
244.1851 +        return ch;
244.1852 +    }
244.1853 +
244.1854 +    /**
244.1855 +     * If in xmode parse past whitespace and comments.
244.1856 +     */
244.1857 +    private int parsePastWhitespace(int ch) {
244.1858 +        while (ASCII.isSpace(ch) || ch == '#') {
244.1859 +            while (ASCII.isSpace(ch))
244.1860 +                ch = temp[cursor++];
244.1861 +            if (ch == '#')
244.1862 +                ch = parsePastLine();
244.1863 +        }
244.1864 +        return ch;
244.1865 +    }
244.1866 +
244.1867 +    /**
244.1868 +     * xmode parse past comment to end of line.
244.1869 +     */
244.1870 +    private int parsePastLine() {
244.1871 +        int ch = temp[cursor++];
244.1872 +        while (ch != 0 && !isLineSeparator(ch))
244.1873 +            ch = temp[cursor++];
244.1874 +        return ch;
244.1875 +    }
244.1876 +
244.1877 +    /**
244.1878 +     * xmode peek past comment to end of line.
244.1879 +     */
244.1880 +    private int peekPastLine() {
244.1881 +        int ch = temp[++cursor];
244.1882 +        while (ch != 0 && !isLineSeparator(ch))
244.1883 +            ch = temp[++cursor];
244.1884 +        return ch;
244.1885 +    }
244.1886 +
244.1887 +    /**
244.1888 +     * Determines if character is a line separator in the current mode
244.1889 +     */
244.1890 +    private boolean isLineSeparator(int ch) {
244.1891 +        if (has(UNIX_LINES)) {
244.1892 +            return ch == '\n';
244.1893 +        } else {
244.1894 +            return (ch == '\n' ||
244.1895 +                    ch == '\r' ||
244.1896 +                    (ch|1) == '\u2029' ||
244.1897 +                    ch == '\u0085');
244.1898 +        }
244.1899 +    }
244.1900 +
244.1901 +    /**
244.1902 +     * Read the character after the next one, and advance the cursor by two.
244.1903 +     */
244.1904 +    private int skip() {
244.1905 +        int i = cursor;
244.1906 +        int ch = temp[i+1];
244.1907 +        cursor = i + 2;
244.1908 +        return ch;
244.1909 +    }
244.1910 +
244.1911 +    /**
244.1912 +     * Unread one next character, and retreat cursor by one.
244.1913 +     */
244.1914 +    private void unread() {
244.1915 +        cursor--;
244.1916 +    }
244.1917 +
244.1918 +    /**
244.1919 +     * Internal method used for handling all syntax errors. The pattern is
244.1920 +     * displayed with a pointer to aid in locating the syntax error.
244.1921 +     */
244.1922 +    private PatternSyntaxException error(String s) {
244.1923 +        return new PatternSyntaxException(s, normalizedPattern,  cursor - 1);
244.1924 +    }
244.1925 +
244.1926 +    /**
244.1927 +     * Determines if there is any supplementary character or unpaired
244.1928 +     * surrogate in the specified range.
244.1929 +     */
244.1930 +    private boolean findSupplementary(int start, int end) {
244.1931 +        for (int i = start; i < end; i++) {
244.1932 +            if (isSupplementary(temp[i]))
244.1933 +                return true;
244.1934 +        }
244.1935 +        return false;
244.1936 +    }
244.1937 +
244.1938 +    /**
244.1939 +     * Determines if the specified code point is a supplementary
244.1940 +     * character or unpaired surrogate.
244.1941 +     */
244.1942 +    private static final boolean isSupplementary(int ch) {
244.1943 +        return ch >= Character.MIN_SUPPLEMENTARY_CODE_POINT ||
244.1944 +               Character.isSurrogate((char)ch);
244.1945 +    }
244.1946 +
244.1947 +    /**
244.1948 +     *  The following methods handle the main parsing. They are sorted
244.1949 +     *  according to their precedence order, the lowest one first.
244.1950 +     */
244.1951 +
244.1952 +    /**
244.1953 +     * The expression is parsed with branch nodes added for alternations.
244.1954 +     * This may be called recursively to parse sub expressions that may
244.1955 +     * contain alternations.
244.1956 +     */
244.1957 +    private Node expr(Node end) {
244.1958 +        Node prev = null;
244.1959 +        Node firstTail = null;
244.1960 +        Node branchConn = null;
244.1961 +
244.1962 +        for (;;) {
244.1963 +            Node node = sequence(end);
244.1964 +            Node nodeTail = root;      //double return
244.1965 +            if (prev == null) {
244.1966 +                prev = node;
244.1967 +                firstTail = nodeTail;
244.1968 +            } else {
244.1969 +                // Branch
244.1970 +                if (branchConn == null) {
244.1971 +                    branchConn = new BranchConn();
244.1972 +                    branchConn.next = end;
244.1973 +                }
244.1974 +                if (node == end) {
244.1975 +                    // if the node returned from sequence() is "end"
244.1976 +                    // we have an empty expr, set a null atom into
244.1977 +                    // the branch to indicate to go "next" directly.
244.1978 +                    node = null;
244.1979 +                } else {
244.1980 +                    // the "tail.next" of each atom goes to branchConn
244.1981 +                    nodeTail.next = branchConn;
244.1982 +                }
244.1983 +                if (prev instanceof Branch) {
244.1984 +                    ((Branch)prev).add(node);
244.1985 +                } else {
244.1986 +                    if (prev == end) {
244.1987 +                        prev = null;
244.1988 +                    } else {
244.1989 +                        // replace the "end" with "branchConn" at its tail.next
244.1990 +                        // when put the "prev" into the branch as the first atom.
244.1991 +                        firstTail.next = branchConn;
244.1992 +                    }
244.1993 +                    prev = new Branch(prev, node, branchConn);
244.1994 +                }
244.1995 +            }
244.1996 +            if (peek() != '|') {
244.1997 +                return prev;
244.1998 +            }
244.1999 +            next();
244.2000 +        }
244.2001 +    }
244.2002 +
244.2003 +    /**
244.2004 +     * Parsing of sequences between alternations.
244.2005 +     */
244.2006 +    private Node sequence(Node end) {
244.2007 +        Node head = null;
244.2008 +        Node tail = null;
244.2009 +        Node node = null;
244.2010 +    LOOP:
244.2011 +        for (;;) {
244.2012 +            int ch = peek();
244.2013 +            switch (ch) {
244.2014 +            case '(':
244.2015 +                // Because group handles its own closure,
244.2016 +                // we need to treat it differently
244.2017 +                node = group0();
244.2018 +                // Check for comment or flag group
244.2019 +                if (node == null)
244.2020 +                    continue;
244.2021 +                if (head == null)
244.2022 +                    head = node;
244.2023 +                else
244.2024 +                    tail.next = node;
244.2025 +                // Double return: Tail was returned in root
244.2026 +                tail = root;
244.2027 +                continue;
244.2028 +            case '[':
244.2029 +                node = clazz(true);
244.2030 +                break;
244.2031 +            case '\\':
244.2032 +                ch = nextEscaped();
244.2033 +                if (ch == 'p' || ch == 'P') {
244.2034 +                    boolean oneLetter = true;
244.2035 +                    boolean comp = (ch == 'P');
244.2036 +                    ch = next(); // Consume { if present
244.2037 +                    if (ch != '{') {
244.2038 +                        unread();
244.2039 +                    } else {
244.2040 +                        oneLetter = false;
244.2041 +                    }
244.2042 +                    node = family(oneLetter, comp);
244.2043 +                } else {
244.2044 +                    unread();
244.2045 +                    node = atom();
244.2046 +                }
244.2047 +                break;
244.2048 +            case '^':
244.2049 +                next();
244.2050 +                if (has(MULTILINE)) {
244.2051 +                    if (has(UNIX_LINES))
244.2052 +                        node = new UnixCaret();
244.2053 +                    else
244.2054 +                        node = new Caret();
244.2055 +                } else {
244.2056 +                    node = new Begin();
244.2057 +                }
244.2058 +                break;
244.2059 +            case '$':
244.2060 +                next();
244.2061 +                if (has(UNIX_LINES))
244.2062 +                    node = new UnixDollar(has(MULTILINE));
244.2063 +                else
244.2064 +                    node = new Dollar(has(MULTILINE));
244.2065 +                break;
244.2066 +            case '.':
244.2067 +                next();
244.2068 +                if (has(DOTALL)) {
244.2069 +                    node = new All();
244.2070 +                } else {
244.2071 +                    if (has(UNIX_LINES))
244.2072 +                        node = new UnixDot();
244.2073 +                    else {
244.2074 +                        node = new Dot();
244.2075 +                    }
244.2076 +                }
244.2077 +                break;
244.2078 +            case '|':
244.2079 +            case ')':
244.2080 +                break LOOP;
244.2081 +            case ']': // Now interpreting dangling ] and } as literals
244.2082 +            case '}':
244.2083 +                node = atom();
244.2084 +                break;
244.2085 +            case '?':
244.2086 +            case '*':
244.2087 +            case '+':
244.2088 +                next();
244.2089 +                throw error("Dangling meta character '" + ((char)ch) + "'");
244.2090 +            case 0:
244.2091 +                if (cursor >= patternLength) {
244.2092 +                    break LOOP;
244.2093 +                }
244.2094 +                // Fall through
244.2095 +            default:
244.2096 +                node = atom();
244.2097 +                break;
244.2098 +            }
244.2099 +
244.2100 +            node = closure(node);
244.2101 +
244.2102 +            if (head == null) {
244.2103 +                head = tail = node;
244.2104 +            } else {
244.2105 +                tail.next = node;
244.2106 +                tail = node;
244.2107 +            }
244.2108 +        }
244.2109 +        if (head == null) {
244.2110 +            return end;
244.2111 +        }
244.2112 +        tail.next = end;
244.2113 +        root = tail;      //double return
244.2114 +        return head;
244.2115 +    }
244.2116 +
244.2117 +    /**
244.2118 +     * Parse and add a new Single or Slice.
244.2119 +     */
244.2120 +    private Node atom() {
244.2121 +        int first = 0;
244.2122 +        int prev = -1;
244.2123 +        boolean hasSupplementary = false;
244.2124 +        int ch = peek();
244.2125 +        for (;;) {
244.2126 +            switch (ch) {
244.2127 +            case '*':
244.2128 +            case '+':
244.2129 +            case '?':
244.2130 +            case '{':
244.2131 +                if (first > 1) {
244.2132 +                    cursor = prev;    // Unwind one character
244.2133 +                    first--;
244.2134 +                }
244.2135 +                break;
244.2136 +            case '$':
244.2137 +            case '.':
244.2138 +            case '^':
244.2139 +            case '(':
244.2140 +            case '[':
244.2141 +            case '|':
244.2142 +            case ')':
244.2143 +                break;
244.2144 +            case '\\':
244.2145 +                ch = nextEscaped();
244.2146 +                if (ch == 'p' || ch == 'P') { // Property
244.2147 +                    if (first > 0) { // Slice is waiting; handle it first
244.2148 +                        unread();
244.2149 +                        break;
244.2150 +                    } else { // No slice; just return the family node
244.2151 +                        boolean comp = (ch == 'P');
244.2152 +                        boolean oneLetter = true;
244.2153 +                        ch = next(); // Consume { if present
244.2154 +                        if (ch != '{')
244.2155 +                            unread();
244.2156 +                        else
244.2157 +                            oneLetter = false;
244.2158 +                        return family(oneLetter, comp);
244.2159 +                    }
244.2160 +                }
244.2161 +                unread();
244.2162 +                prev = cursor;
244.2163 +                ch = escape(false, first == 0);
244.2164 +                if (ch >= 0) {
244.2165 +                    append(ch, first);
244.2166 +                    first++;
244.2167 +                    if (isSupplementary(ch)) {
244.2168 +                        hasSupplementary = true;
244.2169 +                    }
244.2170 +                    ch = peek();
244.2171 +                    continue;
244.2172 +                } else if (first == 0) {
244.2173 +                    return root;
244.2174 +                }
244.2175 +                // Unwind meta escape sequence
244.2176 +                cursor = prev;
244.2177 +                break;
244.2178 +            case 0:
244.2179 +                if (cursor >= patternLength) {
244.2180 +                    break;
244.2181 +                }
244.2182 +                // Fall through
244.2183 +            default:
244.2184 +                prev = cursor;
244.2185 +                append(ch, first);
244.2186 +                first++;
244.2187 +                if (isSupplementary(ch)) {
244.2188 +                    hasSupplementary = true;
244.2189 +                }
244.2190 +                ch = next();
244.2191 +                continue;
244.2192 +            }
244.2193 +            break;
244.2194 +        }
244.2195 +        if (first == 1) {
244.2196 +            return newSingle(buffer[0]);
244.2197 +        } else {
244.2198 +            return newSlice(buffer, first, hasSupplementary);
244.2199 +        }
244.2200 +    }
244.2201 +
244.2202 +    private void append(int ch, int len) {
244.2203 +        if (len >= buffer.length) {
244.2204 +            int[] tmp = new int[len+len];
244.2205 +            System.arraycopy(buffer, 0, tmp, 0, len);
244.2206 +            buffer = tmp;
244.2207 +        }
244.2208 +        buffer[len] = ch;
244.2209 +    }
244.2210 +
244.2211 +    /**
244.2212 +     * Parses a backref greedily, taking as many numbers as it
244.2213 +     * can. The first digit is always treated as a backref, but
244.2214 +     * multi digit numbers are only treated as a backref if at
244.2215 +     * least that many backrefs exist at this point in the regex.
244.2216 +     */
244.2217 +    private Node ref(int refNum) {
244.2218 +        boolean done = false;
244.2219 +        while(!done) {
244.2220 +            int ch = peek();
244.2221 +            switch(ch) {
244.2222 +            case '0':
244.2223 +            case '1':
244.2224 +            case '2':
244.2225 +            case '3':
244.2226 +            case '4':
244.2227 +            case '5':
244.2228 +            case '6':
244.2229 +            case '7':
244.2230 +            case '8':
244.2231 +            case '9':
244.2232 +                int newRefNum = (refNum * 10) + (ch - '0');
244.2233 +                // Add another number if it doesn't make a group
244.2234 +                // that doesn't exist
244.2235 +                if (capturingGroupCount - 1 < newRefNum) {
244.2236 +                    done = true;
244.2237 +                    break;
244.2238 +                }
244.2239 +                refNum = newRefNum;
244.2240 +                read();
244.2241 +                break;
244.2242 +            default:
244.2243 +                done = true;
244.2244 +                break;
244.2245 +            }
244.2246 +        }
244.2247 +        if (has(CASE_INSENSITIVE))
244.2248 +            return new CIBackRef(refNum, has(UNICODE_CASE));
244.2249 +        else
244.2250 +            return new BackRef(refNum);
244.2251 +    }
244.2252 +
244.2253 +    /**
244.2254 +     * Parses an escape sequence to determine the actual value that needs
244.2255 +     * to be matched.
244.2256 +     * If -1 is returned and create was true a new object was added to the tree
244.2257 +     * to handle the escape sequence.
244.2258 +     * If the returned value is greater than zero, it is the value that
244.2259 +     * matches the escape sequence.
244.2260 +     */
244.2261 +    private int escape(boolean inclass, boolean create) {
244.2262 +        int ch = skip();
244.2263 +        switch (ch) {
244.2264 +        case '0':
244.2265 +            return o();
244.2266 +        case '1':
244.2267 +        case '2':
244.2268 +        case '3':
244.2269 +        case '4':
244.2270 +        case '5':
244.2271 +        case '6':
244.2272 +        case '7':
244.2273 +        case '8':
244.2274 +        case '9':
244.2275 +            if (inclass) break;
244.2276 +            if (create) {
244.2277 +                root = ref((ch - '0'));
244.2278 +            }
244.2279 +            return -1;
244.2280 +        case 'A':
244.2281 +            if (inclass) break;
244.2282 +            if (create) root = new Begin();
244.2283 +            return -1;
244.2284 +        case 'B':
244.2285 +            if (inclass) break;
244.2286 +            if (create) root = new Bound(Bound.NONE, has(UNICODE_CHARACTER_CLASS));
244.2287 +            return -1;
244.2288 +        case 'C':
244.2289 +            break;
244.2290 +        case 'D':
244.2291 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2292 +                               ? new Utype(UnicodeProp.DIGIT).complement()
244.2293 +                               : new Ctype(ASCII.DIGIT).complement();
244.2294 +            return -1;
244.2295 +        case 'E':
244.2296 +        case 'F':
244.2297 +            break;
244.2298 +        case 'G':
244.2299 +            if (inclass) break;
244.2300 +            if (create) root = new LastMatch();
244.2301 +            return -1;
244.2302 +        case 'H':
244.2303 +        case 'I':
244.2304 +        case 'J':
244.2305 +        case 'K':
244.2306 +        case 'L':
244.2307 +        case 'M':
244.2308 +        case 'N':
244.2309 +        case 'O':
244.2310 +        case 'P':
244.2311 +        case 'Q':
244.2312 +        case 'R':
244.2313 +            break;
244.2314 +        case 'S':
244.2315 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2316 +                               ? new Utype(UnicodeProp.WHITE_SPACE).complement()
244.2317 +                               : new Ctype(ASCII.SPACE).complement();
244.2318 +            return -1;
244.2319 +        case 'T':
244.2320 +        case 'U':
244.2321 +        case 'V':
244.2322 +            break;
244.2323 +        case 'W':
244.2324 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2325 +                               ? new Utype(UnicodeProp.WORD).complement()
244.2326 +                               : new Ctype(ASCII.WORD).complement();
244.2327 +            return -1;
244.2328 +        case 'X':
244.2329 +        case 'Y':
244.2330 +            break;
244.2331 +        case 'Z':
244.2332 +            if (inclass) break;
244.2333 +            if (create) {
244.2334 +                if (has(UNIX_LINES))
244.2335 +                    root = new UnixDollar(false);
244.2336 +                else
244.2337 +                    root = new Dollar(false);
244.2338 +            }
244.2339 +            return -1;
244.2340 +        case 'a':
244.2341 +            return '\007';
244.2342 +        case 'b':
244.2343 +            if (inclass) break;
244.2344 +            if (create) root = new Bound(Bound.BOTH, has(UNICODE_CHARACTER_CLASS));
244.2345 +            return -1;
244.2346 +        case 'c':
244.2347 +            return c();
244.2348 +        case 'd':
244.2349 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2350 +                               ? new Utype(UnicodeProp.DIGIT)
244.2351 +                               : new Ctype(ASCII.DIGIT);
244.2352 +            return -1;
244.2353 +        case 'e':
244.2354 +            return '\033';
244.2355 +        case 'f':
244.2356 +            return '\f';
244.2357 +        case 'g':
244.2358 +        case 'h':
244.2359 +        case 'i':
244.2360 +        case 'j':
244.2361 +            break;
244.2362 +        case 'k':
244.2363 +            if (inclass)
244.2364 +                break;
244.2365 +            if (read() != '<')
244.2366 +                throw error("\\k is not followed by '<' for named capturing group");
244.2367 +            String name = groupname(read());
244.2368 +            if (!namedGroups().containsKey(name))
244.2369 +                throw error("(named capturing group <"+ name+"> does not exit");
244.2370 +            if (create) {
244.2371 +                if (has(CASE_INSENSITIVE))
244.2372 +                    root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE));
244.2373 +                else
244.2374 +                    root = new BackRef(namedGroups().get(name));
244.2375 +            }
244.2376 +            return -1;
244.2377 +        case 'l':
244.2378 +        case 'm':
244.2379 +            break;
244.2380 +        case 'n':
244.2381 +            return '\n';
244.2382 +        case 'o':
244.2383 +        case 'p':
244.2384 +        case 'q':
244.2385 +            break;
244.2386 +        case 'r':
244.2387 +            return '\r';
244.2388 +        case 's':
244.2389 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2390 +                               ? new Utype(UnicodeProp.WHITE_SPACE)
244.2391 +                               : new Ctype(ASCII.SPACE);
244.2392 +            return -1;
244.2393 +        case 't':
244.2394 +            return '\t';
244.2395 +        case 'u':
244.2396 +            return u();
244.2397 +        case 'v':
244.2398 +            return '\013';
244.2399 +        case 'w':
244.2400 +            if (create) root = has(UNICODE_CHARACTER_CLASS)
244.2401 +                               ? new Utype(UnicodeProp.WORD)
244.2402 +                               : new Ctype(ASCII.WORD);
244.2403 +            return -1;
244.2404 +        case 'x':
244.2405 +            return x();
244.2406 +        case 'y':
244.2407 +            break;
244.2408 +        case 'z':
244.2409 +            if (inclass) break;
244.2410 +            if (create) root = new End();
244.2411 +            return -1;
244.2412 +        default:
244.2413 +            return ch;
244.2414 +        }
244.2415 +        throw error("Illegal/unsupported escape sequence");
244.2416 +    }
244.2417 +
244.2418 +    /**
244.2419 +     * Parse a character class, and return the node that matches it.
244.2420 +     *
244.2421 +     * Consumes a ] on the way out if consume is true. Usually consume
244.2422 +     * is true except for the case of [abc&&def] where def is a separate
244.2423 +     * right hand node with "understood" brackets.
244.2424 +     */
244.2425 +    private CharProperty clazz(boolean consume) {
244.2426 +        CharProperty prev = null;
244.2427 +        CharProperty node = null;
244.2428 +        BitClass bits = new BitClass();
244.2429 +        boolean include = true;
244.2430 +        boolean firstInClass = true;
244.2431 +        int ch = next();
244.2432 +        for (;;) {
244.2433 +            switch (ch) {
244.2434 +                case '^':
244.2435 +                    // Negates if first char in a class, otherwise literal
244.2436 +                    if (firstInClass) {
244.2437 +                        if (temp[cursor-1] != '[')
244.2438 +                            break;
244.2439 +                        ch = next();
244.2440 +                        include = !include;
244.2441 +                        continue;
244.2442 +                    } else {
244.2443 +                        // ^ not first in class, treat as literal
244.2444 +                        break;
244.2445 +                    }
244.2446 +                case '[':
244.2447 +                    firstInClass = false;
244.2448 +                    node = clazz(true);
244.2449 +                    if (prev == null)
244.2450 +                        prev = node;
244.2451 +                    else
244.2452 +                        prev = union(prev, node);
244.2453 +                    ch = peek();
244.2454 +                    continue;
244.2455 +                case '&':
244.2456 +                    firstInClass = false;
244.2457 +                    ch = next();
244.2458 +                    if (ch == '&') {
244.2459 +                        ch = next();
244.2460 +                        CharProperty rightNode = null;
244.2461 +                        while (ch != ']' && ch != '&') {
244.2462 +                            if (ch == '[') {
244.2463 +                                if (rightNode == null)
244.2464 +                                    rightNode = clazz(true);
244.2465 +                                else
244.2466 +                                    rightNode = union(rightNode, clazz(true));
244.2467 +                            } else { // abc&&def
244.2468 +                                unread();
244.2469 +                                rightNode = clazz(false);
244.2470 +                            }
244.2471 +                            ch = peek();
244.2472 +                        }
244.2473 +                        if (rightNode != null)
244.2474 +                            node = rightNode;
244.2475 +                        if (prev == null) {
244.2476 +                            if (rightNode == null)
244.2477 +                                throw error("Bad class syntax");
244.2478 +                            else
244.2479 +                                prev = rightNode;
244.2480 +                        } else {
244.2481 +                            prev = intersection(prev, node);
244.2482 +                        }
244.2483 +                    } else {
244.2484 +                        // treat as a literal &
244.2485 +                        unread();
244.2486 +                        break;
244.2487 +                    }
244.2488 +                    continue;
244.2489 +                case 0:
244.2490 +                    firstInClass = false;
244.2491 +                    if (cursor >= patternLength)
244.2492 +                        throw error("Unclosed character class");
244.2493 +                    break;
244.2494 +                case ']':
244.2495 +                    firstInClass = false;
244.2496 +                    if (prev != null) {
244.2497 +                        if (consume)
244.2498 +                            next();
244.2499 +                        return prev;
244.2500 +                    }
244.2501 +                    break;
244.2502 +                default:
244.2503 +                    firstInClass = false;
244.2504 +                    break;
244.2505 +            }
244.2506 +            node = range(bits);
244.2507 +            if (include) {
244.2508 +                if (prev == null) {
244.2509 +                    prev = node;
244.2510 +                } else {
244.2511 +                    if (prev != node)
244.2512 +                        prev = union(prev, node);
244.2513 +                }
244.2514 +            } else {
244.2515 +                if (prev == null) {
244.2516 +                    prev = node.complement();
244.2517 +                } else {
244.2518 +                    if (prev != node)
244.2519 +                        prev = setDifference(prev, node);
244.2520 +                }
244.2521 +            }
244.2522 +            ch = peek();
244.2523 +        }
244.2524 +    }
244.2525 +
244.2526 +    private CharProperty bitsOrSingle(BitClass bits, int ch) {
244.2527 +        /* Bits can only handle codepoints in [u+0000-u+00ff] range.
244.2528 +           Use "single" node instead of bits when dealing with unicode
244.2529 +           case folding for codepoints listed below.
244.2530 +           (1)Uppercase out of range: u+00ff, u+00b5
244.2531 +              toUpperCase(u+00ff) -> u+0178
244.2532 +              toUpperCase(u+00b5) -> u+039c
244.2533 +           (2)LatinSmallLetterLongS u+17f
244.2534 +              toUpperCase(u+017f) -> u+0053
244.2535 +           (3)LatinSmallLetterDotlessI u+131
244.2536 +              toUpperCase(u+0131) -> u+0049
244.2537 +           (4)LatinCapitalLetterIWithDotAbove u+0130
244.2538 +              toLowerCase(u+0130) -> u+0069
244.2539 +           (5)KelvinSign u+212a
244.2540 +              toLowerCase(u+212a) ==> u+006B
244.2541 +           (6)AngstromSign u+212b
244.2542 +              toLowerCase(u+212b) ==> u+00e5
244.2543 +        */
244.2544 +        int d;
244.2545 +        if (ch < 256 &&
244.2546 +            !(has(CASE_INSENSITIVE) && has(UNICODE_CASE) &&
244.2547 +              (ch == 0xff || ch == 0xb5 ||
244.2548 +               ch == 0x49 || ch == 0x69 ||  //I and i
244.2549 +               ch == 0x53 || ch == 0x73 ||  //S and s
244.2550 +               ch == 0x4b || ch == 0x6b ||  //K and k
244.2551 +               ch == 0xc5 || ch == 0xe5)))  //A+ring
244.2552 +            return bits.add(ch, flags());
244.2553 +        return newSingle(ch);
244.2554 +    }
244.2555 +
244.2556 +    /**
244.2557 +     * Parse a single character or a character range in a character class
244.2558 +     * and return its representative node.
244.2559 +     */
244.2560 +    private CharProperty range(BitClass bits) {
244.2561 +        int ch = peek();
244.2562 +        if (ch == '\\') {
244.2563 +            ch = nextEscaped();
244.2564 +            if (ch == 'p' || ch == 'P') { // A property
244.2565 +                boolean comp = (ch == 'P');
244.2566 +                boolean oneLetter = true;
244.2567 +                // Consume { if present
244.2568 +                ch = next();
244.2569 +                if (ch != '{')
244.2570 +                    unread();
244.2571 +                else
244.2572 +                    oneLetter = false;
244.2573 +                return family(oneLetter, comp);
244.2574 +            } else { // ordinary escape
244.2575 +                unread();
244.2576 +                ch = escape(true, true);
244.2577 +                if (ch == -1)
244.2578 +                    return (CharProperty) root;
244.2579 +            }
244.2580 +        } else {
244.2581 +            ch = single();
244.2582 +        }
244.2583 +        if (ch >= 0) {
244.2584 +            if (peek() == '-') {
244.2585 +                int endRange = temp[cursor+1];
244.2586 +                if (endRange == '[') {
244.2587 +                    return bitsOrSingle(bits, ch);
244.2588 +                }
244.2589 +                if (endRange != ']') {
244.2590 +                    next();
244.2591 +                    int m = single();
244.2592 +                    if (m < ch)
244.2593 +                        throw error("Illegal character range");
244.2594 +                    if (has(CASE_INSENSITIVE))
244.2595 +                        return caseInsensitiveRangeFor(ch, m);
244.2596 +                    else
244.2597 +                        return rangeFor(ch, m);
244.2598 +                }
244.2599 +            }
244.2600 +            return bitsOrSingle(bits, ch);
244.2601 +        }
244.2602 +        throw error("Unexpected character '"+((char)ch)+"'");
244.2603 +    }
244.2604 +
244.2605 +    private int single() {
244.2606 +        int ch = peek();
244.2607 +        switch (ch) {
244.2608 +        case '\\':
244.2609 +            return escape(true, false);
244.2610 +        default:
244.2611 +            next();
244.2612 +            return ch;
244.2613 +        }
244.2614 +    }
244.2615 +
244.2616 +    /**
244.2617 +     * Parses a Unicode character family and returns its representative node.
244.2618 +     */
244.2619 +    private CharProperty family(boolean singleLetter,
244.2620 +                                boolean maybeComplement)
244.2621 +    {
244.2622 +        next();
244.2623 +        String name;
244.2624 +        CharProperty node = null;
244.2625 +
244.2626 +        if (singleLetter) {
244.2627 +            int c = temp[cursor];
244.2628 +            if (!Character.isSupplementaryCodePoint(c)) {
244.2629 +                name = String.valueOf((char)c);
244.2630 +            } else {
244.2631 +                name = new String(temp, cursor, 1);
244.2632 +            }
244.2633 +            read();
244.2634 +        } else {
244.2635 +            int i = cursor;
244.2636 +            mark('}');
244.2637 +            while(read() != '}') {
244.2638 +            }
244.2639 +            mark('\000');
244.2640 +            int j = cursor;
244.2641 +            if (j > patternLength)
244.2642 +                throw error("Unclosed character family");
244.2643 +            if (i + 1 >= j)
244.2644 +                throw error("Empty character family");
244.2645 +            name = new String(temp, i, j-i-1);
244.2646 +        }
244.2647 +
244.2648 +        int i = name.indexOf('=');
244.2649 +        if (i != -1) {
244.2650 +            // property construct \p{name=value}
244.2651 +            String value = name.substring(i + 1);
244.2652 +            name = name.substring(0, i).toLowerCase(Locale.ENGLISH);
244.2653 +    /*        if ("sc".equals(name) || "script".equals(name)) {
244.2654 +                node = unicodeScriptPropertyFor(value);
244.2655 +            } else if ("blk".equals(name) || "block".equals(name)) {
244.2656 +                node = unicodeBlockPropertyFor(value);
244.2657 +            } else*/ if ("gc".equals(name) || "general_category".equals(name)) {
244.2658 +                node = charPropertyNodeFor(value);
244.2659 +            } else {
244.2660 +                throw error("Unknown Unicode property {name=<" + name + ">, "
244.2661 +                             + "value=<" + value + ">}");
244.2662 +            }
244.2663 +        } else {
244.2664 +            /*if (name.startsWith("In")) {
244.2665 +                // \p{inBlockName}
244.2666 +                node = unicodeBlockPropertyFor(name.substring(2));
244.2667 +            } else if (name.startsWith("Is")) {
244.2668 +                // \p{isGeneralCategory} and \p{isScriptName}
244.2669 +                name = name.substring(2);
244.2670 +                UnicodeProp uprop = UnicodeProp.forName(name);
244.2671 +                if (uprop != null)
244.2672 +                    node = new Utype(uprop);
244.2673 +                if (node == null)
244.2674 +                    node = CharPropertyNames.charPropertyFor(name);
244.2675 +                if (node == null)
244.2676 +                    node = unicodeScriptPropertyFor(name);
244.2677 +            } else*/ {
244.2678 +                if (has(UNICODE_CHARACTER_CLASS)) {
244.2679 +                    UnicodeProp uprop = UnicodeProp.forPOSIXName(name);
244.2680 +                    if (uprop != null)
244.2681 +                        node = new Utype(uprop);
244.2682 +                }
244.2683 +                if (node == null)
244.2684 +                    node = charPropertyNodeFor(name);
244.2685 +            }
244.2686 +        }
244.2687 +        if (maybeComplement) {
244.2688 +            if (node instanceof Category /*|| node instanceof Block*/)
244.2689 +                hasSupplementary = true;
244.2690 +            node = node.complement();
244.2691 +        }
244.2692 +        return node;
244.2693 +    }
244.2694 +
244.2695 +
244.2696 +    /**
244.2697 +     * Returns a CharProperty matching all characters belong to
244.2698 +     * a UnicodeScript.
244.2699 +     *
244.2700 +    private CharProperty unicodeScriptPropertyFor(String name) {
244.2701 +        final Character.UnicodeScript script;
244.2702 +        try {
244.2703 +            script = Character.UnicodeScript.forName(name);
244.2704 +        } catch (IllegalArgumentException iae) {
244.2705 +            throw error("Unknown character script name {" + name + "}");
244.2706 +        }
244.2707 +        return new Script(script);
244.2708 +    }
244.2709 +
244.2710 +    /**
244.2711 +     * Returns a CharProperty matching all characters in a UnicodeBlock.
244.2712 +     *
244.2713 +    private CharProperty unicodeBlockPropertyFor(String name) {
244.2714 +        final Character.UnicodeBlock block;
244.2715 +        try {
244.2716 +            block = Character.UnicodeBlock.forName(name);
244.2717 +        } catch (IllegalArgumentException iae) {
244.2718 +            throw error("Unknown character block name {" + name + "}");
244.2719 +        }
244.2720 +        return new Block(block);
244.2721 +    }
244.2722 +
244.2723 +    /**
244.2724 +     * Returns a CharProperty matching all characters in a named property.
244.2725 +     */
244.2726 +    private CharProperty charPropertyNodeFor(String name) {
244.2727 +        CharProperty p = CharPropertyNames.charPropertyFor(name);
244.2728 +        if (p == null)
244.2729 +            throw error("Unknown character property name {" + name + "}");
244.2730 +        return p;
244.2731 +    }
244.2732 +
244.2733 +    /**
244.2734 +     * Parses and returns the name of a "named capturing group", the trailing
244.2735 +     * ">" is consumed after parsing.
244.2736 +     */
244.2737 +    private String groupname(int ch) {
244.2738 +        StringBuilder sb = new StringBuilder();
244.2739 +        sb.append(Character.toChars(ch));
244.2740 +        while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) ||
244.2741 +               ASCII.isDigit(ch)) {
244.2742 +            sb.append(Character.toChars(ch));
244.2743 +        }
244.2744 +        if (sb.length() == 0)
244.2745 +            throw error("named capturing group has 0 length name");
244.2746 +        if (ch != '>')
244.2747 +            throw error("named capturing group is missing trailing '>'");
244.2748 +        return sb.toString();
244.2749 +    }
244.2750 +
244.2751 +    /**
244.2752 +     * Parses a group and returns the head node of a set of nodes that process
244.2753 +     * the group. Sometimes a double return system is used where the tail is
244.2754 +     * returned in root.
244.2755 +     */
244.2756 +    private Node group0() {
244.2757 +        boolean capturingGroup = false;
244.2758 +        Node head = null;
244.2759 +        Node tail = null;
244.2760 +        int save = flags;
244.2761 +        root = null;
244.2762 +        int ch = next();
244.2763 +        if (ch == '?') {
244.2764 +            ch = skip();
244.2765 +            switch (ch) {
244.2766 +            case ':':   //  (?:xxx) pure group
244.2767 +                head = createGroup(true);
244.2768 +                tail = root;
244.2769 +                head.next = expr(tail);
244.2770 +                break;
244.2771 +            case '=':   // (?=xxx) and (?!xxx) lookahead
244.2772 +            case '!':
244.2773 +                head = createGroup(true);
244.2774 +                tail = root;
244.2775 +                head.next = expr(tail);
244.2776 +                if (ch == '=') {
244.2777 +                    head = tail = new Pos(head);
244.2778 +                } else {
244.2779 +                    head = tail = new Neg(head);
244.2780 +                }
244.2781 +                break;
244.2782 +            case '>':   // (?>xxx)  independent group
244.2783 +                head = createGroup(true);
244.2784 +                tail = root;
244.2785 +                head.next = expr(tail);
244.2786 +                head = tail = new Ques(head, INDEPENDENT);
244.2787 +                break;
244.2788 +            case '<':   // (?<xxx)  look behind
244.2789 +                ch = read();
244.2790 +                if (ASCII.isLower(ch) || ASCII.isUpper(ch)) {
244.2791 +                    // named captured group
244.2792 +                    String name = groupname(ch);
244.2793 +                    if (namedGroups().containsKey(name))
244.2794 +                        throw error("Named capturing group <" + name
244.2795 +                                    + "> is already defined");
244.2796 +                    capturingGroup = true;
244.2797 +                    head = createGroup(false);
244.2798 +                    tail = root;
244.2799 +                    namedGroups().put(name, capturingGroupCount-1);
244.2800 +                    head.next = expr(tail);
244.2801 +                    break;
244.2802 +                }
244.2803 +                int start = cursor;
244.2804 +                head = createGroup(true);
244.2805 +                tail = root;
244.2806 +                head.next = expr(tail);
244.2807 +                tail.next = lookbehindEnd;
244.2808 +                TreeInfo info = new TreeInfo();
244.2809 +                head.study(info);
244.2810 +                if (info.maxValid == false) {
244.2811 +                    throw error("Look-behind group does not have "
244.2812 +                                + "an obvious maximum length");
244.2813 +                }
244.2814 +                boolean hasSupplementary = findSupplementary(start, patternLength);
244.2815 +                if (ch == '=') {
244.2816 +                    head = tail = (hasSupplementary ?
244.2817 +                                   new BehindS(head, info.maxLength,
244.2818 +                                               info.minLength) :
244.2819 +                                   new Behind(head, info.maxLength,
244.2820 +                                              info.minLength));
244.2821 +                } else if (ch == '!') {
244.2822 +                    head = tail = (hasSupplementary ?
244.2823 +                                   new NotBehindS(head, info.maxLength,
244.2824 +                                                  info.minLength) :
244.2825 +                                   new NotBehind(head, info.maxLength,
244.2826 +                                                 info.minLength));
244.2827 +                } else {
244.2828 +                    throw error("Unknown look-behind group");
244.2829 +                }
244.2830 +                break;
244.2831 +            case '$':
244.2832 +            case '@':
244.2833 +                throw error("Unknown group type");
244.2834 +            default:    // (?xxx:) inlined match flags
244.2835 +                unread();
244.2836 +                addFlag();
244.2837 +                ch = read();
244.2838 +                if (ch == ')') {
244.2839 +                    return null;    // Inline modifier only
244.2840 +                }
244.2841 +                if (ch != ':') {
244.2842 +                    throw error("Unknown inline modifier");
244.2843 +                }
244.2844 +                head = createGroup(true);
244.2845 +                tail = root;
244.2846 +                head.next = expr(tail);
244.2847 +                break;
244.2848 +            }
244.2849 +        } else { // (xxx) a regular group
244.2850 +            capturingGroup = true;
244.2851 +            head = createGroup(false);
244.2852 +            tail = root;
244.2853 +            head.next = expr(tail);
244.2854 +        }
244.2855 +
244.2856 +        accept(')', "Unclosed group");
244.2857 +        flags = save;
244.2858 +
244.2859 +        // Check for quantifiers
244.2860 +        Node node = closure(head);
244.2861 +        if (node == head) { // No closure
244.2862 +            root = tail;
244.2863 +            return node;    // Dual return
244.2864 +        }
244.2865 +        if (head == tail) { // Zero length assertion
244.2866 +            root = node;
244.2867 +            return node;    // Dual return
244.2868 +        }
244.2869 +
244.2870 +        if (node instanceof Ques) {
244.2871 +            Ques ques = (Ques) node;
244.2872 +            if (ques.type == POSSESSIVE) {
244.2873 +                root = node;
244.2874 +                return node;
244.2875 +            }
244.2876 +            tail.next = new BranchConn();
244.2877 +            tail = tail.next;
244.2878 +            if (ques.type == GREEDY) {
244.2879 +                head = new Branch(head, null, tail);
244.2880 +            } else { // Reluctant quantifier
244.2881 +                head = new Branch(null, head, tail);
244.2882 +            }
244.2883 +            root = tail;
244.2884 +            return head;
244.2885 +        } else if (node instanceof Curly) {
244.2886 +            Curly curly = (Curly) node;
244.2887 +            if (curly.type == POSSESSIVE) {
244.2888 +                root = node;
244.2889 +                return node;
244.2890 +            }
244.2891 +            // Discover if the group is deterministic
244.2892 +            TreeInfo info = new TreeInfo();
244.2893 +            if (head.study(info)) { // Deterministic
244.2894 +                GroupTail temp = (GroupTail) tail;
244.2895 +                head = root = new GroupCurly(head.next, curly.cmin,
244.2896 +                                   curly.cmax, curly.type,
244.2897 +                                   ((GroupTail)tail).localIndex,
244.2898 +                                   ((GroupTail)tail).groupIndex,
244.2899 +                                             capturingGroup);
244.2900 +                return head;
244.2901 +            } else { // Non-deterministic
244.2902 +                int temp = ((GroupHead) head).localIndex;
244.2903 +                Loop loop;
244.2904 +                if (curly.type == GREEDY)
244.2905 +                    loop = new Loop(this.localCount, temp);
244.2906 +                else  // Reluctant Curly
244.2907 +                    loop = new LazyLoop(this.localCount, temp);
244.2908 +                Prolog prolog = new Prolog(loop);
244.2909 +                this.localCount += 1;
244.2910 +                loop.cmin = curly.cmin;
244.2911 +                loop.cmax = curly.cmax;
244.2912 +                loop.body = head;
244.2913 +                tail.next = loop;
244.2914 +                root = loop;
244.2915 +                return prolog; // Dual return
244.2916 +            }
244.2917 +        }
244.2918 +        throw error("Internal logic error");
244.2919 +    }
244.2920 +
244.2921 +    /**
244.2922 +     * Create group head and tail nodes using double return. If the group is
244.2923 +     * created with anonymous true then it is a pure group and should not
244.2924 +     * affect group counting.
244.2925 +     */
244.2926 +    private Node createGroup(boolean anonymous) {
244.2927 +        int localIndex = localCount++;
244.2928 +        int groupIndex = 0;
244.2929 +        if (!anonymous)
244.2930 +            groupIndex = capturingGroupCount++;
244.2931 +        GroupHead head = new GroupHead(localIndex);
244.2932 +        root = new GroupTail(localIndex, groupIndex);
244.2933 +        if (!anonymous && groupIndex < 10)
244.2934 +            groupNodes[groupIndex] = head;
244.2935 +        return head;
244.2936 +    }
244.2937 +
244.2938 +    /**
244.2939 +     * Parses inlined match flags and set them appropriately.
244.2940 +     */
244.2941 +    private void addFlag() {
244.2942 +        int ch = peek();
244.2943 +        for (;;) {
244.2944 +            switch (ch) {
244.2945 +            case 'i':
244.2946 +                flags |= CASE_INSENSITIVE;
244.2947 +                break;
244.2948 +            case 'm':
244.2949 +                flags |= MULTILINE;
244.2950 +                break;
244.2951 +            case 's':
244.2952 +                flags |= DOTALL;
244.2953 +                break;
244.2954 +            case 'd':
244.2955 +                flags |= UNIX_LINES;
244.2956 +                break;
244.2957 +            case 'u':
244.2958 +                flags |= UNICODE_CASE;
244.2959 +                break;
244.2960 +            case 'c':
244.2961 +                flags |= CANON_EQ;
244.2962 +                break;
244.2963 +            case 'x':
244.2964 +                flags |= COMMENTS;
244.2965 +                break;
244.2966 +            case 'U':
244.2967 +                flags |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
244.2968 +                break;
244.2969 +            case '-': // subFlag then fall through
244.2970 +                ch = next();
244.2971 +                subFlag();
244.2972 +            default:
244.2973 +                return;
244.2974 +            }
244.2975 +            ch = next();
244.2976 +        }
244.2977 +    }
244.2978 +
244.2979 +    /**
244.2980 +     * Parses the second part of inlined match flags and turns off
244.2981 +     * flags appropriately.
244.2982 +     */
244.2983 +    private void subFlag() {
244.2984 +        int ch = peek();
244.2985 +        for (;;) {
244.2986 +            switch (ch) {
244.2987 +            case 'i':
244.2988 +                flags &= ~CASE_INSENSITIVE;
244.2989 +                break;
244.2990 +            case 'm':
244.2991 +                flags &= ~MULTILINE;
244.2992 +                break;
244.2993 +            case 's':
244.2994 +                flags &= ~DOTALL;
244.2995 +                break;
244.2996 +            case 'd':
244.2997 +                flags &= ~UNIX_LINES;
244.2998 +                break;
244.2999 +            case 'u':
244.3000 +                flags &= ~UNICODE_CASE;
244.3001 +                break;
244.3002 +            case 'c':
244.3003 +                flags &= ~CANON_EQ;
244.3004 +                break;
244.3005 +            case 'x':
244.3006 +                flags &= ~COMMENTS;
244.3007 +                break;
244.3008 +            case 'U':
244.3009 +                flags &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
244.3010 +            default:
244.3011 +                return;
244.3012 +            }
244.3013 +            ch = next();
244.3014 +        }
244.3015 +    }
244.3016 +
244.3017 +    static final int MAX_REPS   = 0x7FFFFFFF;
244.3018 +
244.3019 +    static final int GREEDY     = 0;
244.3020 +
244.3021 +    static final int LAZY       = 1;
244.3022 +
244.3023 +    static final int POSSESSIVE = 2;
244.3024 +
244.3025 +    static final int INDEPENDENT = 3;
244.3026 +
244.3027 +    /**
244.3028 +     * Processes repetition. If the next character peeked is a quantifier
244.3029 +     * then new nodes must be appended to handle the repetition.
244.3030 +     * Prev could be a single or a group, so it could be a chain of nodes.
244.3031 +     */
244.3032 +    private Node closure(Node prev) {
244.3033 +        Node atom;
244.3034 +        int ch = peek();
244.3035 +        switch (ch) {
244.3036 +        case '?':
244.3037 +            ch = next();
244.3038 +            if (ch == '?') {
244.3039 +                next();
244.3040 +                return new Ques(prev, LAZY);
244.3041 +            } else if (ch == '+') {
244.3042 +                next();
244.3043 +                return new Ques(prev, POSSESSIVE);
244.3044 +            }
244.3045 +            return new Ques(prev, GREEDY);
244.3046 +        case '*':
244.3047 +            ch = next();
244.3048 +            if (ch == '?') {
244.3049 +                next();
244.3050 +                return new Curly(prev, 0, MAX_REPS, LAZY);
244.3051 +            } else if (ch == '+') {
244.3052 +                next();
244.3053 +                return new Curly(prev, 0, MAX_REPS, POSSESSIVE);
244.3054 +            }
244.3055 +            return new Curly(prev, 0, MAX_REPS, GREEDY);
244.3056 +        case '+':
244.3057 +            ch = next();
244.3058 +            if (ch == '?') {
244.3059 +                next();
244.3060 +                return new Curly(prev, 1, MAX_REPS, LAZY);
244.3061 +            } else if (ch == '+') {
244.3062 +                next();
244.3063 +                return new Curly(prev, 1, MAX_REPS, POSSESSIVE);
244.3064 +            }
244.3065 +            return new Curly(prev, 1, MAX_REPS, GREEDY);
244.3066 +        case '{':
244.3067 +            ch = temp[cursor+1];
244.3068 +            if (ASCII.isDigit(ch)) {
244.3069 +                skip();
244.3070 +                int cmin = 0;
244.3071 +                do {
244.3072 +                    cmin = cmin * 10 + (ch - '0');
244.3073 +                } while (ASCII.isDigit(ch = read()));
244.3074 +                int cmax = cmin;
244.3075 +                if (ch == ',') {
244.3076 +                    ch = read();
244.3077 +                    cmax = MAX_REPS;
244.3078 +                    if (ch != '}') {
244.3079 +                        cmax = 0;
244.3080 +                        while (ASCII.isDigit(ch)) {
244.3081 +                            cmax = cmax * 10 + (ch - '0');
244.3082 +                            ch = read();
244.3083 +                        }
244.3084 +                    }
244.3085 +                }
244.3086 +                if (ch != '}')
244.3087 +                    throw error("Unclosed counted closure");
244.3088 +                if (((cmin) | (cmax) | (cmax - cmin)) < 0)
244.3089 +                    throw error("Illegal repetition range");
244.3090 +                Curly curly;
244.3091 +                ch = peek();
244.3092 +                if (ch == '?') {
244.3093 +                    next();
244.3094 +                    curly = new Curly(prev, cmin, cmax, LAZY);
244.3095 +                } else if (ch == '+') {
244.3096 +                    next();
244.3097 +                    curly = new Curly(prev, cmin, cmax, POSSESSIVE);
244.3098 +                } else {
244.3099 +                    curly = new Curly(prev, cmin, cmax, GREEDY);
244.3100 +                }
244.3101 +                return curly;
244.3102 +            } else {
244.3103 +                throw error("Illegal repetition");
244.3104 +            }
244.3105 +        default:
244.3106 +            return prev;
244.3107 +        }
244.3108 +    }
244.3109 +
244.3110 +    /**
244.3111 +     *  Utility method for parsing control escape sequences.
244.3112 +     */
244.3113 +    private int c() {
244.3114 +        if (cursor < patternLength) {
244.3115 +            return read() ^ 64;
244.3116 +        }
244.3117 +        throw error("Illegal control escape sequence");
244.3118 +    }
244.3119 +
244.3120 +    /**
244.3121 +     *  Utility method for parsing octal escape sequences.
244.3122 +     */
244.3123 +    private int o() {
244.3124 +        int n = read();
244.3125 +        if (((n-'0')|('7'-n)) >= 0) {
244.3126 +            int m = read();
244.3127 +            if (((m-'0')|('7'-m)) >= 0) {
244.3128 +                int o = read();
244.3129 +                if ((((o-'0')|('7'-o)) >= 0) && (((n-'0')|('3'-n)) >= 0)) {
244.3130 +                    return (n - '0') * 64 + (m - '0') * 8 + (o - '0');
244.3131 +                }
244.3132 +                unread();
244.3133 +                return (n - '0') * 8 + (m - '0');
244.3134 +            }
244.3135 +            unread();
244.3136 +            return (n - '0');
244.3137 +        }
244.3138 +        throw error("Illegal octal escape sequence");
244.3139 +    }
244.3140 +
244.3141 +    /**
244.3142 +     *  Utility method for parsing hexadecimal escape sequences.
244.3143 +     */
244.3144 +    private int x() {
244.3145 +        int n = read();
244.3146 +        if (ASCII.isHexDigit(n)) {
244.3147 +            int m = read();
244.3148 +            if (ASCII.isHexDigit(m)) {
244.3149 +                return ASCII.toDigit(n) * 16 + ASCII.toDigit(m);
244.3150 +            }
244.3151 +        } else if (n == '{' && ASCII.isHexDigit(peek())) {
244.3152 +            int ch = 0;
244.3153 +            while (ASCII.isHexDigit(n = read())) {
244.3154 +                ch = (ch << 4) + ASCII.toDigit(n);
244.3155 +                if (ch > Character.MAX_CODE_POINT)
244.3156 +                    throw error("Hexadecimal codepoint is too big");
244.3157 +            }
244.3158 +            if (n != '}')
244.3159 +                throw error("Unclosed hexadecimal escape sequence");
244.3160 +            return ch;
244.3161 +        }
244.3162 +        throw error("Illegal hexadecimal escape sequence");
244.3163 +    }
244.3164 +
244.3165 +    /**
244.3166 +     *  Utility method for parsing unicode escape sequences.
244.3167 +     */
244.3168 +    private int cursor() {
244.3169 +        return cursor;
244.3170 +    }
244.3171 +
244.3172 +    private void setcursor(int pos) {
244.3173 +        cursor = pos;
244.3174 +    }
244.3175 +
244.3176 +    private int uxxxx() {
244.3177 +        int n = 0;
244.3178 +        for (int i = 0; i < 4; i++) {
244.3179 +            int ch = read();
244.3180 +            if (!ASCII.isHexDigit(ch)) {
244.3181 +                throw error("Illegal Unicode escape sequence");
244.3182 +            }
244.3183 +            n = n * 16 + ASCII.toDigit(ch);
244.3184 +        }
244.3185 +        return n;
244.3186 +    }
244.3187 +
244.3188 +    private int u() {
244.3189 +        int n = uxxxx();
244.3190 +        if (Character.isHighSurrogate((char)n)) {
244.3191 +            int cur = cursor();
244.3192 +            if (read() == '\\' && read() == 'u') {
244.3193 +                int n2 = uxxxx();
244.3194 +                if (Character.isLowSurrogate((char)n2))
244.3195 +                    return Character.toCodePoint((char)n, (char)n2);
244.3196 +            }
244.3197 +            setcursor(cur);
244.3198 +        }
244.3199 +        return n;
244.3200 +    }
244.3201 +
244.3202 +    //
244.3203 +    // Utility methods for code point support
244.3204 +    //
244.3205 +
244.3206 +    private static final int countChars(CharSequence seq, int index,
244.3207 +                                        int lengthInCodePoints) {
244.3208 +        // optimization
244.3209 +        if (lengthInCodePoints == 1 && !Character.isHighSurrogate(seq.charAt(index))) {
244.3210 +            assert (index >= 0 && index < seq.length());
244.3211 +            return 1;
244.3212 +        }
244.3213 +        int length = seq.length();
244.3214 +        int x = index;
244.3215 +        if (lengthInCodePoints >= 0) {
244.3216 +            assert (index >= 0 && index < length);
244.3217 +            for (int i = 0; x < length && i < lengthInCodePoints; i++) {
244.3218 +                if (Character.isHighSurrogate(seq.charAt(x++))) {
244.3219 +                    if (x < length && Character.isLowSurrogate(seq.charAt(x))) {
244.3220 +                        x++;
244.3221 +                    }
244.3222 +                }
244.3223 +            }
244.3224 +            return x - index;
244.3225 +        }
244.3226 +
244.3227 +        assert (index >= 0 && index <= length);
244.3228 +        if (index == 0) {
244.3229 +            return 0;
244.3230 +        }
244.3231 +        int len = -lengthInCodePoints;
244.3232 +        for (int i = 0; x > 0 && i < len; i++) {
244.3233 +            if (Character.isLowSurrogate(seq.charAt(--x))) {
244.3234 +                if (x > 0 && Character.isHighSurrogate(seq.charAt(x-1))) {
244.3235 +                    x--;
244.3236 +                }
244.3237 +            }
244.3238 +        }
244.3239 +        return index - x;
244.3240 +    }
244.3241 +
244.3242 +    private static final int countCodePoints(CharSequence seq) {
244.3243 +        int length = seq.length();
244.3244 +        int n = 0;
244.3245 +        for (int i = 0; i < length; ) {
244.3246 +            n++;
244.3247 +            if (Character.isHighSurrogate(seq.charAt(i++))) {
244.3248 +                if (i < length && Character.isLowSurrogate(seq.charAt(i))) {
244.3249 +                    i++;
244.3250 +                }
244.3251 +            }
244.3252 +        }
244.3253 +        return n;
244.3254 +    }
244.3255 +
244.3256 +    /**
244.3257 +     *  Creates a bit vector for matching Latin-1 values. A normal BitClass
244.3258 +     *  never matches values above Latin-1, and a complemented BitClass always
244.3259 +     *  matches values above Latin-1.
244.3260 +     */
244.3261 +    private static final class BitClass extends BmpCharProperty {
244.3262 +        final boolean[] bits;
244.3263 +        BitClass() { bits = new boolean[256]; }
244.3264 +        private BitClass(boolean[] bits) { this.bits = bits; }
244.3265 +        BitClass add(int c, int flags) {
244.3266 +            assert c >= 0 && c <= 255;
244.3267 +            if ((flags & CASE_INSENSITIVE) != 0) {
244.3268 +                if (ASCII.isAscii(c)) {
244.3269 +                    bits[ASCII.toUpper(c)] = true;
244.3270 +                    bits[ASCII.toLower(c)] = true;
244.3271 +                } else if ((flags & UNICODE_CASE) != 0) {
244.3272 +                    bits[Character.toLowerCase(c)] = true;
244.3273 +                    bits[Character.toUpperCase(c)] = true;
244.3274 +                }
244.3275 +            }
244.3276 +            bits[c] = true;
244.3277 +            return this;
244.3278 +        }
244.3279 +        boolean isSatisfiedBy(int ch) {
244.3280 +            return ch < 256 && bits[ch];
244.3281 +        }
244.3282 +    }
244.3283 +
244.3284 +    /**
244.3285 +     *  Returns a suitably optimized, single character matcher.
244.3286 +     */
244.3287 +    private CharProperty newSingle(final int ch) {
244.3288 +        if (has(CASE_INSENSITIVE)) {
244.3289 +            int lower, upper;
244.3290 +            if (has(UNICODE_CASE)) {
244.3291 +                upper = Character.toUpperCase(ch);
244.3292 +                lower = Character.toLowerCase(upper);
244.3293 +                if (upper != lower)
244.3294 +                    return new SingleU(lower);
244.3295 +            } else if (ASCII.isAscii(ch)) {
244.3296 +                lower = ASCII.toLower(ch);
244.3297 +                upper = ASCII.toUpper(ch);
244.3298 +                if (lower != upper)
244.3299 +                    return new SingleI(lower, upper);
244.3300 +            }
244.3301 +        }
244.3302 +        if (isSupplementary(ch))
244.3303 +            return new SingleS(ch);    // Match a given Unicode character
244.3304 +        return new Single(ch);         // Match a given BMP character
244.3305 +    }
244.3306 +
244.3307 +    /**
244.3308 +     *  Utility method for creating a string slice matcher.
244.3309 +     */
244.3310 +    private Node newSlice(int[] buf, int count, boolean hasSupplementary) {
244.3311 +        int[] tmp = new int[count];
244.3312 +        if (has(CASE_INSENSITIVE)) {
244.3313 +            if (has(UNICODE_CASE)) {
244.3314 +                for (int i = 0; i < count; i++) {
244.3315 +                    tmp[i] = Character.toLowerCase(
244.3316 +                                 Character.toUpperCase(buf[i]));
244.3317 +                }
244.3318 +                return hasSupplementary? new SliceUS(tmp) : new SliceU(tmp);
244.3319 +            }
244.3320 +            for (int i = 0; i < count; i++) {
244.3321 +                tmp[i] = ASCII.toLower(buf[i]);
244.3322 +            }
244.3323 +            return hasSupplementary? new SliceIS(tmp) : new SliceI(tmp);
244.3324 +        }
244.3325 +        for (int i = 0; i < count; i++) {
244.3326 +            tmp[i] = buf[i];
244.3327 +        }
244.3328 +        return hasSupplementary ? new SliceS(tmp) : new Slice(tmp);
244.3329 +    }
244.3330 +
244.3331 +    /**
244.3332 +     * The following classes are the building components of the object
244.3333 +     * tree that represents a compiled regular expression. The object tree
244.3334 +     * is made of individual elements that handle constructs in the Pattern.
244.3335 +     * Each type of object knows how to match its equivalent construct with
244.3336 +     * the match() method.
244.3337 +     */
244.3338 +
244.3339 +    /**
244.3340 +     * Base class for all node classes. Subclasses should override the match()
244.3341 +     * method as appropriate. This class is an accepting node, so its match()
244.3342 +     * always returns true.
244.3343 +     */
244.3344 +    static class Node extends Object {
244.3345 +        Node next;
244.3346 +        Node() {
244.3347 +            next = Pattern.accept;
244.3348 +        }
244.3349 +        /**
244.3350 +         * This method implements the classic accept node.
244.3351 +         */
244.3352 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3353 +            matcher.last = i;
244.3354 +            matcher.groups[0] = matcher.first;
244.3355 +            matcher.groups[1] = matcher.last;
244.3356 +            return true;
244.3357 +        }
244.3358 +        /**
244.3359 +         * This method is good for all zero length assertions.
244.3360 +         */
244.3361 +        boolean study(TreeInfo info) {
244.3362 +            if (next != null) {
244.3363 +                return next.study(info);
244.3364 +            } else {
244.3365 +                return info.deterministic;
244.3366 +            }
244.3367 +        }
244.3368 +    }
244.3369 +
244.3370 +    static class LastNode extends Node {
244.3371 +        /**
244.3372 +         * This method implements the classic accept node with
244.3373 +         * the addition of a check to see if the match occurred
244.3374 +         * using all of the input.
244.3375 +         */
244.3376 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3377 +            if (matcher.acceptMode == Matcher.ENDANCHOR && i != matcher.to)
244.3378 +                return false;
244.3379 +            matcher.last = i;
244.3380 +            matcher.groups[0] = matcher.first;
244.3381 +            matcher.groups[1] = matcher.last;
244.3382 +            return true;
244.3383 +        }
244.3384 +    }
244.3385 +
244.3386 +    /**
244.3387 +     * Used for REs that can start anywhere within the input string.
244.3388 +     * This basically tries to match repeatedly at each spot in the
244.3389 +     * input string, moving forward after each try. An anchored search
244.3390 +     * or a BnM will bypass this node completely.
244.3391 +     */
244.3392 +    static class Start extends Node {
244.3393 +        int minLength;
244.3394 +        Start(Node node) {
244.3395 +            this.next = node;
244.3396 +            TreeInfo info = new TreeInfo();
244.3397 +            next.study(info);
244.3398 +            minLength = info.minLength;
244.3399 +        }
244.3400 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3401 +            if (i > matcher.to - minLength) {
244.3402 +                matcher.hitEnd = true;
244.3403 +                return false;
244.3404 +            }
244.3405 +            int guard = matcher.to - minLength;
244.3406 +            for (; i <= guard; i++) {
244.3407 +                if (next.match(matcher, i, seq)) {
244.3408 +                    matcher.first = i;
244.3409 +                    matcher.groups[0] = matcher.first;
244.3410 +                    matcher.groups[1] = matcher.last;
244.3411 +                    return true;
244.3412 +                }
244.3413 +            }
244.3414 +            matcher.hitEnd = true;
244.3415 +            return false;
244.3416 +        }
244.3417 +        boolean study(TreeInfo info) {
244.3418 +            next.study(info);
244.3419 +            info.maxValid = false;
244.3420 +            info.deterministic = false;
244.3421 +            return false;
244.3422 +        }
244.3423 +    }
244.3424 +
244.3425 +    /*
244.3426 +     * StartS supports supplementary characters, including unpaired surrogates.
244.3427 +     */
244.3428 +    static final class StartS extends Start {
244.3429 +        StartS(Node node) {
244.3430 +            super(node);
244.3431 +        }
244.3432 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3433 +            if (i > matcher.to - minLength) {
244.3434 +                matcher.hitEnd = true;
244.3435 +                return false;
244.3436 +            }
244.3437 +            int guard = matcher.to - minLength;
244.3438 +            while (i <= guard) {
244.3439 +                //if ((ret = next.match(matcher, i, seq)) || i == guard)
244.3440 +                if (next.match(matcher, i, seq)) {
244.3441 +                    matcher.first = i;
244.3442 +                    matcher.groups[0] = matcher.first;
244.3443 +                    matcher.groups[1] = matcher.last;
244.3444 +                    return true;
244.3445 +                }
244.3446 +                if (i == guard)
244.3447 +                    break;
244.3448 +                // Optimization to move to the next character. This is
244.3449 +                // faster than countChars(seq, i, 1).
244.3450 +                if (Character.isHighSurrogate(seq.charAt(i++))) {
244.3451 +                    if (i < seq.length() &&
244.3452 +                        Character.isLowSurrogate(seq.charAt(i))) {
244.3453 +                        i++;
244.3454 +                    }
244.3455 +                }
244.3456 +            }
244.3457 +            matcher.hitEnd = true;
244.3458 +            return false;
244.3459 +        }
244.3460 +    }
244.3461 +
244.3462 +    /**
244.3463 +     * Node to anchor at the beginning of input. This object implements the
244.3464 +     * match for a \A sequence, and the caret anchor will use this if not in
244.3465 +     * multiline mode.
244.3466 +     */
244.3467 +    static final class Begin extends Node {
244.3468 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3469 +            int fromIndex = (matcher.anchoringBounds) ?
244.3470 +                matcher.from : 0;
244.3471 +            if (i == fromIndex && next.match(matcher, i, seq)) {
244.3472 +                matcher.first = i;
244.3473 +                matcher.groups[0] = i;
244.3474 +                matcher.groups[1] = matcher.last;
244.3475 +                return true;
244.3476 +            } else {
244.3477 +                return false;
244.3478 +            }
244.3479 +        }
244.3480 +    }
244.3481 +
244.3482 +    /**
244.3483 +     * Node to anchor at the end of input. This is the absolute end, so this
244.3484 +     * should not match at the last newline before the end as $ will.
244.3485 +     */
244.3486 +    static final class End extends Node {
244.3487 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3488 +            int endIndex = (matcher.anchoringBounds) ?
244.3489 +                matcher.to : matcher.getTextLength();
244.3490 +            if (i == endIndex) {
244.3491 +                matcher.hitEnd = true;
244.3492 +                return next.match(matcher, i, seq);
244.3493 +            }
244.3494 +            return false;
244.3495 +        }
244.3496 +    }
244.3497 +
244.3498 +    /**
244.3499 +     * Node to anchor at the beginning of a line. This is essentially the
244.3500 +     * object to match for the multiline ^.
244.3501 +     */
244.3502 +    static final class Caret extends Node {
244.3503 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3504 +            int startIndex = matcher.from;
244.3505 +            int endIndex = matcher.to;
244.3506 +            if (!matcher.anchoringBounds) {
244.3507 +                startIndex = 0;
244.3508 +                endIndex = matcher.getTextLength();
244.3509 +            }
244.3510 +            // Perl does not match ^ at end of input even after newline
244.3511 +            if (i == endIndex) {
244.3512 +                matcher.hitEnd = true;
244.3513 +                return false;
244.3514 +            }
244.3515 +            if (i > startIndex) {
244.3516 +                char ch = seq.charAt(i-1);
244.3517 +                if (ch != '\n' && ch != '\r'
244.3518 +                    && (ch|1) != '\u2029'
244.3519 +                    && ch != '\u0085' ) {
244.3520 +                    return false;
244.3521 +                }
244.3522 +                // Should treat /r/n as one newline
244.3523 +                if (ch == '\r' && seq.charAt(i) == '\n')
244.3524 +                    return false;
244.3525 +            }
244.3526 +            return next.match(matcher, i, seq);
244.3527 +        }
244.3528 +    }
244.3529 +
244.3530 +    /**
244.3531 +     * Node to anchor at the beginning of a line when in unixdot mode.
244.3532 +     */
244.3533 +    static final class UnixCaret extends Node {
244.3534 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3535 +            int startIndex = matcher.from;
244.3536 +            int endIndex = matcher.to;
244.3537 +            if (!matcher.anchoringBounds) {
244.3538 +                startIndex = 0;
244.3539 +                endIndex = matcher.getTextLength();
244.3540 +            }
244.3541 +            // Perl does not match ^ at end of input even after newline
244.3542 +            if (i == endIndex) {
244.3543 +                matcher.hitEnd = true;
244.3544 +                return false;
244.3545 +            }
244.3546 +            if (i > startIndex) {
244.3547 +                char ch = seq.charAt(i-1);
244.3548 +                if (ch != '\n') {
244.3549 +                    return false;
244.3550 +                }
244.3551 +            }
244.3552 +            return next.match(matcher, i, seq);
244.3553 +        }
244.3554 +    }
244.3555 +
244.3556 +    /**
244.3557 +     * Node to match the location where the last match ended.
244.3558 +     * This is used for the \G construct.
244.3559 +     */
244.3560 +    static final class LastMatch extends Node {
244.3561 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3562 +            if (i != matcher.oldLast)
244.3563 +                return false;
244.3564 +            return next.match(matcher, i, seq);
244.3565 +        }
244.3566 +    }
244.3567 +
244.3568 +    /**
244.3569 +     * Node to anchor at the end of a line or the end of input based on the
244.3570 +     * multiline mode.
244.3571 +     *
244.3572 +     * When not in multiline mode, the $ can only match at the very end
244.3573 +     * of the input, unless the input ends in a line terminator in which
244.3574 +     * it matches right before the last line terminator.
244.3575 +     *
244.3576 +     * Note that \r\n is considered an atomic line terminator.
244.3577 +     *
244.3578 +     * Like ^ the $ operator matches at a position, it does not match the
244.3579 +     * line terminators themselves.
244.3580 +     */
244.3581 +    static final class Dollar extends Node {
244.3582 +        boolean multiline;
244.3583 +        Dollar(boolean mul) {
244.3584 +            multiline = mul;
244.3585 +        }
244.3586 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3587 +            int endIndex = (matcher.anchoringBounds) ?
244.3588 +                matcher.to : matcher.getTextLength();
244.3589 +            if (!multiline) {
244.3590 +                if (i < endIndex - 2)
244.3591 +                    return false;
244.3592 +                if (i == endIndex - 2) {
244.3593 +                    char ch = seq.charAt(i);
244.3594 +                    if (ch != '\r')
244.3595 +                        return false;
244.3596 +                    ch = seq.charAt(i + 1);
244.3597 +                    if (ch != '\n')
244.3598 +                        return false;
244.3599 +                }
244.3600 +            }
244.3601 +            // Matches before any line terminator; also matches at the
244.3602 +            // end of input
244.3603 +            // Before line terminator:
244.3604 +            // If multiline, we match here no matter what
244.3605 +            // If not multiline, fall through so that the end
244.3606 +            // is marked as hit; this must be a /r/n or a /n
244.3607 +            // at the very end so the end was hit; more input
244.3608 +            // could make this not match here
244.3609 +            if (i < endIndex) {
244.3610 +                char ch = seq.charAt(i);
244.3611 +                 if (ch == '\n') {
244.3612 +                     // No match between \r\n
244.3613 +                     if (i > 0 && seq.charAt(i-1) == '\r')
244.3614 +                         return false;
244.3615 +                     if (multiline)
244.3616 +                         return next.match(matcher, i, seq);
244.3617 +                 } else if (ch == '\r' || ch == '\u0085' ||
244.3618 +                            (ch|1) == '\u2029') {
244.3619 +                     if (multiline)
244.3620 +                         return next.match(matcher, i, seq);
244.3621 +                 } else { // No line terminator, no match
244.3622 +                     return false;
244.3623 +                 }
244.3624 +            }
244.3625 +            // Matched at current end so hit end
244.3626 +            matcher.hitEnd = true;
244.3627 +            // If a $ matches because of end of input, then more input
244.3628 +            // could cause it to fail!
244.3629 +            matcher.requireEnd = true;
244.3630 +            return next.match(matcher, i, seq);
244.3631 +        }
244.3632 +        boolean study(TreeInfo info) {
244.3633 +            next.study(info);
244.3634 +            return info.deterministic;
244.3635 +        }
244.3636 +    }
244.3637 +
244.3638 +    /**
244.3639 +     * Node to anchor at the end of a line or the end of input based on the
244.3640 +     * multiline mode when in unix lines mode.
244.3641 +     */
244.3642 +    static final class UnixDollar extends Node {
244.3643 +        boolean multiline;
244.3644 +        UnixDollar(boolean mul) {
244.3645 +            multiline = mul;
244.3646 +        }
244.3647 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3648 +            int endIndex = (matcher.anchoringBounds) ?
244.3649 +                matcher.to : matcher.getTextLength();
244.3650 +            if (i < endIndex) {
244.3651 +                char ch = seq.charAt(i);
244.3652 +                if (ch == '\n') {
244.3653 +                    // If not multiline, then only possible to
244.3654 +                    // match at very end or one before end
244.3655 +                    if (multiline == false && i != endIndex - 1)
244.3656 +                        return false;
244.3657 +                    // If multiline return next.match without setting
244.3658 +                    // matcher.hitEnd
244.3659 +                    if (multiline)
244.3660 +                        return next.match(matcher, i, seq);
244.3661 +                } else {
244.3662 +                    return false;
244.3663 +                }
244.3664 +            }
244.3665 +            // Matching because at the end or 1 before the end;
244.3666 +            // more input could change this so set hitEnd
244.3667 +            matcher.hitEnd = true;
244.3668 +            // If a $ matches because of end of input, then more input
244.3669 +            // could cause it to fail!
244.3670 +            matcher.requireEnd = true;
244.3671 +            return next.match(matcher, i, seq);
244.3672 +        }
244.3673 +        boolean study(TreeInfo info) {
244.3674 +            next.study(info);
244.3675 +            return info.deterministic;
244.3676 +        }
244.3677 +    }
244.3678 +
244.3679 +    /**
244.3680 +     * Abstract node class to match one character satisfying some
244.3681 +     * boolean property.
244.3682 +     */
244.3683 +    private static abstract class CharProperty extends Node {
244.3684 +        abstract boolean isSatisfiedBy(int ch);
244.3685 +        CharProperty complement() {
244.3686 +            return new CharProperty() {
244.3687 +                    boolean isSatisfiedBy(int ch) {
244.3688 +                        return ! CharProperty.this.isSatisfiedBy(ch);}};
244.3689 +        }
244.3690 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3691 +            if (i < matcher.to) {
244.3692 +                int ch = Character.codePointAt(seq, i);
244.3693 +                return isSatisfiedBy(ch)
244.3694 +                    && next.match(matcher, i+Character.charCount(ch), seq);
244.3695 +            } else {
244.3696 +                matcher.hitEnd = true;
244.3697 +                return false;
244.3698 +            }
244.3699 +        }
244.3700 +        boolean study(TreeInfo info) {
244.3701 +            info.minLength++;
244.3702 +            info.maxLength++;
244.3703 +            return next.study(info);
244.3704 +        }
244.3705 +    }
244.3706 +
244.3707 +    /**
244.3708 +     * Optimized version of CharProperty that works only for
244.3709 +     * properties never satisfied by Supplementary characters.
244.3710 +     */
244.3711 +    private static abstract class BmpCharProperty extends CharProperty {
244.3712 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3713 +            if (i < matcher.to) {
244.3714 +                return isSatisfiedBy(seq.charAt(i))
244.3715 +                    && next.match(matcher, i+1, seq);
244.3716 +            } else {
244.3717 +                matcher.hitEnd = true;
244.3718 +                return false;
244.3719 +            }
244.3720 +        }
244.3721 +    }
244.3722 +
244.3723 +    /**
244.3724 +     * Node class that matches a Supplementary Unicode character
244.3725 +     */
244.3726 +    static final class SingleS extends CharProperty {
244.3727 +        final int c;
244.3728 +        SingleS(int c) { this.c = c; }
244.3729 +        boolean isSatisfiedBy(int ch) {
244.3730 +            return ch == c;
244.3731 +        }
244.3732 +    }
244.3733 +
244.3734 +    /**
244.3735 +     * Optimization -- matches a given BMP character
244.3736 +     */
244.3737 +    static final class Single extends BmpCharProperty {
244.3738 +        final int c;
244.3739 +        Single(int c) { this.c = c; }
244.3740 +        boolean isSatisfiedBy(int ch) {
244.3741 +            return ch == c;
244.3742 +        }
244.3743 +    }
244.3744 +
244.3745 +    /**
244.3746 +     * Case insensitive matches a given BMP character
244.3747 +     */
244.3748 +    static final class SingleI extends BmpCharProperty {
244.3749 +        final int lower;
244.3750 +        final int upper;
244.3751 +        SingleI(int lower, int upper) {
244.3752 +            this.lower = lower;
244.3753 +            this.upper = upper;
244.3754 +        }
244.3755 +        boolean isSatisfiedBy(int ch) {
244.3756 +            return ch == lower || ch == upper;
244.3757 +        }
244.3758 +    }
244.3759 +
244.3760 +    /**
244.3761 +     * Unicode case insensitive matches a given Unicode character
244.3762 +     */
244.3763 +    static final class SingleU extends CharProperty {
244.3764 +        final int lower;
244.3765 +        SingleU(int lower) {
244.3766 +            this.lower = lower;
244.3767 +        }
244.3768 +        boolean isSatisfiedBy(int ch) {
244.3769 +            return lower == ch ||
244.3770 +                lower == Character.toLowerCase(Character.toUpperCase(ch));
244.3771 +        }
244.3772 +    }
244.3773 +
244.3774 +
244.3775 +    /**
244.3776 +     * Node class that matches a Unicode block.
244.3777 +     *
244.3778 +    static final class Block extends CharProperty {
244.3779 +        final Character.UnicodeBlock block;
244.3780 +        Block(Character.UnicodeBlock block) {
244.3781 +            this.block = block;
244.3782 +        }
244.3783 +        boolean isSatisfiedBy(int ch) {
244.3784 +            return block == Character.UnicodeBlock.of(ch);
244.3785 +        }
244.3786 +    }
244.3787 +
244.3788 +    /**
244.3789 +     * Node class that matches a Unicode script
244.3790 +     *
244.3791 +    static final class Script extends CharProperty {
244.3792 +        final Character.UnicodeScript script;
244.3793 +        Script(Character.UnicodeScript script) {
244.3794 +            this.script = script;
244.3795 +        }
244.3796 +        boolean isSatisfiedBy(int ch) {
244.3797 +            return script == Character.UnicodeScript.of(ch);
244.3798 +        }
244.3799 +    }
244.3800 +
244.3801 +    /**
244.3802 +     * Node class that matches a Unicode category.
244.3803 +     */
244.3804 +    static final class Category extends CharProperty {
244.3805 +        final int typeMask;
244.3806 +        Category(int typeMask) { this.typeMask = typeMask; }
244.3807 +        boolean isSatisfiedBy(int ch) {
244.3808 +            return (typeMask & (1 << Character.getType(ch))) != 0;
244.3809 +        }
244.3810 +    }
244.3811 +
244.3812 +    /**
244.3813 +     * Node class that matches a Unicode "type"
244.3814 +     */
244.3815 +    static final class Utype extends CharProperty {
244.3816 +        final UnicodeProp uprop;
244.3817 +        Utype(UnicodeProp uprop) { this.uprop = uprop; }
244.3818 +        boolean isSatisfiedBy(int ch) {
244.3819 +            return uprop.is(ch);
244.3820 +        }
244.3821 +    }
244.3822 +
244.3823 +
244.3824 +    /**
244.3825 +     * Node class that matches a POSIX type.
244.3826 +     */
244.3827 +    static final class Ctype extends BmpCharProperty {
244.3828 +        final int ctype;
244.3829 +        Ctype(int ctype) { this.ctype = ctype; }
244.3830 +        boolean isSatisfiedBy(int ch) {
244.3831 +            return ch < 128 && ASCII.isType(ch, ctype);
244.3832 +        }
244.3833 +    }
244.3834 +
244.3835 +    /**
244.3836 +     * Base class for all Slice nodes
244.3837 +     */
244.3838 +    static class SliceNode extends Node {
244.3839 +        int[] buffer;
244.3840 +        SliceNode(int[] buf) {
244.3841 +            buffer = buf;
244.3842 +        }
244.3843 +        boolean study(TreeInfo info) {
244.3844 +            info.minLength += buffer.length;
244.3845 +            info.maxLength += buffer.length;
244.3846 +            return next.study(info);
244.3847 +        }
244.3848 +    }
244.3849 +
244.3850 +    /**
244.3851 +     * Node class for a case sensitive/BMP-only sequence of literal
244.3852 +     * characters.
244.3853 +     */
244.3854 +    static final class Slice extends SliceNode {
244.3855 +        Slice(int[] buf) {
244.3856 +            super(buf);
244.3857 +        }
244.3858 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3859 +            int[] buf = buffer;
244.3860 +            int len = buf.length;
244.3861 +            for (int j=0; j<len; j++) {
244.3862 +                if ((i+j) >= matcher.to) {
244.3863 +                    matcher.hitEnd = true;
244.3864 +                    return false;
244.3865 +                }
244.3866 +                if (buf[j] != seq.charAt(i+j))
244.3867 +                    return false;
244.3868 +            }
244.3869 +            return next.match(matcher, i+len, seq);
244.3870 +        }
244.3871 +    }
244.3872 +
244.3873 +    /**
244.3874 +     * Node class for a case_insensitive/BMP-only sequence of literal
244.3875 +     * characters.
244.3876 +     */
244.3877 +    static class SliceI extends SliceNode {
244.3878 +        SliceI(int[] buf) {
244.3879 +            super(buf);
244.3880 +        }
244.3881 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3882 +            int[] buf = buffer;
244.3883 +            int len = buf.length;
244.3884 +            for (int j=0; j<len; j++) {
244.3885 +                if ((i+j) >= matcher.to) {
244.3886 +                    matcher.hitEnd = true;
244.3887 +                    return false;
244.3888 +                }
244.3889 +                int c = seq.charAt(i+j);
244.3890 +                if (buf[j] != c &&
244.3891 +                    buf[j] != ASCII.toLower(c))
244.3892 +                    return false;
244.3893 +            }
244.3894 +            return next.match(matcher, i+len, seq);
244.3895 +        }
244.3896 +    }
244.3897 +
244.3898 +    /**
244.3899 +     * Node class for a unicode_case_insensitive/BMP-only sequence of
244.3900 +     * literal characters. Uses unicode case folding.
244.3901 +     */
244.3902 +    static final class SliceU extends SliceNode {
244.3903 +        SliceU(int[] buf) {
244.3904 +            super(buf);
244.3905 +        }
244.3906 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3907 +            int[] buf = buffer;
244.3908 +            int len = buf.length;
244.3909 +            for (int j=0; j<len; j++) {
244.3910 +                if ((i+j) >= matcher.to) {
244.3911 +                    matcher.hitEnd = true;
244.3912 +                    return false;
244.3913 +                }
244.3914 +                int c = seq.charAt(i+j);
244.3915 +                if (buf[j] != c &&
244.3916 +                    buf[j] != Character.toLowerCase(Character.toUpperCase(c)))
244.3917 +                    return false;
244.3918 +            }
244.3919 +            return next.match(matcher, i+len, seq);
244.3920 +        }
244.3921 +    }
244.3922 +
244.3923 +    /**
244.3924 +     * Node class for a case sensitive sequence of literal characters
244.3925 +     * including supplementary characters.
244.3926 +     */
244.3927 +    static final class SliceS extends SliceNode {
244.3928 +        SliceS(int[] buf) {
244.3929 +            super(buf);
244.3930 +        }
244.3931 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3932 +            int[] buf = buffer;
244.3933 +            int x = i;
244.3934 +            for (int j = 0; j < buf.length; j++) {
244.3935 +                if (x >= matcher.to) {
244.3936 +                    matcher.hitEnd = true;
244.3937 +                    return false;
244.3938 +                }
244.3939 +                int c = Character.codePointAt(seq, x);
244.3940 +                if (buf[j] != c)
244.3941 +                    return false;
244.3942 +                x += Character.charCount(c);
244.3943 +                if (x > matcher.to) {
244.3944 +                    matcher.hitEnd = true;
244.3945 +                    return false;
244.3946 +                }
244.3947 +            }
244.3948 +            return next.match(matcher, x, seq);
244.3949 +        }
244.3950 +    }
244.3951 +
244.3952 +    /**
244.3953 +     * Node class for a case insensitive sequence of literal characters
244.3954 +     * including supplementary characters.
244.3955 +     */
244.3956 +    static class SliceIS extends SliceNode {
244.3957 +        SliceIS(int[] buf) {
244.3958 +            super(buf);
244.3959 +        }
244.3960 +        int toLower(int c) {
244.3961 +            return ASCII.toLower(c);
244.3962 +        }
244.3963 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.3964 +            int[] buf = buffer;
244.3965 +            int x = i;
244.3966 +            for (int j = 0; j < buf.length; j++) {
244.3967 +                if (x >= matcher.to) {
244.3968 +                    matcher.hitEnd = true;
244.3969 +                    return false;
244.3970 +                }
244.3971 +                int c = Character.codePointAt(seq, x);
244.3972 +                if (buf[j] != c && buf[j] != toLower(c))
244.3973 +                    return false;
244.3974 +                x += Character.charCount(c);
244.3975 +                if (x > matcher.to) {
244.3976 +                    matcher.hitEnd = true;
244.3977 +                    return false;
244.3978 +                }
244.3979 +            }
244.3980 +            return next.match(matcher, x, seq);
244.3981 +        }
244.3982 +    }
244.3983 +
244.3984 +    /**
244.3985 +     * Node class for a case insensitive sequence of literal characters.
244.3986 +     * Uses unicode case folding.
244.3987 +     */
244.3988 +    static final class SliceUS extends SliceIS {
244.3989 +        SliceUS(int[] buf) {
244.3990 +            super(buf);
244.3991 +        }
244.3992 +        int toLower(int c) {
244.3993 +            return Character.toLowerCase(Character.toUpperCase(c));
244.3994 +        }
244.3995 +    }
244.3996 +
244.3997 +    private static boolean inRange(int lower, int ch, int upper) {
244.3998 +        return lower <= ch && ch <= upper;
244.3999 +    }
244.4000 +
244.4001 +    /**
244.4002 +     * Returns node for matching characters within an explicit value range.
244.4003 +     */
244.4004 +    private static CharProperty rangeFor(final int lower,
244.4005 +                                         final int upper) {
244.4006 +        return new CharProperty() {
244.4007 +                boolean isSatisfiedBy(int ch) {
244.4008 +                    return inRange(lower, ch, upper);}};
244.4009 +    }
244.4010 +
244.4011 +    /**
244.4012 +     * Returns node for matching characters within an explicit value
244.4013 +     * range in a case insensitive manner.
244.4014 +     */
244.4015 +    private CharProperty caseInsensitiveRangeFor(final int lower,
244.4016 +                                                 final int upper) {
244.4017 +        if (has(UNICODE_CASE))
244.4018 +            return new CharProperty() {
244.4019 +                boolean isSatisfiedBy(int ch) {
244.4020 +                    if (inRange(lower, ch, upper))
244.4021 +                        return true;
244.4022 +                    int up = Character.toUpperCase(ch);
244.4023 +                    return inRange(lower, up, upper) ||
244.4024 +                           inRange(lower, Character.toLowerCase(up), upper);}};
244.4025 +        return new CharProperty() {
244.4026 +            boolean isSatisfiedBy(int ch) {
244.4027 +                return inRange(lower, ch, upper) ||
244.4028 +                    ASCII.isAscii(ch) &&
244.4029 +                        (inRange(lower, ASCII.toUpper(ch), upper) ||
244.4030 +                         inRange(lower, ASCII.toLower(ch), upper));
244.4031 +            }};
244.4032 +    }
244.4033 +
244.4034 +    /**
244.4035 +     * Implements the Unicode category ALL and the dot metacharacter when
244.4036 +     * in dotall mode.
244.4037 +     */
244.4038 +    static final class All extends CharProperty {
244.4039 +        boolean isSatisfiedBy(int ch) {
244.4040 +            return true;
244.4041 +        }
244.4042 +    }
244.4043 +
244.4044 +    /**
244.4045 +     * Node class for the dot metacharacter when dotall is not enabled.
244.4046 +     */
244.4047 +    static final class Dot extends CharProperty {
244.4048 +        boolean isSatisfiedBy(int ch) {
244.4049 +            return (ch != '\n' && ch != '\r'
244.4050 +                    && (ch|1) != '\u2029'
244.4051 +                    && ch != '\u0085');
244.4052 +        }
244.4053 +    }
244.4054 +
244.4055 +    /**
244.4056 +     * Node class for the dot metacharacter when dotall is not enabled
244.4057 +     * but UNIX_LINES is enabled.
244.4058 +     */
244.4059 +    static final class UnixDot extends CharProperty {
244.4060 +        boolean isSatisfiedBy(int ch) {
244.4061 +            return ch != '\n';
244.4062 +        }
244.4063 +    }
244.4064 +
244.4065 +    /**
244.4066 +     * The 0 or 1 quantifier. This one class implements all three types.
244.4067 +     */
244.4068 +    static final class Ques extends Node {
244.4069 +        Node atom;
244.4070 +        int type;
244.4071 +        Ques(Node node, int type) {
244.4072 +            this.atom = node;
244.4073 +            this.type = type;
244.4074 +        }
244.4075 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4076 +            switch (type) {
244.4077 +            case GREEDY:
244.4078 +                return (atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq))
244.4079 +                    || next.match(matcher, i, seq);
244.4080 +            case LAZY:
244.4081 +                return next.match(matcher, i, seq)
244.4082 +                    || (atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq));
244.4083 +            case POSSESSIVE:
244.4084 +                if (atom.match(matcher, i, seq)) i = matcher.last;
244.4085 +                return next.match(matcher, i, seq);
244.4086 +            default:
244.4087 +                return atom.match(matcher, i, seq) && next.match(matcher, matcher.last, seq);
244.4088 +            }
244.4089 +        }
244.4090 +        boolean study(TreeInfo info) {
244.4091 +            if (type != INDEPENDENT) {
244.4092 +                int minL = info.minLength;
244.4093 +                atom.study(info);
244.4094 +                info.minLength = minL;
244.4095 +                info.deterministic = false;
244.4096 +                return next.study(info);
244.4097 +            } else {
244.4098 +                atom.study(info);
244.4099 +                return next.study(info);
244.4100 +            }
244.4101 +        }
244.4102 +    }
244.4103 +
244.4104 +    /**
244.4105 +     * Handles the curly-brace style repetition with a specified minimum and
244.4106 +     * maximum occurrences. The * quantifier is handled as a special case.
244.4107 +     * This class handles the three types.
244.4108 +     */
244.4109 +    static final class Curly extends Node {
244.4110 +        Node atom;
244.4111 +        int type;
244.4112 +        int cmin;
244.4113 +        int cmax;
244.4114 +
244.4115 +        Curly(Node node, int cmin, int cmax, int type) {
244.4116 +            this.atom = node;
244.4117 +            this.type = type;
244.4118 +            this.cmin = cmin;
244.4119 +            this.cmax = cmax;
244.4120 +        }
244.4121 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4122 +            int j;
244.4123 +            for (j = 0; j < cmin; j++) {
244.4124 +                if (atom.match(matcher, i, seq)) {
244.4125 +                    i = matcher.last;
244.4126 +                    continue;
244.4127 +                }
244.4128 +                return false;
244.4129 +            }
244.4130 +            if (type == GREEDY)
244.4131 +                return match0(matcher, i, j, seq);
244.4132 +            else if (type == LAZY)
244.4133 +                return match1(matcher, i, j, seq);
244.4134 +            else
244.4135 +                return match2(matcher, i, j, seq);
244.4136 +        }
244.4137 +        // Greedy match.
244.4138 +        // i is the index to start matching at
244.4139 +        // j is the number of atoms that have matched
244.4140 +        boolean match0(Matcher matcher, int i, int j, CharSequence seq) {
244.4141 +            if (j >= cmax) {
244.4142 +                // We have matched the maximum... continue with the rest of
244.4143 +                // the regular expression
244.4144 +                return next.match(matcher, i, seq);
244.4145 +            }
244.4146 +            int backLimit = j;
244.4147 +            while (atom.match(matcher, i, seq)) {
244.4148 +                // k is the length of this match
244.4149 +                int k = matcher.last - i;
244.4150 +                if (k == 0) // Zero length match
244.4151 +                    break;
244.4152 +                // Move up index and number matched
244.4153 +                i = matcher.last;
244.4154 +                j++;
244.4155 +                // We are greedy so match as many as we can
244.4156 +                while (j < cmax) {
244.4157 +                    if (!atom.match(matcher, i, seq))
244.4158 +                        break;
244.4159 +                    if (i + k != matcher.last) {
244.4160 +                        if (match0(matcher, matcher.last, j+1, seq))
244.4161 +                            return true;
244.4162 +                        break;
244.4163 +                    }
244.4164 +                    i += k;
244.4165 +                    j++;
244.4166 +                }
244.4167 +                // Handle backing off if match fails
244.4168 +                while (j >= backLimit) {
244.4169 +                   if (next.match(matcher, i, seq))
244.4170 +                        return true;
244.4171 +                    i -= k;
244.4172 +                    j--;
244.4173 +                }
244.4174 +                return false;
244.4175 +            }
244.4176 +            return next.match(matcher, i, seq);
244.4177 +        }
244.4178 +        // Reluctant match. At this point, the minimum has been satisfied.
244.4179 +        // i is the index to start matching at
244.4180 +        // j is the number of atoms that have matched
244.4181 +        boolean match1(Matcher matcher, int i, int j, CharSequence seq) {
244.4182 +            for (;;) {
244.4183 +                // Try finishing match without consuming any more
244.4184 +                if (next.match(matcher, i, seq))
244.4185 +                    return true;
244.4186 +                // At the maximum, no match found
244.4187 +                if (j >= cmax)
244.4188 +                    return false;
244.4189 +                // Okay, must try one more atom
244.4190 +                if (!atom.match(matcher, i, seq))
244.4191 +                    return false;
244.4192 +                // If we haven't moved forward then must break out
244.4193 +                if (i == matcher.last)
244.4194 +                    return false;
244.4195 +                // Move up index and number matched
244.4196 +                i = matcher.last;
244.4197 +                j++;
244.4198 +            }
244.4199 +        }
244.4200 +        boolean match2(Matcher matcher, int i, int j, CharSequence seq) {
244.4201 +            for (; j < cmax; j++) {
244.4202 +                if (!atom.match(matcher, i, seq))
244.4203 +                    break;
244.4204 +                if (i == matcher.last)
244.4205 +                    break;
244.4206 +                i = matcher.last;
244.4207 +            }
244.4208 +            return next.match(matcher, i, seq);
244.4209 +        }
244.4210 +        boolean study(TreeInfo info) {
244.4211 +            // Save original info
244.4212 +            int minL = info.minLength;
244.4213 +            int maxL = info.maxLength;
244.4214 +            boolean maxV = info.maxValid;
244.4215 +            boolean detm = info.deterministic;
244.4216 +            info.reset();
244.4217 +
244.4218 +            atom.study(info);
244.4219 +
244.4220 +            int temp = info.minLength * cmin + minL;
244.4221 +            if (temp < minL) {
244.4222 +                temp = 0xFFFFFFF; // arbitrary large number
244.4223 +            }
244.4224 +            info.minLength = temp;
244.4225 +
244.4226 +            if (maxV & info.maxValid) {
244.4227 +                temp = info.maxLength * cmax + maxL;
244.4228 +                info.maxLength = temp;
244.4229 +                if (temp < maxL) {
244.4230 +                    info.maxValid = false;
244.4231 +                }
244.4232 +            } else {
244.4233 +                info.maxValid = false;
244.4234 +            }
244.4235 +
244.4236 +            if (info.deterministic && cmin == cmax)
244.4237 +                info.deterministic = detm;
244.4238 +            else
244.4239 +                info.deterministic = false;
244.4240 +
244.4241 +            return next.study(info);
244.4242 +        }
244.4243 +    }
244.4244 +
244.4245 +    /**
244.4246 +     * Handles the curly-brace style repetition with a specified minimum and
244.4247 +     * maximum occurrences in deterministic cases. This is an iterative
244.4248 +     * optimization over the Prolog and Loop system which would handle this
244.4249 +     * in a recursive way. The * quantifier is handled as a special case.
244.4250 +     * If capture is true then this class saves group settings and ensures
244.4251 +     * that groups are unset when backing off of a group match.
244.4252 +     */
244.4253 +    static final class GroupCurly extends Node {
244.4254 +        Node atom;
244.4255 +        int type;
244.4256 +        int cmin;
244.4257 +        int cmax;
244.4258 +        int localIndex;
244.4259 +        int groupIndex;
244.4260 +        boolean capture;
244.4261 +
244.4262 +        GroupCurly(Node node, int cmin, int cmax, int type, int local,
244.4263 +                   int group, boolean capture) {
244.4264 +            this.atom = node;
244.4265 +            this.type = type;
244.4266 +            this.cmin = cmin;
244.4267 +            this.cmax = cmax;
244.4268 +            this.localIndex = local;
244.4269 +            this.groupIndex = group;
244.4270 +            this.capture = capture;
244.4271 +        }
244.4272 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4273 +            int[] groups = matcher.groups;
244.4274 +            int[] locals = matcher.locals;
244.4275 +            int save0 = locals[localIndex];
244.4276 +            int save1 = 0;
244.4277 +            int save2 = 0;
244.4278 +
244.4279 +            if (capture) {
244.4280 +                save1 = groups[groupIndex];
244.4281 +                save2 = groups[groupIndex+1];
244.4282 +            }
244.4283 +
244.4284 +            // Notify GroupTail there is no need to setup group info
244.4285 +            // because it will be set here
244.4286 +            locals[localIndex] = -1;
244.4287 +
244.4288 +            boolean ret = true;
244.4289 +            for (int j = 0; j < cmin; j++) {
244.4290 +                if (atom.match(matcher, i, seq)) {
244.4291 +                    if (capture) {
244.4292 +                        groups[groupIndex] = i;
244.4293 +                        groups[groupIndex+1] = matcher.last;
244.4294 +                    }
244.4295 +                    i = matcher.last;
244.4296 +                } else {
244.4297 +                    ret = false;
244.4298 +                    break;
244.4299 +                }
244.4300 +            }
244.4301 +            if (ret) {
244.4302 +                if (type == GREEDY) {
244.4303 +                    ret = match0(matcher, i, cmin, seq);
244.4304 +                } else if (type == LAZY) {
244.4305 +                    ret = match1(matcher, i, cmin, seq);
244.4306 +                } else {
244.4307 +                    ret = match2(matcher, i, cmin, seq);
244.4308 +                }
244.4309 +            }
244.4310 +            if (!ret) {
244.4311 +                locals[localIndex] = save0;
244.4312 +                if (capture) {
244.4313 +                    groups[groupIndex] = save1;
244.4314 +                    groups[groupIndex+1] = save2;
244.4315 +                }
244.4316 +            }
244.4317 +            return ret;
244.4318 +        }
244.4319 +        // Aggressive group match
244.4320 +        boolean match0(Matcher matcher, int i, int j, CharSequence seq) {
244.4321 +            int[] groups = matcher.groups;
244.4322 +            int save0 = 0;
244.4323 +            int save1 = 0;
244.4324 +            if (capture) {
244.4325 +                save0 = groups[groupIndex];
244.4326 +                save1 = groups[groupIndex+1];
244.4327 +            }
244.4328 +            for (;;) {
244.4329 +                if (j >= cmax)
244.4330 +                    break;
244.4331 +                if (!atom.match(matcher, i, seq))
244.4332 +                    break;
244.4333 +                int k = matcher.last - i;
244.4334 +                if (k <= 0) {
244.4335 +                    if (capture) {
244.4336 +                        groups[groupIndex] = i;
244.4337 +                        groups[groupIndex+1] = i + k;
244.4338 +                    }
244.4339 +                    i = i + k;
244.4340 +                    break;
244.4341 +                }
244.4342 +                for (;;) {
244.4343 +                    if (capture) {
244.4344 +                        groups[groupIndex] = i;
244.4345 +                        groups[groupIndex+1] = i + k;
244.4346 +                    }
244.4347 +                    i = i + k;
244.4348 +                    if (++j >= cmax)
244.4349 +                        break;
244.4350 +                    if (!atom.match(matcher, i, seq))
244.4351 +                        break;
244.4352 +                    if (i + k != matcher.last) {
244.4353 +                        if (match0(matcher, i, j, seq))
244.4354 +                            return true;
244.4355 +                        break;
244.4356 +                    }
244.4357 +                }
244.4358 +                while (j > cmin) {
244.4359 +                    if (next.match(matcher, i, seq)) {
244.4360 +                        if (capture) {
244.4361 +                            groups[groupIndex+1] = i;
244.4362 +                            groups[groupIndex] = i - k;
244.4363 +                        }
244.4364 +                        i = i - k;
244.4365 +                        return true;
244.4366 +                    }
244.4367 +                    // backing off
244.4368 +                    if (capture) {
244.4369 +                        groups[groupIndex+1] = i;
244.4370 +                        groups[groupIndex] = i - k;
244.4371 +                    }
244.4372 +                    i = i - k;
244.4373 +                    j--;
244.4374 +                }
244.4375 +                break;
244.4376 +            }
244.4377 +            if (capture) {
244.4378 +                groups[groupIndex] = save0;
244.4379 +                groups[groupIndex+1] = save1;
244.4380 +            }
244.4381 +            return next.match(matcher, i, seq);
244.4382 +        }
244.4383 +        // Reluctant matching
244.4384 +        boolean match1(Matcher matcher, int i, int j, CharSequence seq) {
244.4385 +            for (;;) {
244.4386 +                if (next.match(matcher, i, seq))
244.4387 +                    return true;
244.4388 +                if (j >= cmax)
244.4389 +                    return false;
244.4390 +                if (!atom.match(matcher, i, seq))
244.4391 +                    return false;
244.4392 +                if (i == matcher.last)
244.4393 +                    return false;
244.4394 +                if (capture) {
244.4395 +                    matcher.groups[groupIndex] = i;
244.4396 +                    matcher.groups[groupIndex+1] = matcher.last;
244.4397 +                }
244.4398 +                i = matcher.last;
244.4399 +                j++;
244.4400 +            }
244.4401 +        }
244.4402 +        // Possessive matching
244.4403 +        boolean match2(Matcher matcher, int i, int j, CharSequence seq) {
244.4404 +            for (; j < cmax; j++) {
244.4405 +                if (!atom.match(matcher, i, seq)) {
244.4406 +                    break;
244.4407 +                }
244.4408 +                if (capture) {
244.4409 +                    matcher.groups[groupIndex] = i;
244.4410 +                    matcher.groups[groupIndex+1] = matcher.last;
244.4411 +                }
244.4412 +                if (i == matcher.last) {
244.4413 +                    break;
244.4414 +                }
244.4415 +                i = matcher.last;
244.4416 +            }
244.4417 +            return next.match(matcher, i, seq);
244.4418 +        }
244.4419 +        boolean study(TreeInfo info) {
244.4420 +            // Save original info
244.4421 +            int minL = info.minLength;
244.4422 +            int maxL = info.maxLength;
244.4423 +            boolean maxV = info.maxValid;
244.4424 +            boolean detm = info.deterministic;
244.4425 +            info.reset();
244.4426 +
244.4427 +            atom.study(info);
244.4428 +
244.4429 +            int temp = info.minLength * cmin + minL;
244.4430 +            if (temp < minL) {
244.4431 +                temp = 0xFFFFFFF; // Arbitrary large number
244.4432 +            }
244.4433 +            info.minLength = temp;
244.4434 +
244.4435 +            if (maxV & info.maxValid) {
244.4436 +                temp = info.maxLength * cmax + maxL;
244.4437 +                info.maxLength = temp;
244.4438 +                if (temp < maxL) {
244.4439 +                    info.maxValid = false;
244.4440 +                }
244.4441 +            } else {
244.4442 +                info.maxValid = false;
244.4443 +            }
244.4444 +
244.4445 +            if (info.deterministic && cmin == cmax) {
244.4446 +                info.deterministic = detm;
244.4447 +            } else {
244.4448 +                info.deterministic = false;
244.4449 +            }
244.4450 +
244.4451 +            return next.study(info);
244.4452 +        }
244.4453 +    }
244.4454 +
244.4455 +    /**
244.4456 +     * A Guard node at the end of each atom node in a Branch. It
244.4457 +     * serves the purpose of chaining the "match" operation to
244.4458 +     * "next" but not the "study", so we can collect the TreeInfo
244.4459 +     * of each atom node without including the TreeInfo of the
244.4460 +     * "next".
244.4461 +     */
244.4462 +    static final class BranchConn extends Node {
244.4463 +        BranchConn() {};
244.4464 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4465 +            return next.match(matcher, i, seq);
244.4466 +        }
244.4467 +        boolean study(TreeInfo info) {
244.4468 +            return info.deterministic;
244.4469 +        }
244.4470 +    }
244.4471 +
244.4472 +    /**
244.4473 +     * Handles the branching of alternations. Note this is also used for
244.4474 +     * the ? quantifier to branch between the case where it matches once
244.4475 +     * and where it does not occur.
244.4476 +     */
244.4477 +    static final class Branch extends Node {
244.4478 +        Node[] atoms = new Node[2];
244.4479 +        int size = 2;
244.4480 +        Node conn;
244.4481 +        Branch(Node first, Node second, Node branchConn) {
244.4482 +            conn = branchConn;
244.4483 +            atoms[0] = first;
244.4484 +            atoms[1] = second;
244.4485 +        }
244.4486 +
244.4487 +        void add(Node node) {
244.4488 +            if (size >= atoms.length) {
244.4489 +                Node[] tmp = new Node[atoms.length*2];
244.4490 +                System.arraycopy(atoms, 0, tmp, 0, atoms.length);
244.4491 +                atoms = tmp;
244.4492 +            }
244.4493 +            atoms[size++] = node;
244.4494 +        }
244.4495 +
244.4496 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4497 +            for (int n = 0; n < size; n++) {
244.4498 +                if (atoms[n] == null) {
244.4499 +                    if (conn.next.match(matcher, i, seq))
244.4500 +                        return true;
244.4501 +                } else if (atoms[n].match(matcher, i, seq)) {
244.4502 +                    return true;
244.4503 +                }
244.4504 +            }
244.4505 +            return false;
244.4506 +        }
244.4507 +
244.4508 +        boolean study(TreeInfo info) {
244.4509 +            int minL = info.minLength;
244.4510 +            int maxL = info.maxLength;
244.4511 +            boolean maxV = info.maxValid;
244.4512 +
244.4513 +            int minL2 = Integer.MAX_VALUE; //arbitrary large enough num
244.4514 +            int maxL2 = -1;
244.4515 +            for (int n = 0; n < size; n++) {
244.4516 +                info.reset();
244.4517 +                if (atoms[n] != null)
244.4518 +                    atoms[n].study(info);
244.4519 +                minL2 = Math.min(minL2, info.minLength);
244.4520 +                maxL2 = Math.max(maxL2, info.maxLength);
244.4521 +                maxV = (maxV & info.maxValid);
244.4522 +            }
244.4523 +
244.4524 +            minL += minL2;
244.4525 +            maxL += maxL2;
244.4526 +
244.4527 +            info.reset();
244.4528 +            conn.next.study(info);
244.4529 +
244.4530 +            info.minLength += minL;
244.4531 +            info.maxLength += maxL;
244.4532 +            info.maxValid &= maxV;
244.4533 +            info.deterministic = false;
244.4534 +            return false;
244.4535 +        }
244.4536 +    }
244.4537 +
244.4538 +    /**
244.4539 +     * The GroupHead saves the location where the group begins in the locals
244.4540 +     * and restores them when the match is done.
244.4541 +     *
244.4542 +     * The matchRef is used when a reference to this group is accessed later
244.4543 +     * in the expression. The locals will have a negative value in them to
244.4544 +     * indicate that we do not want to unset the group if the reference
244.4545 +     * doesn't match.
244.4546 +     */
244.4547 +    static final class GroupHead extends Node {
244.4548 +        int localIndex;
244.4549 +        GroupHead(int localCount) {
244.4550 +            localIndex = localCount;
244.4551 +        }
244.4552 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4553 +            int save = matcher.locals[localIndex];
244.4554 +            matcher.locals[localIndex] = i;
244.4555 +            boolean ret = next.match(matcher, i, seq);
244.4556 +            matcher.locals[localIndex] = save;
244.4557 +            return ret;
244.4558 +        }
244.4559 +        boolean matchRef(Matcher matcher, int i, CharSequence seq) {
244.4560 +            int save = matcher.locals[localIndex];
244.4561 +            matcher.locals[localIndex] = ~i; // HACK
244.4562 +            boolean ret = next.match(matcher, i, seq);
244.4563 +            matcher.locals[localIndex] = save;
244.4564 +            return ret;
244.4565 +        }
244.4566 +    }
244.4567 +
244.4568 +    /**
244.4569 +     * Recursive reference to a group in the regular expression. It calls
244.4570 +     * matchRef because if the reference fails to match we would not unset
244.4571 +     * the group.
244.4572 +     */
244.4573 +    static final class GroupRef extends Node {
244.4574 +        GroupHead head;
244.4575 +        GroupRef(GroupHead head) {
244.4576 +            this.head = head;
244.4577 +        }
244.4578 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4579 +            return head.matchRef(matcher, i, seq)
244.4580 +                && next.match(matcher, matcher.last, seq);
244.4581 +        }
244.4582 +        boolean study(TreeInfo info) {
244.4583 +            info.maxValid = false;
244.4584 +            info.deterministic = false;
244.4585 +            return next.study(info);
244.4586 +        }
244.4587 +    }
244.4588 +
244.4589 +    /**
244.4590 +     * The GroupTail handles the setting of group beginning and ending
244.4591 +     * locations when groups are successfully matched. It must also be able to
244.4592 +     * unset groups that have to be backed off of.
244.4593 +     *
244.4594 +     * The GroupTail node is also used when a previous group is referenced,
244.4595 +     * and in that case no group information needs to be set.
244.4596 +     */
244.4597 +    static final class GroupTail extends Node {
244.4598 +        int localIndex;
244.4599 +        int groupIndex;
244.4600 +        GroupTail(int localCount, int groupCount) {
244.4601 +            localIndex = localCount;
244.4602 +            groupIndex = groupCount + groupCount;
244.4603 +        }
244.4604 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4605 +            int tmp = matcher.locals[localIndex];
244.4606 +            if (tmp >= 0) { // This is the normal group case.
244.4607 +                // Save the group so we can unset it if it
244.4608 +                // backs off of a match.
244.4609 +                int groupStart = matcher.groups[groupIndex];
244.4610 +                int groupEnd = matcher.groups[groupIndex+1];
244.4611 +
244.4612 +                matcher.groups[groupIndex] = tmp;
244.4613 +                matcher.groups[groupIndex+1] = i;
244.4614 +                if (next.match(matcher, i, seq)) {
244.4615 +                    return true;
244.4616 +                }
244.4617 +                matcher.groups[groupIndex] = groupStart;
244.4618 +                matcher.groups[groupIndex+1] = groupEnd;
244.4619 +                return false;
244.4620 +            } else {
244.4621 +                // This is a group reference case. We don't need to save any
244.4622 +                // group info because it isn't really a group.
244.4623 +                matcher.last = i;
244.4624 +                return true;
244.4625 +            }
244.4626 +        }
244.4627 +    }
244.4628 +
244.4629 +    /**
244.4630 +     * This sets up a loop to handle a recursive quantifier structure.
244.4631 +     */
244.4632 +    static final class Prolog extends Node {
244.4633 +        Loop loop;
244.4634 +        Prolog(Loop loop) {
244.4635 +            this.loop = loop;
244.4636 +        }
244.4637 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4638 +            return loop.matchInit(matcher, i, seq);
244.4639 +        }
244.4640 +        boolean study(TreeInfo info) {
244.4641 +            return loop.study(info);
244.4642 +        }
244.4643 +    }
244.4644 +
244.4645 +    /**
244.4646 +     * Handles the repetition count for a greedy Curly. The matchInit
244.4647 +     * is called from the Prolog to save the index of where the group
244.4648 +     * beginning is stored. A zero length group check occurs in the
244.4649 +     * normal match but is skipped in the matchInit.
244.4650 +     */
244.4651 +    static class Loop extends Node {
244.4652 +        Node body;
244.4653 +        int countIndex; // local count index in matcher locals
244.4654 +        int beginIndex; // group beginning index
244.4655 +        int cmin, cmax;
244.4656 +        Loop(int countIndex, int beginIndex) {
244.4657 +            this.countIndex = countIndex;
244.4658 +            this.beginIndex = beginIndex;
244.4659 +        }
244.4660 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4661 +            // Avoid infinite loop in zero-length case.
244.4662 +            if (i > matcher.locals[beginIndex]) {
244.4663 +                int count = matcher.locals[countIndex];
244.4664 +
244.4665 +                // This block is for before we reach the minimum
244.4666 +                // iterations required for the loop to match
244.4667 +                if (count < cmin) {
244.4668 +                    matcher.locals[countIndex] = count + 1;
244.4669 +                    boolean b = body.match(matcher, i, seq);
244.4670 +                    // If match failed we must backtrack, so
244.4671 +                    // the loop count should NOT be incremented
244.4672 +                    if (!b)
244.4673 +                        matcher.locals[countIndex] = count;
244.4674 +                    // Return success or failure since we are under
244.4675 +                    // minimum
244.4676 +                    return b;
244.4677 +                }
244.4678 +                // This block is for after we have the minimum
244.4679 +                // iterations required for the loop to match
244.4680 +                if (count < cmax) {
244.4681 +                    matcher.locals[countIndex] = count + 1;
244.4682 +                    boolean b = body.match(matcher, i, seq);
244.4683 +                    // If match failed we must backtrack, so
244.4684 +                    // the loop count should NOT be incremented
244.4685 +                    if (!b)
244.4686 +                        matcher.locals[countIndex] = count;
244.4687 +                    else
244.4688 +                        return true;
244.4689 +                }
244.4690 +            }
244.4691 +            return next.match(matcher, i, seq);
244.4692 +        }
244.4693 +        boolean matchInit(Matcher matcher, int i, CharSequence seq) {
244.4694 +            int save = matcher.locals[countIndex];
244.4695 +            boolean ret = false;
244.4696 +            if (0 < cmin) {
244.4697 +                matcher.locals[countIndex] = 1;
244.4698 +                ret = body.match(matcher, i, seq);
244.4699 +            } else if (0 < cmax) {
244.4700 +                matcher.locals[countIndex] = 1;
244.4701 +                ret = body.match(matcher, i, seq);
244.4702 +                if (ret == false)
244.4703 +                    ret = next.match(matcher, i, seq);
244.4704 +            } else {
244.4705 +                ret = next.match(matcher, i, seq);
244.4706 +            }
244.4707 +            matcher.locals[countIndex] = save;
244.4708 +            return ret;
244.4709 +        }
244.4710 +        boolean study(TreeInfo info) {
244.4711 +            info.maxValid = false;
244.4712 +            info.deterministic = false;
244.4713 +            return false;
244.4714 +        }
244.4715 +    }
244.4716 +
244.4717 +    /**
244.4718 +     * Handles the repetition count for a reluctant Curly. The matchInit
244.4719 +     * is called from the Prolog to save the index of where the group
244.4720 +     * beginning is stored. A zero length group check occurs in the
244.4721 +     * normal match but is skipped in the matchInit.
244.4722 +     */
244.4723 +    static final class LazyLoop extends Loop {
244.4724 +        LazyLoop(int countIndex, int beginIndex) {
244.4725 +            super(countIndex, beginIndex);
244.4726 +        }
244.4727 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4728 +            // Check for zero length group
244.4729 +            if (i > matcher.locals[beginIndex]) {
244.4730 +                int count = matcher.locals[countIndex];
244.4731 +                if (count < cmin) {
244.4732 +                    matcher.locals[countIndex] = count + 1;
244.4733 +                    boolean result = body.match(matcher, i, seq);
244.4734 +                    // If match failed we must backtrack, so
244.4735 +                    // the loop count should NOT be incremented
244.4736 +                    if (!result)
244.4737 +                        matcher.locals[countIndex] = count;
244.4738 +                    return result;
244.4739 +                }
244.4740 +                if (next.match(matcher, i, seq))
244.4741 +                    return true;
244.4742 +                if (count < cmax) {
244.4743 +                    matcher.locals[countIndex] = count + 1;
244.4744 +                    boolean result = body.match(matcher, i, seq);
244.4745 +                    // If match failed we must backtrack, so
244.4746 +                    // the loop count should NOT be incremented
244.4747 +                    if (!result)
244.4748 +                        matcher.locals[countIndex] = count;
244.4749 +                    return result;
244.4750 +                }
244.4751 +                return false;
244.4752 +            }
244.4753 +            return next.match(matcher, i, seq);
244.4754 +        }
244.4755 +        boolean matchInit(Matcher matcher, int i, CharSequence seq) {
244.4756 +            int save = matcher.locals[countIndex];
244.4757 +            boolean ret = false;
244.4758 +            if (0 < cmin) {
244.4759 +                matcher.locals[countIndex] = 1;
244.4760 +                ret = body.match(matcher, i, seq);
244.4761 +            } else if (next.match(matcher, i, seq)) {
244.4762 +                ret = true;
244.4763 +            } else if (0 < cmax) {
244.4764 +                matcher.locals[countIndex] = 1;
244.4765 +                ret = body.match(matcher, i, seq);
244.4766 +            }
244.4767 +            matcher.locals[countIndex] = save;
244.4768 +            return ret;
244.4769 +        }
244.4770 +        boolean study(TreeInfo info) {
244.4771 +            info.maxValid = false;
244.4772 +            info.deterministic = false;
244.4773 +            return false;
244.4774 +        }
244.4775 +    }
244.4776 +
244.4777 +    /**
244.4778 +     * Refers to a group in the regular expression. Attempts to match
244.4779 +     * whatever the group referred to last matched.
244.4780 +     */
244.4781 +    static class BackRef extends Node {
244.4782 +        int groupIndex;
244.4783 +        BackRef(int groupCount) {
244.4784 +            super();
244.4785 +            groupIndex = groupCount + groupCount;
244.4786 +        }
244.4787 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4788 +            int j = matcher.groups[groupIndex];
244.4789 +            int k = matcher.groups[groupIndex+1];
244.4790 +
244.4791 +            int groupSize = k - j;
244.4792 +
244.4793 +            // If the referenced group didn't match, neither can this
244.4794 +            if (j < 0)
244.4795 +                return false;
244.4796 +
244.4797 +            // If there isn't enough input left no match
244.4798 +            if (i + groupSize > matcher.to) {
244.4799 +                matcher.hitEnd = true;
244.4800 +                return false;
244.4801 +            }
244.4802 +
244.4803 +            // Check each new char to make sure it matches what the group
244.4804 +            // referenced matched last time around
244.4805 +            for (int index=0; index<groupSize; index++)
244.4806 +                if (seq.charAt(i+index) != seq.charAt(j+index))
244.4807 +                    return false;
244.4808 +
244.4809 +            return next.match(matcher, i+groupSize, seq);
244.4810 +        }
244.4811 +        boolean study(TreeInfo info) {
244.4812 +            info.maxValid = false;
244.4813 +            return next.study(info);
244.4814 +        }
244.4815 +    }
244.4816 +
244.4817 +    static class CIBackRef extends Node {
244.4818 +        int groupIndex;
244.4819 +        boolean doUnicodeCase;
244.4820 +        CIBackRef(int groupCount, boolean doUnicodeCase) {
244.4821 +            super();
244.4822 +            groupIndex = groupCount + groupCount;
244.4823 +            this.doUnicodeCase = doUnicodeCase;
244.4824 +        }
244.4825 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4826 +            int j = matcher.groups[groupIndex];
244.4827 +            int k = matcher.groups[groupIndex+1];
244.4828 +
244.4829 +            int groupSize = k - j;
244.4830 +
244.4831 +            // If the referenced group didn't match, neither can this
244.4832 +            if (j < 0)
244.4833 +                return false;
244.4834 +
244.4835 +            // If there isn't enough input left no match
244.4836 +            if (i + groupSize > matcher.to) {
244.4837 +                matcher.hitEnd = true;
244.4838 +                return false;
244.4839 +            }
244.4840 +
244.4841 +            // Check each new char to make sure it matches what the group
244.4842 +            // referenced matched last time around
244.4843 +            int x = i;
244.4844 +            for (int index=0; index<groupSize; index++) {
244.4845 +                int c1 = Character.codePointAt(seq, x);
244.4846 +                int c2 = Character.codePointAt(seq, j);
244.4847 +                if (c1 != c2) {
244.4848 +                    if (doUnicodeCase) {
244.4849 +                        int cc1 = Character.toUpperCase(c1);
244.4850 +                        int cc2 = Character.toUpperCase(c2);
244.4851 +                        if (cc1 != cc2 &&
244.4852 +                            Character.toLowerCase(cc1) !=
244.4853 +                            Character.toLowerCase(cc2))
244.4854 +                            return false;
244.4855 +                    } else {
244.4856 +                        if (ASCII.toLower(c1) != ASCII.toLower(c2))
244.4857 +                            return false;
244.4858 +                    }
244.4859 +                }
244.4860 +                x += Character.charCount(c1);
244.4861 +                j += Character.charCount(c2);
244.4862 +            }
244.4863 +
244.4864 +            return next.match(matcher, i+groupSize, seq);
244.4865 +        }
244.4866 +        boolean study(TreeInfo info) {
244.4867 +            info.maxValid = false;
244.4868 +            return next.study(info);
244.4869 +        }
244.4870 +    }
244.4871 +
244.4872 +    /**
244.4873 +     * Searches until the next instance of its atom. This is useful for
244.4874 +     * finding the atom efficiently without passing an instance of it
244.4875 +     * (greedy problem) and without a lot of wasted search time (reluctant
244.4876 +     * problem).
244.4877 +     */
244.4878 +    static final class First extends Node {
244.4879 +        Node atom;
244.4880 +        First(Node node) {
244.4881 +            this.atom = BnM.optimize(node);
244.4882 +        }
244.4883 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4884 +            if (atom instanceof BnM) {
244.4885 +                return atom.match(matcher, i, seq)
244.4886 +                    && next.match(matcher, matcher.last, seq);
244.4887 +            }
244.4888 +            for (;;) {
244.4889 +                if (i > matcher.to) {
244.4890 +                    matcher.hitEnd = true;
244.4891 +                    return false;
244.4892 +                }
244.4893 +                if (atom.match(matcher, i, seq)) {
244.4894 +                    return next.match(matcher, matcher.last, seq);
244.4895 +                }
244.4896 +                i += countChars(seq, i, 1);
244.4897 +                matcher.first++;
244.4898 +            }
244.4899 +        }
244.4900 +        boolean study(TreeInfo info) {
244.4901 +            atom.study(info);
244.4902 +            info.maxValid = false;
244.4903 +            info.deterministic = false;
244.4904 +            return next.study(info);
244.4905 +        }
244.4906 +    }
244.4907 +
244.4908 +    static final class Conditional extends Node {
244.4909 +        Node cond, yes, not;
244.4910 +        Conditional(Node cond, Node yes, Node not) {
244.4911 +            this.cond = cond;
244.4912 +            this.yes = yes;
244.4913 +            this.not = not;
244.4914 +        }
244.4915 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4916 +            if (cond.match(matcher, i, seq)) {
244.4917 +                return yes.match(matcher, i, seq);
244.4918 +            } else {
244.4919 +                return not.match(matcher, i, seq);
244.4920 +            }
244.4921 +        }
244.4922 +        boolean study(TreeInfo info) {
244.4923 +            int minL = info.minLength;
244.4924 +            int maxL = info.maxLength;
244.4925 +            boolean maxV = info.maxValid;
244.4926 +            info.reset();
244.4927 +            yes.study(info);
244.4928 +
244.4929 +            int minL2 = info.minLength;
244.4930 +            int maxL2 = info.maxLength;
244.4931 +            boolean maxV2 = info.maxValid;
244.4932 +            info.reset();
244.4933 +            not.study(info);
244.4934 +
244.4935 +            info.minLength = minL + Math.min(minL2, info.minLength);
244.4936 +            info.maxLength = maxL + Math.max(maxL2, info.maxLength);
244.4937 +            info.maxValid = (maxV & maxV2 & info.maxValid);
244.4938 +            info.deterministic = false;
244.4939 +            return next.study(info);
244.4940 +        }
244.4941 +    }
244.4942 +
244.4943 +    /**
244.4944 +     * Zero width positive lookahead.
244.4945 +     */
244.4946 +    static final class Pos extends Node {
244.4947 +        Node cond;
244.4948 +        Pos(Node cond) {
244.4949 +            this.cond = cond;
244.4950 +        }
244.4951 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4952 +            int savedTo = matcher.to;
244.4953 +            boolean conditionMatched = false;
244.4954 +
244.4955 +            // Relax transparent region boundaries for lookahead
244.4956 +            if (matcher.transparentBounds)
244.4957 +                matcher.to = matcher.getTextLength();
244.4958 +            try {
244.4959 +                conditionMatched = cond.match(matcher, i, seq);
244.4960 +            } finally {
244.4961 +                // Reinstate region boundaries
244.4962 +                matcher.to = savedTo;
244.4963 +            }
244.4964 +            return conditionMatched && next.match(matcher, i, seq);
244.4965 +        }
244.4966 +    }
244.4967 +
244.4968 +    /**
244.4969 +     * Zero width negative lookahead.
244.4970 +     */
244.4971 +    static final class Neg extends Node {
244.4972 +        Node cond;
244.4973 +        Neg(Node cond) {
244.4974 +            this.cond = cond;
244.4975 +        }
244.4976 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.4977 +            int savedTo = matcher.to;
244.4978 +            boolean conditionMatched = false;
244.4979 +
244.4980 +            // Relax transparent region boundaries for lookahead
244.4981 +            if (matcher.transparentBounds)
244.4982 +                matcher.to = matcher.getTextLength();
244.4983 +            try {
244.4984 +                if (i < matcher.to) {
244.4985 +                    conditionMatched = !cond.match(matcher, i, seq);
244.4986 +                } else {
244.4987 +                    // If a negative lookahead succeeds then more input
244.4988 +                    // could cause it to fail!
244.4989 +                    matcher.requireEnd = true;
244.4990 +                    conditionMatched = !cond.match(matcher, i, seq);
244.4991 +                }
244.4992 +            } finally {
244.4993 +                // Reinstate region boundaries
244.4994 +                matcher.to = savedTo;
244.4995 +            }
244.4996 +            return conditionMatched && next.match(matcher, i, seq);
244.4997 +        }
244.4998 +    }
244.4999 +
244.5000 +    /**
244.5001 +     * For use with lookbehinds; matches the position where the lookbehind
244.5002 +     * was encountered.
244.5003 +     */
244.5004 +    static Node lookbehindEnd = new Node() {
244.5005 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5006 +            return i == matcher.lookbehindTo;
244.5007 +        }
244.5008 +    };
244.5009 +
244.5010 +    /**
244.5011 +     * Zero width positive lookbehind.
244.5012 +     */
244.5013 +    static class Behind extends Node {
244.5014 +        Node cond;
244.5015 +        int rmax, rmin;
244.5016 +        Behind(Node cond, int rmax, int rmin) {
244.5017 +            this.cond = cond;
244.5018 +            this.rmax = rmax;
244.5019 +            this.rmin = rmin;
244.5020 +        }
244.5021 +
244.5022 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5023 +            int savedFrom = matcher.from;
244.5024 +            boolean conditionMatched = false;
244.5025 +            int startIndex = (!matcher.transparentBounds) ?
244.5026 +                             matcher.from : 0;
244.5027 +            int from = Math.max(i - rmax, startIndex);
244.5028 +            // Set end boundary
244.5029 +            int savedLBT = matcher.lookbehindTo;
244.5030 +            matcher.lookbehindTo = i;
244.5031 +            // Relax transparent region boundaries for lookbehind
244.5032 +            if (matcher.transparentBounds)
244.5033 +                matcher.from = 0;
244.5034 +            for (int j = i - rmin; !conditionMatched && j >= from; j--) {
244.5035 +                conditionMatched = cond.match(matcher, j, seq);
244.5036 +            }
244.5037 +            matcher.from = savedFrom;
244.5038 +            matcher.lookbehindTo = savedLBT;
244.5039 +            return conditionMatched && next.match(matcher, i, seq);
244.5040 +        }
244.5041 +    }
244.5042 +
244.5043 +    /**
244.5044 +     * Zero width positive lookbehind, including supplementary
244.5045 +     * characters or unpaired surrogates.
244.5046 +     */
244.5047 +    static final class BehindS extends Behind {
244.5048 +        BehindS(Node cond, int rmax, int rmin) {
244.5049 +            super(cond, rmax, rmin);
244.5050 +        }
244.5051 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5052 +            int rmaxChars = countChars(seq, i, -rmax);
244.5053 +            int rminChars = countChars(seq, i, -rmin);
244.5054 +            int savedFrom = matcher.from;
244.5055 +            int startIndex = (!matcher.transparentBounds) ?
244.5056 +                             matcher.from : 0;
244.5057 +            boolean conditionMatched = false;
244.5058 +            int from = Math.max(i - rmaxChars, startIndex);
244.5059 +            // Set end boundary
244.5060 +            int savedLBT = matcher.lookbehindTo;
244.5061 +            matcher.lookbehindTo = i;
244.5062 +            // Relax transparent region boundaries for lookbehind
244.5063 +            if (matcher.transparentBounds)
244.5064 +                matcher.from = 0;
244.5065 +
244.5066 +            for (int j = i - rminChars;
244.5067 +                 !conditionMatched && j >= from;
244.5068 +                 j -= j>from ? countChars(seq, j, -1) : 1) {
244.5069 +                conditionMatched = cond.match(matcher, j, seq);
244.5070 +            }
244.5071 +            matcher.from = savedFrom;
244.5072 +            matcher.lookbehindTo = savedLBT;
244.5073 +            return conditionMatched && next.match(matcher, i, seq);
244.5074 +        }
244.5075 +    }
244.5076 +
244.5077 +    /**
244.5078 +     * Zero width negative lookbehind.
244.5079 +     */
244.5080 +    static class NotBehind extends Node {
244.5081 +        Node cond;
244.5082 +        int rmax, rmin;
244.5083 +        NotBehind(Node cond, int rmax, int rmin) {
244.5084 +            this.cond = cond;
244.5085 +            this.rmax = rmax;
244.5086 +            this.rmin = rmin;
244.5087 +        }
244.5088 +
244.5089 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5090 +            int savedLBT = matcher.lookbehindTo;
244.5091 +            int savedFrom = matcher.from;
244.5092 +            boolean conditionMatched = false;
244.5093 +            int startIndex = (!matcher.transparentBounds) ?
244.5094 +                             matcher.from : 0;
244.5095 +            int from = Math.max(i - rmax, startIndex);
244.5096 +            matcher.lookbehindTo = i;
244.5097 +            // Relax transparent region boundaries for lookbehind
244.5098 +            if (matcher.transparentBounds)
244.5099 +                matcher.from = 0;
244.5100 +            for (int j = i - rmin; !conditionMatched && j >= from; j--) {
244.5101 +                conditionMatched = cond.match(matcher, j, seq);
244.5102 +            }
244.5103 +            // Reinstate region boundaries
244.5104 +            matcher.from = savedFrom;
244.5105 +            matcher.lookbehindTo = savedLBT;
244.5106 +            return !conditionMatched && next.match(matcher, i, seq);
244.5107 +        }
244.5108 +    }
244.5109 +
244.5110 +    /**
244.5111 +     * Zero width negative lookbehind, including supplementary
244.5112 +     * characters or unpaired surrogates.
244.5113 +     */
244.5114 +    static final class NotBehindS extends NotBehind {
244.5115 +        NotBehindS(Node cond, int rmax, int rmin) {
244.5116 +            super(cond, rmax, rmin);
244.5117 +        }
244.5118 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5119 +            int rmaxChars = countChars(seq, i, -rmax);
244.5120 +            int rminChars = countChars(seq, i, -rmin);
244.5121 +            int savedFrom = matcher.from;
244.5122 +            int savedLBT = matcher.lookbehindTo;
244.5123 +            boolean conditionMatched = false;
244.5124 +            int startIndex = (!matcher.transparentBounds) ?
244.5125 +                             matcher.from : 0;
244.5126 +            int from = Math.max(i - rmaxChars, startIndex);
244.5127 +            matcher.lookbehindTo = i;
244.5128 +            // Relax transparent region boundaries for lookbehind
244.5129 +            if (matcher.transparentBounds)
244.5130 +                matcher.from = 0;
244.5131 +            for (int j = i - rminChars;
244.5132 +                 !conditionMatched && j >= from;
244.5133 +                 j -= j>from ? countChars(seq, j, -1) : 1) {
244.5134 +                conditionMatched = cond.match(matcher, j, seq);
244.5135 +            }
244.5136 +            //Reinstate region boundaries
244.5137 +            matcher.from = savedFrom;
244.5138 +            matcher.lookbehindTo = savedLBT;
244.5139 +            return !conditionMatched && next.match(matcher, i, seq);
244.5140 +        }
244.5141 +    }
244.5142 +
244.5143 +    /**
244.5144 +     * Returns the set union of two CharProperty nodes.
244.5145 +     */
244.5146 +    private static CharProperty union(final CharProperty lhs,
244.5147 +                                      final CharProperty rhs) {
244.5148 +        return new CharProperty() {
244.5149 +                boolean isSatisfiedBy(int ch) {
244.5150 +                    return lhs.isSatisfiedBy(ch) || rhs.isSatisfiedBy(ch);}};
244.5151 +    }
244.5152 +
244.5153 +    /**
244.5154 +     * Returns the set intersection of two CharProperty nodes.
244.5155 +     */
244.5156 +    private static CharProperty intersection(final CharProperty lhs,
244.5157 +                                             final CharProperty rhs) {
244.5158 +        return new CharProperty() {
244.5159 +                boolean isSatisfiedBy(int ch) {
244.5160 +                    return lhs.isSatisfiedBy(ch) && rhs.isSatisfiedBy(ch);}};
244.5161 +    }
244.5162 +
244.5163 +    /**
244.5164 +     * Returns the set difference of two CharProperty nodes.
244.5165 +     */
244.5166 +    private static CharProperty setDifference(final CharProperty lhs,
244.5167 +                                              final CharProperty rhs) {
244.5168 +        return new CharProperty() {
244.5169 +                boolean isSatisfiedBy(int ch) {
244.5170 +                    return ! rhs.isSatisfiedBy(ch) && lhs.isSatisfiedBy(ch);}};
244.5171 +    }
244.5172 +
244.5173 +    /**
244.5174 +     * Handles word boundaries. Includes a field to allow this one class to
244.5175 +     * deal with the different types of word boundaries we can match. The word
244.5176 +     * characters include underscores, letters, and digits. Non spacing marks
244.5177 +     * can are also part of a word if they have a base character, otherwise
244.5178 +     * they are ignored for purposes of finding word boundaries.
244.5179 +     */
244.5180 +    static final class Bound extends Node {
244.5181 +        static int LEFT = 0x1;
244.5182 +        static int RIGHT= 0x2;
244.5183 +        static int BOTH = 0x3;
244.5184 +        static int NONE = 0x4;
244.5185 +        int type;
244.5186 +        boolean useUWORD;
244.5187 +        Bound(int n, boolean useUWORD) {
244.5188 +            type = n;
244.5189 +            this.useUWORD = useUWORD;
244.5190 +        }
244.5191 +
244.5192 +        boolean isWord(int ch) {
244.5193 +            return useUWORD ? UnicodeProp.WORD.is(ch)
244.5194 +                            : (ch == '_' || Character.isLetterOrDigit(ch));
244.5195 +        }
244.5196 +
244.5197 +        int check(Matcher matcher, int i, CharSequence seq) {
244.5198 +            int ch;
244.5199 +            boolean left = false;
244.5200 +            int startIndex = matcher.from;
244.5201 +            int endIndex = matcher.to;
244.5202 +            if (matcher.transparentBounds) {
244.5203 +                startIndex = 0;
244.5204 +                endIndex = matcher.getTextLength();
244.5205 +            }
244.5206 +            if (i > startIndex) {
244.5207 +                ch = Character.codePointBefore(seq, i);
244.5208 +                left = (isWord(ch) ||
244.5209 +                    ((Character.getType(ch) == Character.NON_SPACING_MARK)
244.5210 +                     && hasBaseCharacter(matcher, i-1, seq)));
244.5211 +            }
244.5212 +            boolean right = false;
244.5213 +            if (i < endIndex) {
244.5214 +                ch = Character.codePointAt(seq, i);
244.5215 +                right = (isWord(ch) ||
244.5216 +                    ((Character.getType(ch) == Character.NON_SPACING_MARK)
244.5217 +                     && hasBaseCharacter(matcher, i, seq)));
244.5218 +            } else {
244.5219 +                // Tried to access char past the end
244.5220 +                matcher.hitEnd = true;
244.5221 +                // The addition of another char could wreck a boundary
244.5222 +                matcher.requireEnd = true;
244.5223 +            }
244.5224 +            return ((left ^ right) ? (right ? LEFT : RIGHT) : NONE);
244.5225 +        }
244.5226 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5227 +            return (check(matcher, i, seq) & type) > 0
244.5228 +                && next.match(matcher, i, seq);
244.5229 +        }
244.5230 +    }
244.5231 +
244.5232 +    /**
244.5233 +     * Non spacing marks only count as word characters in bounds calculations
244.5234 +     * if they have a base character.
244.5235 +     */
244.5236 +    private static boolean hasBaseCharacter(Matcher matcher, int i,
244.5237 +                                            CharSequence seq)
244.5238 +    {
244.5239 +        int start = (!matcher.transparentBounds) ?
244.5240 +            matcher.from : 0;
244.5241 +        for (int x=i; x >= start; x--) {
244.5242 +            int ch = Character.codePointAt(seq, x);
244.5243 +            if (Character.isLetterOrDigit(ch))
244.5244 +                return true;
244.5245 +            if (Character.getType(ch) == Character.NON_SPACING_MARK)
244.5246 +                continue;
244.5247 +            return false;
244.5248 +        }
244.5249 +        return false;
244.5250 +    }
244.5251 +
244.5252 +    /**
244.5253 +     * Attempts to match a slice in the input using the Boyer-Moore string
244.5254 +     * matching algorithm. The algorithm is based on the idea that the
244.5255 +     * pattern can be shifted farther ahead in the search text if it is
244.5256 +     * matched right to left.
244.5257 +     * <p>
244.5258 +     * The pattern is compared to the input one character at a time, from
244.5259 +     * the rightmost character in the pattern to the left. If the characters
244.5260 +     * all match the pattern has been found. If a character does not match,
244.5261 +     * the pattern is shifted right a distance that is the maximum of two
244.5262 +     * functions, the bad character shift and the good suffix shift. This
244.5263 +     * shift moves the attempted match position through the input more
244.5264 +     * quickly than a naive one position at a time check.
244.5265 +     * <p>
244.5266 +     * The bad character shift is based on the character from the text that
244.5267 +     * did not match. If the character does not appear in the pattern, the
244.5268 +     * pattern can be shifted completely beyond the bad character. If the
244.5269 +     * character does occur in the pattern, the pattern can be shifted to
244.5270 +     * line the pattern up with the next occurrence of that character.
244.5271 +     * <p>
244.5272 +     * The good suffix shift is based on the idea that some subset on the right
244.5273 +     * side of the pattern has matched. When a bad character is found, the
244.5274 +     * pattern can be shifted right by the pattern length if the subset does
244.5275 +     * not occur again in pattern, or by the amount of distance to the
244.5276 +     * next occurrence of the subset in the pattern.
244.5277 +     *
244.5278 +     * Boyer-Moore search methods adapted from code by Amy Yu.
244.5279 +     */
244.5280 +    static class BnM extends Node {
244.5281 +        int[] buffer;
244.5282 +        int[] lastOcc;
244.5283 +        int[] optoSft;
244.5284 +
244.5285 +        /**
244.5286 +         * Pre calculates arrays needed to generate the bad character
244.5287 +         * shift and the good suffix shift. Only the last seven bits
244.5288 +         * are used to see if chars match; This keeps the tables small
244.5289 +         * and covers the heavily used ASCII range, but occasionally
244.5290 +         * results in an aliased match for the bad character shift.
244.5291 +         */
244.5292 +        static Node optimize(Node node) {
244.5293 +            if (!(node instanceof Slice)) {
244.5294 +                return node;
244.5295 +            }
244.5296 +
244.5297 +            int[] src = ((Slice) node).buffer;
244.5298 +            int patternLength = src.length;
244.5299 +            // The BM algorithm requires a bit of overhead;
244.5300 +            // If the pattern is short don't use it, since
244.5301 +            // a shift larger than the pattern length cannot
244.5302 +            // be used anyway.
244.5303 +            if (patternLength < 4) {
244.5304 +                return node;
244.5305 +            }
244.5306 +            int i, j, k;
244.5307 +            int[] lastOcc = new int[128];
244.5308 +            int[] optoSft = new int[patternLength];
244.5309 +            // Precalculate part of the bad character shift
244.5310 +            // It is a table for where in the pattern each
244.5311 +            // lower 7-bit value occurs
244.5312 +            for (i = 0; i < patternLength; i++) {
244.5313 +                lastOcc[src[i]&0x7F] = i + 1;
244.5314 +            }
244.5315 +            // Precalculate the good suffix shift
244.5316 +            // i is the shift amount being considered
244.5317 +NEXT:       for (i = patternLength; i > 0; i--) {
244.5318 +                // j is the beginning index of suffix being considered
244.5319 +                for (j = patternLength - 1; j >= i; j--) {
244.5320 +                    // Testing for good suffix
244.5321 +                    if (src[j] == src[j-i]) {
244.5322 +                        // src[j..len] is a good suffix
244.5323 +                        optoSft[j-1] = i;
244.5324 +                    } else {
244.5325 +                        // No match. The array has already been
244.5326 +                        // filled up with correct values before.
244.5327 +                        continue NEXT;
244.5328 +                    }
244.5329 +                }
244.5330 +                // This fills up the remaining of optoSft
244.5331 +                // any suffix can not have larger shift amount
244.5332 +                // then its sub-suffix. Why???
244.5333 +                while (j > 0) {
244.5334 +                    optoSft[--j] = i;
244.5335 +                }
244.5336 +            }
244.5337 +            // Set the guard value because of unicode compression
244.5338 +            optoSft[patternLength-1] = 1;
244.5339 +            if (node instanceof SliceS)
244.5340 +                return new BnMS(src, lastOcc, optoSft, node.next);
244.5341 +            return new BnM(src, lastOcc, optoSft, node.next);
244.5342 +        }
244.5343 +        BnM(int[] src, int[] lastOcc, int[] optoSft, Node next) {
244.5344 +            this.buffer = src;
244.5345 +            this.lastOcc = lastOcc;
244.5346 +            this.optoSft = optoSft;
244.5347 +            this.next = next;
244.5348 +        }
244.5349 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5350 +            int[] src = buffer;
244.5351 +            int patternLength = src.length;
244.5352 +            int last = matcher.to - patternLength;
244.5353 +
244.5354 +            // Loop over all possible match positions in text
244.5355 +NEXT:       while (i <= last) {
244.5356 +                // Loop over pattern from right to left
244.5357 +                for (int j = patternLength - 1; j >= 0; j--) {
244.5358 +                    int ch = seq.charAt(i+j);
244.5359 +                    if (ch != src[j]) {
244.5360 +                        // Shift search to the right by the maximum of the
244.5361 +                        // bad character shift and the good suffix shift
244.5362 +                        i += Math.max(j + 1 - lastOcc[ch&0x7F], optoSft[j]);
244.5363 +                        continue NEXT;
244.5364 +                    }
244.5365 +                }
244.5366 +                // Entire pattern matched starting at i
244.5367 +                matcher.first = i;
244.5368 +                boolean ret = next.match(matcher, i + patternLength, seq);
244.5369 +                if (ret) {
244.5370 +                    matcher.first = i;
244.5371 +                    matcher.groups[0] = matcher.first;
244.5372 +                    matcher.groups[1] = matcher.last;
244.5373 +                    return true;
244.5374 +                }
244.5375 +                i++;
244.5376 +            }
244.5377 +            // BnM is only used as the leading node in the unanchored case,
244.5378 +            // and it replaced its Start() which always searches to the end
244.5379 +            // if it doesn't find what it's looking for, so hitEnd is true.
244.5380 +            matcher.hitEnd = true;
244.5381 +            return false;
244.5382 +        }
244.5383 +        boolean study(TreeInfo info) {
244.5384 +            info.minLength += buffer.length;
244.5385 +            info.maxValid = false;
244.5386 +            return next.study(info);
244.5387 +        }
244.5388 +    }
244.5389 +
244.5390 +    /**
244.5391 +     * Supplementary support version of BnM(). Unpaired surrogates are
244.5392 +     * also handled by this class.
244.5393 +     */
244.5394 +    static final class BnMS extends BnM {
244.5395 +        int lengthInChars;
244.5396 +
244.5397 +        BnMS(int[] src, int[] lastOcc, int[] optoSft, Node next) {
244.5398 +            super(src, lastOcc, optoSft, next);
244.5399 +            for (int x = 0; x < buffer.length; x++) {
244.5400 +                lengthInChars += Character.charCount(buffer[x]);
244.5401 +            }
244.5402 +        }
244.5403 +        boolean match(Matcher matcher, int i, CharSequence seq) {
244.5404 +            int[] src = buffer;
244.5405 +            int patternLength = src.length;
244.5406 +            int last = matcher.to - lengthInChars;
244.5407 +
244.5408 +            // Loop over all possible match positions in text
244.5409 +NEXT:       while (i <= last) {
244.5410 +                // Loop over pattern from right to left
244.5411 +                int ch;
244.5412 +                for (int j = countChars(seq, i, patternLength), x = patternLength - 1;
244.5413 +                     j > 0; j -= Character.charCount(ch), x--) {
244.5414 +                    ch = Character.codePointBefore(seq, i+j);
244.5415 +                    if (ch != src[x]) {
244.5416 +                        // Shift search to the right by the maximum of the
244.5417 +                        // bad character shift and the good suffix shift
244.5418 +                        int n = Math.max(x + 1 - lastOcc[ch&0x7F], optoSft[x]);
244.5419 +                        i += countChars(seq, i, n);
244.5420 +                        continue NEXT;
244.5421 +                    }
244.5422 +                }
244.5423 +                // Entire pattern matched starting at i
244.5424 +                matcher.first = i;
244.5425 +                boolean ret = next.match(matcher, i + lengthInChars, seq);
244.5426 +                if (ret) {
244.5427 +                    matcher.first = i;
244.5428 +                    matcher.groups[0] = matcher.first;
244.5429 +                    matcher.groups[1] = matcher.last;
244.5430 +                    return true;
244.5431 +                }
244.5432 +                i += countChars(seq, i, 1);
244.5433 +            }
244.5434 +            matcher.hitEnd = true;
244.5435 +            return false;
244.5436 +        }
244.5437 +    }
244.5438 +
244.5439 +///////////////////////////////////////////////////////////////////////////////
244.5440 +///////////////////////////////////////////////////////////////////////////////
244.5441 +
244.5442 +    /**
244.5443 +     *  This must be the very first initializer.
244.5444 +     */
244.5445 +    static Node accept = new Node();
244.5446 +
244.5447 +    static Node lastAccept = new LastNode();
244.5448 +
244.5449 +    private static class CharPropertyNames {
244.5450 +
244.5451 +        static CharProperty charPropertyFor(String name) {
244.5452 +            CharPropertyFactory m = map.get(name);
244.5453 +            return m == null ? null : m.make();
244.5454 +        }
244.5455 +
244.5456 +        private static abstract class CharPropertyFactory {
244.5457 +            abstract CharProperty make();
244.5458 +        }
244.5459 +
244.5460 +        private static void defCategory(String name,
244.5461 +                                        final int typeMask) {
244.5462 +            map.put(name, new CharPropertyFactory() {
244.5463 +                    CharProperty make() { return new Category(typeMask);}});
244.5464 +        }
244.5465 +
244.5466 +        private static void defRange(String name,
244.5467 +                                     final int lower, final int upper) {
244.5468 +            map.put(name, new CharPropertyFactory() {
244.5469 +                    CharProperty make() { return rangeFor(lower, upper);}});
244.5470 +        }
244.5471 +
244.5472 +        private static void defCtype(String name,
244.5473 +                                     final int ctype) {
244.5474 +            map.put(name, new CharPropertyFactory() {
244.5475 +                    CharProperty make() { return new Ctype(ctype);}});
244.5476 +        }
244.5477 +
244.5478 +        private static abstract class CloneableProperty
244.5479 +            extends CharProperty implements Cloneable
244.5480 +        {
244.5481 +            public CloneableProperty clone() {
244.5482 +                try {
244.5483 +                    return (CloneableProperty) super.clone();
244.5484 +                } catch (CloneNotSupportedException e) {
244.5485 +                    throw new AssertionError(e);
244.5486 +                }
244.5487 +            }
244.5488 +        }
244.5489 +
244.5490 +        private static void defClone(String name,
244.5491 +                                     final CloneableProperty p) {
244.5492 +            map.put(name, new CharPropertyFactory() {
244.5493 +                    CharProperty make() { return p.clone();}});
244.5494 +        }
244.5495 +
244.5496 +        private static final HashMap<String, CharPropertyFactory> map
244.5497 +            = new HashMap<>();
244.5498 +
244.5499 +        static {
244.5500 +            // Unicode character property aliases, defined in
244.5501 +            // http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt
244.5502 +            defCategory("Cn", 1<<Character.UNASSIGNED);
244.5503 +            defCategory("Lu", 1<<Character.UPPERCASE_LETTER);
244.5504 +            defCategory("Ll", 1<<Character.LOWERCASE_LETTER);
244.5505 +            defCategory("Lt", 1<<Character.TITLECASE_LETTER);
244.5506 +            defCategory("Lm", 1<<Character.MODIFIER_LETTER);
244.5507 +            defCategory("Lo", 1<<Character.OTHER_LETTER);
244.5508 +            defCategory("Mn", 1<<Character.NON_SPACING_MARK);
244.5509 +            defCategory("Me", 1<<Character.ENCLOSING_MARK);
244.5510 +            defCategory("Mc", 1<<Character.COMBINING_SPACING_MARK);
244.5511 +            defCategory("Nd", 1<<Character.DECIMAL_DIGIT_NUMBER);
244.5512 +            defCategory("Nl", 1<<Character.LETTER_NUMBER);
244.5513 +            defCategory("No", 1<<Character.OTHER_NUMBER);
244.5514 +            defCategory("Zs", 1<<Character.SPACE_SEPARATOR);
244.5515 +            defCategory("Zl", 1<<Character.LINE_SEPARATOR);
244.5516 +            defCategory("Zp", 1<<Character.PARAGRAPH_SEPARATOR);
244.5517 +            defCategory("Cc", 1<<Character.CONTROL);
244.5518 +            defCategory("Cf", 1<<Character.FORMAT);
244.5519 +            defCategory("Co", 1<<Character.PRIVATE_USE);
244.5520 +            defCategory("Cs", 1<<Character.SURROGATE);
244.5521 +            defCategory("Pd", 1<<Character.DASH_PUNCTUATION);
244.5522 +            defCategory("Ps", 1<<Character.START_PUNCTUATION);
244.5523 +            defCategory("Pe", 1<<Character.END_PUNCTUATION);
244.5524 +            defCategory("Pc", 1<<Character.CONNECTOR_PUNCTUATION);
244.5525 +            defCategory("Po", 1<<Character.OTHER_PUNCTUATION);
244.5526 +            defCategory("Sm", 1<<Character.MATH_SYMBOL);
244.5527 +            defCategory("Sc", 1<<Character.CURRENCY_SYMBOL);
244.5528 +            defCategory("Sk", 1<<Character.MODIFIER_SYMBOL);
244.5529 +            defCategory("So", 1<<Character.OTHER_SYMBOL);
244.5530 +            defCategory("Pi", 1<<Character.INITIAL_QUOTE_PUNCTUATION);
244.5531 +            defCategory("Pf", 1<<Character.FINAL_QUOTE_PUNCTUATION);
244.5532 +            defCategory("L", ((1<<Character.UPPERCASE_LETTER) |
244.5533 +                              (1<<Character.LOWERCASE_LETTER) |
244.5534 +                              (1<<Character.TITLECASE_LETTER) |
244.5535 +                              (1<<Character.MODIFIER_LETTER)  |
244.5536 +                              (1<<Character.OTHER_LETTER)));
244.5537 +            defCategory("M", ((1<<Character.NON_SPACING_MARK) |
244.5538 +                              (1<<Character.ENCLOSING_MARK)   |
244.5539 +                              (1<<Character.COMBINING_SPACING_MARK)));
244.5540 +            defCategory("N", ((1<<Character.DECIMAL_DIGIT_NUMBER) |
244.5541 +                              (1<<Character.LETTER_NUMBER)        |
244.5542 +                              (1<<Character.OTHER_NUMBER)));
244.5543 +            defCategory("Z", ((1<<Character.SPACE_SEPARATOR) |
244.5544 +                              (1<<Character.LINE_SEPARATOR)  |
244.5545 +                              (1<<Character.PARAGRAPH_SEPARATOR)));
244.5546 +            defCategory("C", ((1<<Character.CONTROL)     |
244.5547 +                              (1<<Character.FORMAT)      |
244.5548 +                              (1<<Character.PRIVATE_USE) |
244.5549 +                              (1<<Character.SURROGATE))); // Other
244.5550 +            defCategory("P", ((1<<Character.DASH_PUNCTUATION)      |
244.5551 +                              (1<<Character.START_PUNCTUATION)     |
244.5552 +                              (1<<Character.END_PUNCTUATION)       |
244.5553 +                              (1<<Character.CONNECTOR_PUNCTUATION) |
244.5554 +                              (1<<Character.OTHER_PUNCTUATION)     |
244.5555 +                              (1<<Character.INITIAL_QUOTE_PUNCTUATION) |
244.5556 +                              (1<<Character.FINAL_QUOTE_PUNCTUATION)));
244.5557 +            defCategory("S", ((1<<Character.MATH_SYMBOL)     |
244.5558 +                              (1<<Character.CURRENCY_SYMBOL) |
244.5559 +                              (1<<Character.MODIFIER_SYMBOL) |
244.5560 +                              (1<<Character.OTHER_SYMBOL)));
244.5561 +            defCategory("LC", ((1<<Character.UPPERCASE_LETTER) |
244.5562 +                               (1<<Character.LOWERCASE_LETTER) |
244.5563 +                               (1<<Character.TITLECASE_LETTER)));
244.5564 +            defCategory("LD", ((1<<Character.UPPERCASE_LETTER) |
244.5565 +                               (1<<Character.LOWERCASE_LETTER) |
244.5566 +                               (1<<Character.TITLECASE_LETTER) |
244.5567 +                               (1<<Character.MODIFIER_LETTER)  |
244.5568 +                               (1<<Character.OTHER_LETTER)     |
244.5569 +                               (1<<Character.DECIMAL_DIGIT_NUMBER)));
244.5570 +            defRange("L1", 0x00, 0xFF); // Latin-1
244.5571 +            map.put("all", new CharPropertyFactory() {
244.5572 +                    CharProperty make() { return new All(); }});
244.5573 +
244.5574 +            // Posix regular expression character classes, defined in
244.5575 +            // http://www.unix.org/onlinepubs/009695399/basedefs/xbd_chap09.html
244.5576 +            defRange("ASCII", 0x00, 0x7F);   // ASCII
244.5577 +            defCtype("Alnum", ASCII.ALNUM);  // Alphanumeric characters
244.5578 +            defCtype("Alpha", ASCII.ALPHA);  // Alphabetic characters
244.5579 +            defCtype("Blank", ASCII.BLANK);  // Space and tab characters
244.5580 +            defCtype("Cntrl", ASCII.CNTRL);  // Control characters
244.5581 +            defRange("Digit", '0', '9');     // Numeric characters
244.5582 +            defCtype("Graph", ASCII.GRAPH);  // printable and visible
244.5583 +            defRange("Lower", 'a', 'z');     // Lower-case alphabetic
244.5584 +            defRange("Print", 0x20, 0x7E);   // Printable characters
244.5585 +            defCtype("Punct", ASCII.PUNCT);  // Punctuation characters
244.5586 +            defCtype("Space", ASCII.SPACE);  // Space characters
244.5587 +            defRange("Upper", 'A', 'Z');     // Upper-case alphabetic
244.5588 +            defCtype("XDigit",ASCII.XDIGIT); // hexadecimal digits
244.5589 +
244.5590 +            // Java character properties, defined by methods in Character.java
244.5591 +            defClone("javaLowerCase", new CloneableProperty() {
244.5592 +                boolean isSatisfiedBy(int ch) {
244.5593 +                    return Character.isLowerCase(ch);}});
244.5594 +            defClone("javaUpperCase", new CloneableProperty() {
244.5595 +                boolean isSatisfiedBy(int ch) {
244.5596 +                    return Character.isUpperCase(ch);}});
244.5597 +            defClone("javaAlphabetic", new CloneableProperty() {
244.5598 +                boolean isSatisfiedBy(int ch) {
244.5599 +                    return Character.isAlphabetic(ch);}});
244.5600 +            defClone("javaIdeographic", new CloneableProperty() {
244.5601 +                boolean isSatisfiedBy(int ch) {
244.5602 +                    return Character.isIdeographic(ch);}});
244.5603 +            defClone("javaTitleCase", new CloneableProperty() {
244.5604 +                boolean isSatisfiedBy(int ch) {
244.5605 +                    return Character.isTitleCase(ch);}});
244.5606 +            defClone("javaDigit", new CloneableProperty() {
244.5607 +                boolean isSatisfiedBy(int ch) {
244.5608 +                    return Character.isDigit(ch);}});
244.5609 +            defClone("javaDefined", new CloneableProperty() {
244.5610 +                boolean isSatisfiedBy(int ch) {
244.5611 +                    return Character.isDefined(ch);}});
244.5612 +            defClone("javaLetter", new CloneableProperty() {
244.5613 +                boolean isSatisfiedBy(int ch) {
244.5614 +                    return Character.isLetter(ch);}});
244.5615 +            defClone("javaLetterOrDigit", new CloneableProperty() {
244.5616 +                boolean isSatisfiedBy(int ch) {
244.5617 +                    return Character.isLetterOrDigit(ch);}});
244.5618 +            defClone("javaJavaIdentifierStart", new CloneableProperty() {
244.5619 +                boolean isSatisfiedBy(int ch) {
244.5620 +                    return Character.isJavaIdentifierStart(ch);}});
244.5621 +            defClone("javaJavaIdentifierPart", new CloneableProperty() {
244.5622 +                boolean isSatisfiedBy(int ch) {
244.5623 +                    return Character.isJavaIdentifierPart(ch);}});
244.5624 +            defClone("javaUnicodeIdentifierStart", new CloneableProperty() {
244.5625 +                boolean isSatisfiedBy(int ch) {
244.5626 +                    return Character.isUnicodeIdentifierStart(ch);}});
244.5627 +            defClone("javaUnicodeIdentifierPart", new CloneableProperty() {
244.5628 +                boolean isSatisfiedBy(int ch) {
244.5629 +                    return Character.isUnicodeIdentifierPart(ch);}});
244.5630 +            defClone("javaIdentifierIgnorable", new CloneableProperty() {
244.5631 +                boolean isSatisfiedBy(int ch) {
244.5632 +                    return Character.isIdentifierIgnorable(ch);}});
244.5633 +            defClone("javaSpaceChar", new CloneableProperty() {
244.5634 +                boolean isSatisfiedBy(int ch) {
244.5635 +                    return Character.isSpaceChar(ch);}});
244.5636 +            defClone("javaWhitespace", new CloneableProperty() {
244.5637 +                boolean isSatisfiedBy(int ch) {
244.5638 +                    return Character.isWhitespace(ch);}});
244.5639 +            defClone("javaISOControl", new CloneableProperty() {
244.5640 +                boolean isSatisfiedBy(int ch) {
244.5641 +                    return Character.isISOControl(ch);}});
244.5642 +            defClone("javaMirrored", new CloneableProperty() {
244.5643 +                boolean isSatisfiedBy(int ch) {
244.5644 +                    return Character.isMirrored(ch);}});
244.5645 +        }
244.5646 +    }
244.5647 +    
244.5648 +    private static final class Normalizer {
244.5649 +        public static final int NFD = 1;
244.5650 +        public static final int NFC = 2;
244.5651 +
244.5652 +        static String normalize(String pattern, int NFD) {
244.5653 +            return pattern;
244.5654 +        }
244.5655 +
244.5656 +        private static int getCombiningClass(int c) {
244.5657 +            return 1;
244.5658 +        }
244.5659 +    }
244.5660 +}
   245.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   245.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/PatternSyntaxException.java	Wed Apr 30 15:04:10 2014 +0200
   245.3 @@ -0,0 +1,119 @@
   245.4 +/*
   245.5 + * Copyright (c) 1999, 2008, 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 java.util.regex;
  245.30 +
  245.31 +/**
  245.32 + * Unchecked exception thrown to indicate a syntax error in a
  245.33 + * regular-expression pattern.
  245.34 + *
  245.35 + * @author  unascribed
  245.36 + * @since 1.4
  245.37 + * @spec JSR-51
  245.38 + */
  245.39 +
  245.40 +public class PatternSyntaxException
  245.41 +    extends IllegalArgumentException
  245.42 +{
  245.43 +    private static final long serialVersionUID = -3864639126226059218L;
  245.44 +
  245.45 +    private final String desc;
  245.46 +    private final String pattern;
  245.47 +    private final int index;
  245.48 +
  245.49 +    /**
  245.50 +     * Constructs a new instance of this class.
  245.51 +     *
  245.52 +     * @param  desc
  245.53 +     *         A description of the error
  245.54 +     *
  245.55 +     * @param  regex
  245.56 +     *         The erroneous pattern
  245.57 +     *
  245.58 +     * @param  index
  245.59 +     *         The approximate index in the pattern of the error,
  245.60 +     *         or <tt>-1</tt> if the index is not known
  245.61 +     */
  245.62 +    public PatternSyntaxException(String desc, String regex, int index) {
  245.63 +        this.desc = desc;
  245.64 +        this.pattern = regex;
  245.65 +        this.index = index;
  245.66 +    }
  245.67 +
  245.68 +    /**
  245.69 +     * Retrieves the error index.
  245.70 +     *
  245.71 +     * @return  The approximate index in the pattern of the error,
  245.72 +     *         or <tt>-1</tt> if the index is not known
  245.73 +     */
  245.74 +    public int getIndex() {
  245.75 +        return index;
  245.76 +    }
  245.77 +
  245.78 +    /**
  245.79 +     * Retrieves the description of the error.
  245.80 +     *
  245.81 +     * @return  The description of the error
  245.82 +     */
  245.83 +    public String getDescription() {
  245.84 +        return desc;
  245.85 +    }
  245.86 +
  245.87 +    /**
  245.88 +     * Retrieves the erroneous regular-expression pattern.
  245.89 +     *
  245.90 +     * @return  The erroneous pattern
  245.91 +     */
  245.92 +    public String getPattern() {
  245.93 +        return pattern;
  245.94 +    }
  245.95 +
  245.96 +    private static final String nl = System.lineSeparator();
  245.97 +
  245.98 +    /**
  245.99 +     * Returns a multi-line string containing the description of the syntax
 245.100 +     * error and its index, the erroneous regular-expression pattern, and a
 245.101 +     * visual indication of the error index within the pattern.
 245.102 +     *
 245.103 +     * @return  The full detail message
 245.104 +     */
 245.105 +    public String getMessage() {
 245.106 +        StringBuffer sb = new StringBuffer();
 245.107 +        sb.append(desc);
 245.108 +        if (index >= 0) {
 245.109 +            sb.append(" near index ");
 245.110 +            sb.append(index);
 245.111 +        }
 245.112 +        sb.append(nl);
 245.113 +        sb.append(pattern);
 245.114 +        if (index >= 0) {
 245.115 +            sb.append(nl);
 245.116 +            for (int i = 0; i < index; i++) sb.append(' ');
 245.117 +            sb.append('^');
 245.118 +        }
 245.119 +        return sb.toString();
 245.120 +    }
 245.121 +
 245.122 +}
   246.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   246.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/UnicodeProp.java	Wed Apr 30 15:04:10 2014 +0200
   246.3 @@ -0,0 +1,236 @@
   246.4 +/*
   246.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   246.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   246.7 + *
   246.8 + * This code is free software; you can redistribute it and/or modify it
   246.9 + * under the terms of the GNU General Public License version 2 only, as
  246.10 + * published by the Free Software Foundation.  Oracle designates this
  246.11 + * particular file as subject to the "Classpath" exception as provided
  246.12 + * by Oracle in the LICENSE file that accompanied this code.
  246.13 + *
  246.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  246.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  246.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  246.17 + * version 2 for more details (a copy is included in the LICENSE file that
  246.18 + * accompanied this code).
  246.19 + *
  246.20 + * You should have received a copy of the GNU General Public License version
  246.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  246.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  246.23 + *
  246.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  246.25 + * or visit www.oracle.com if you need additional information or have any
  246.26 + * questions.
  246.27 + */
  246.28 +
  246.29 +package java.util.regex;
  246.30 +
  246.31 +import java.util.HashMap;
  246.32 +import java.util.Locale;
  246.33 +
  246.34 +enum UnicodeProp {
  246.35 +
  246.36 +    ALPHABETIC {
  246.37 +        public boolean is(int ch) {
  246.38 +            return Character.isAlphabetic(ch);
  246.39 +        }
  246.40 +    },
  246.41 +
  246.42 +    LETTER {
  246.43 +        public boolean is(int ch) {
  246.44 +            return Character.isLetter(ch);
  246.45 +        }
  246.46 +    },
  246.47 +
  246.48 +    IDEOGRAPHIC {
  246.49 +        public boolean is(int ch) {
  246.50 +            return Character.isIdeographic(ch);
  246.51 +        }
  246.52 +    },
  246.53 +
  246.54 +    LOWERCASE {
  246.55 +        public boolean is(int ch) {
  246.56 +            return Character.isLowerCase(ch);
  246.57 +        }
  246.58 +    },
  246.59 +
  246.60 +    UPPERCASE {
  246.61 +        public boolean is(int ch) {
  246.62 +            return Character.isUpperCase(ch);
  246.63 +        }
  246.64 +    },
  246.65 +
  246.66 +    TITLECASE {
  246.67 +        public boolean is(int ch) {
  246.68 +            return Character.isTitleCase(ch);
  246.69 +        }
  246.70 +    },
  246.71 +
  246.72 +    WHITE_SPACE {
  246.73 +        // \p{Whitespace}
  246.74 +        public boolean is(int ch) {
  246.75 +            return ((((1 << Character.SPACE_SEPARATOR) |
  246.76 +                      (1 << Character.LINE_SEPARATOR) |
  246.77 +                      (1 << Character.PARAGRAPH_SEPARATOR)) >> Character.getType(ch)) & 1)
  246.78 +                   != 0 || (ch >= 0x9 && ch <= 0xd) || (ch == 0x85);
  246.79 +        }
  246.80 +    },
  246.81 +
  246.82 +    CONTROL {
  246.83 +        // \p{gc=Control}
  246.84 +        public boolean is(int ch) {
  246.85 +            return Character.getType(ch) == Character.CONTROL;
  246.86 +        }
  246.87 +    },
  246.88 +
  246.89 +    PUNCTUATION {
  246.90 +        // \p{gc=Punctuation}
  246.91 +        public boolean is(int ch) {
  246.92 +            return ((((1 << Character.CONNECTOR_PUNCTUATION) |
  246.93 +                      (1 << Character.DASH_PUNCTUATION) |
  246.94 +                      (1 << Character.START_PUNCTUATION) |
  246.95 +                      (1 << Character.END_PUNCTUATION) |
  246.96 +                      (1 << Character.OTHER_PUNCTUATION) |
  246.97 +                      (1 << Character.INITIAL_QUOTE_PUNCTUATION) |
  246.98 +                      (1 << Character.FINAL_QUOTE_PUNCTUATION)) >> Character.getType(ch)) & 1)
  246.99 +                   != 0;
 246.100 +        }
 246.101 +    },
 246.102 +
 246.103 +    HEX_DIGIT {
 246.104 +        // \p{gc=Decimal_Number}
 246.105 +        // \p{Hex_Digit}    -> PropList.txt: Hex_Digit
 246.106 +        public boolean is(int ch) {
 246.107 +            return DIGIT.is(ch) ||
 246.108 +                   (ch >= 0x0030 && ch <= 0x0039) ||
 246.109 +                   (ch >= 0x0041 && ch <= 0x0046) ||
 246.110 +                   (ch >= 0x0061 && ch <= 0x0066) ||
 246.111 +                   (ch >= 0xFF10 && ch <= 0xFF19) ||
 246.112 +                   (ch >= 0xFF21 && ch <= 0xFF26) ||
 246.113 +                   (ch >= 0xFF41 && ch <= 0xFF46);
 246.114 +        }
 246.115 +    },
 246.116 +
 246.117 +    ASSIGNED {
 246.118 +        public boolean is(int ch) {
 246.119 +            return Character.getType(ch) != Character.UNASSIGNED;
 246.120 +        }
 246.121 +    },
 246.122 +
 246.123 +    NONCHARACTER_CODE_POINT {
 246.124 +        // PropList.txt:Noncharacter_Code_Point
 246.125 +        public boolean is(int ch) {
 246.126 +            return (ch & 0xfffe) == 0xfffe || (ch >= 0xfdd0 && ch <= 0xfdef);
 246.127 +        }
 246.128 +    },
 246.129 +
 246.130 +    DIGIT {
 246.131 +        // \p{gc=Decimal_Number}
 246.132 +        public boolean is(int ch) {
 246.133 +            return Character.isDigit(ch);
 246.134 +        }
 246.135 +    },
 246.136 +
 246.137 +    ALNUM {
 246.138 +        // \p{alpha}
 246.139 +        // \p{digit}
 246.140 +        public boolean is(int ch) {
 246.141 +            return ALPHABETIC.is(ch) || DIGIT.is(ch);
 246.142 +        }
 246.143 +    },
 246.144 +
 246.145 +    BLANK {
 246.146 +        // \p{Whitespace} --
 246.147 +        // [\N{LF} \N{VT} \N{FF} \N{CR} \N{NEL}  -> 0xa, 0xb, 0xc, 0xd, 0x85
 246.148 +        //  \p{gc=Line_Separator}
 246.149 +        //  \p{gc=Paragraph_Separator}]
 246.150 +        public boolean is(int ch) {
 246.151 +            return Character.getType(ch) == Character.SPACE_SEPARATOR ||
 246.152 +                   ch == 0x9; // \N{HT}
 246.153 +        }
 246.154 +    },
 246.155 +
 246.156 +    GRAPH {
 246.157 +        // [^
 246.158 +        //  \p{space}
 246.159 +        //  \p{gc=Control}
 246.160 +        //  \p{gc=Surrogate}
 246.161 +        //  \p{gc=Unassigned}]
 246.162 +        public boolean is(int ch) {
 246.163 +            return ((((1 << Character.SPACE_SEPARATOR) |
 246.164 +                      (1 << Character.LINE_SEPARATOR) |
 246.165 +                      (1 << Character.PARAGRAPH_SEPARATOR) |
 246.166 +                      (1 << Character.CONTROL) |
 246.167 +                      (1 << Character.SURROGATE) |
 246.168 +                      (1 << Character.UNASSIGNED)) >> Character.getType(ch)) & 1)
 246.169 +                   == 0;
 246.170 +        }
 246.171 +    },
 246.172 +
 246.173 +    PRINT {
 246.174 +        // \p{graph}
 246.175 +        // \p{blank}
 246.176 +        // -- \p{cntrl}
 246.177 +        public boolean is(int ch) {
 246.178 +            return (GRAPH.is(ch) || BLANK.is(ch)) && !CONTROL.is(ch);
 246.179 +        }
 246.180 +    },
 246.181 +
 246.182 +    WORD {
 246.183 +        //  \p{alpha}
 246.184 +        //  \p{gc=Mark}
 246.185 +        //  \p{digit}
 246.186 +        //  \p{gc=Connector_Punctuation}
 246.187 +
 246.188 +        public boolean is(int ch) {
 246.189 +            return ALPHABETIC.is(ch) ||
 246.190 +                   ((((1 << Character.NON_SPACING_MARK) |
 246.191 +                      (1 << Character.ENCLOSING_MARK) |
 246.192 +                      (1 << Character.COMBINING_SPACING_MARK) |
 246.193 +                      (1 << Character.DECIMAL_DIGIT_NUMBER) |
 246.194 +                      (1 << Character.CONNECTOR_PUNCTUATION)) >> Character.getType(ch)) & 1)
 246.195 +                   != 0;
 246.196 +        }
 246.197 +    };
 246.198 +
 246.199 +    private final static HashMap<String, String> posix = new HashMap<>();
 246.200 +    private final static HashMap<String, String> aliases = new HashMap<>();
 246.201 +    static {
 246.202 +        posix.put("ALPHA", "ALPHABETIC");
 246.203 +        posix.put("LOWER", "LOWERCASE");
 246.204 +        posix.put("UPPER", "UPPERCASE");
 246.205 +        posix.put("SPACE", "WHITE_SPACE");
 246.206 +        posix.put("PUNCT", "PUNCTUATION");
 246.207 +        posix.put("XDIGIT","HEX_DIGIT");
 246.208 +        posix.put("ALNUM", "ALNUM");
 246.209 +        posix.put("CNTRL", "CONTROL");
 246.210 +        posix.put("DIGIT", "DIGIT");
 246.211 +        posix.put("BLANK", "BLANK");
 246.212 +        posix.put("GRAPH", "GRAPH");
 246.213 +        posix.put("PRINT", "PRINT");
 246.214 +
 246.215 +        aliases.put("WHITESPACE", "WHITE_SPACE");
 246.216 +        aliases.put("HEXDIGIT","HEX_DIGIT");
 246.217 +        aliases.put("NONCHARACTERCODEPOINT", "NONCHARACTER_CODE_POINT");
 246.218 +    }
 246.219 +
 246.220 +    public static UnicodeProp forName(String propName) {
 246.221 +        propName = propName.toUpperCase(Locale.ENGLISH);
 246.222 +        String alias = aliases.get(propName);
 246.223 +        if (alias != null)
 246.224 +            propName = alias;
 246.225 +        try {
 246.226 +            return valueOf (propName);
 246.227 +        } catch (IllegalArgumentException x) {}
 246.228 +        return null;
 246.229 +    }
 246.230 +
 246.231 +    public static UnicodeProp forPOSIXName(String propName) {
 246.232 +        propName = posix.get(propName.toUpperCase(Locale.ENGLISH));
 246.233 +        if (propName == null)
 246.234 +            return null;
 246.235 +        return valueOf (propName);
 246.236 +    }
 246.237 +
 246.238 +    public abstract boolean is(int ch);
 246.239 +}
   247.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   247.2 +++ b/rt/emul/compact/src/main/java/java/util/regex/package.html	Wed Apr 30 15:04:10 2014 +0200
   247.3 @@ -0,0 +1,66 @@
   247.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
   247.5 +<html>
   247.6 +<head>
   247.7 +<!--
   247.8 +Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
   247.9 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  247.10 +
  247.11 +This code is free software; you can redistribute it and/or modify it
  247.12 +under the terms of the GNU General Public License version 2 only, as
  247.13 +published by the Free Software Foundation.  Oracle designates this
  247.14 +particular file as subject to the "Classpath" exception as provided
  247.15 +by Oracle in the LICENSE file that accompanied this code.
  247.16 +
  247.17 +This code is distributed in the hope that it will be useful, but WITHOUT
  247.18 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  247.19 +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  247.20 +version 2 for more details (a copy is included in the LICENSE file that
  247.21 +accompanied this code).
  247.22 +
  247.23 +You should have received a copy of the GNU General Public License version
  247.24 +2 along with this work; if not, write to the Free Software Foundation,
  247.25 +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  247.26 +
  247.27 +Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  247.28 +or visit www.oracle.com if you need additional information or have any
  247.29 +questions.
  247.30 +-->
  247.31 +
  247.32 +</head>
  247.33 +<body bgcolor="white">
  247.34 +
  247.35 +Classes for matching character sequences against patterns specified by regular
  247.36 +expressions.
  247.37 +
  247.38 +<p> An instance of the {@link java.util.regex.Pattern} class represents a
  247.39 +regular expression that is specified in string form in a syntax similar to
  247.40 +that used by Perl.
  247.41 +
  247.42 +<p> Instances of the {@link java.util.regex.Matcher} class are used to match
  247.43 +character sequences against a given pattern.  Input is provided to matchers via
  247.44 +the {@link java.lang.CharSequence} interface in order to support matching
  247.45 +against characters from a wide variety of input sources. </p>
  247.46 +
  247.47 +<p> Unless otherwise noted, passing a <tt>null</tt> argument to a method
  247.48 +in any class or interface in this package will cause a
  247.49 +{@link java.lang.NullPointerException NullPointerException} to be thrown.
  247.50 +
  247.51 +<h2>Related Documentation</h2>
  247.52 +
  247.53 +<p> An excellent tutorial and overview of regular expressions is <a
  247.54 +href="http://www.oreilly.com/catalog/regex/"><i>Mastering Regular
  247.55 +Expressions</i>, Jeffrey E. F. Friedl, O'Reilly and Associates, 1997.</a> </p>
  247.56 +
  247.57 +<!--
  247.58 +For overviews, tutorials, examples, guides, and tool documentation, please see:
  247.59 +<ul>
  247.60 +  <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
  247.61 +</ul>
  247.62 +-->
  247.63 +
  247.64 +@since 1.4
  247.65 +@author Mike McCloskey
  247.66 +@author Mark Reinhold
  247.67 +
  247.68 +</body>
  247.69 +</html>
   248.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   248.2 +++ b/rt/emul/compact/src/main/java/org/apidesign/bck2brwsr/emul/reflect/ProxyImpl.java	Wed Apr 30 15:04:10 2014 +0200
   248.3 @@ -0,0 +1,1620 @@
   248.4 +/*
   248.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
   248.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   248.7 + *
   248.8 + * This code is free software; you can redistribute it and/or modify it
   248.9 + * under the terms of the GNU General Public License version 2 only, as
  248.10 + * published by the Free Software Foundation.  Oracle designates this
  248.11 + * particular file as subject to the "Classpath" exception as provided
  248.12 + * by Oracle in the LICENSE file that accompanied this code.
  248.13 + *
  248.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  248.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  248.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  248.17 + * version 2 for more details (a copy is included in the LICENSE file that
  248.18 + * accompanied this code).
  248.19 + *
  248.20 + * You should have received a copy of the GNU General Public License version
  248.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  248.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  248.23 + *
  248.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  248.25 + * or visit www.oracle.com if you need additional information or have any
  248.26 + * questions.
  248.27 + */
  248.28 +
  248.29 +package org.apidesign.bck2brwsr.emul.reflect;
  248.30 +
  248.31 +import java.io.ByteArrayOutputStream;
  248.32 +import java.io.DataOutputStream;
  248.33 +import java.io.IOException;
  248.34 +import java.io.OutputStream;
  248.35 +import java.lang.ref.Reference;
  248.36 +import java.lang.ref.WeakReference;
  248.37 +import java.lang.reflect.Array;
  248.38 +import java.lang.reflect.Constructor;
  248.39 +import java.lang.reflect.InvocationHandler;
  248.40 +import java.lang.reflect.InvocationTargetException;
  248.41 +import java.lang.reflect.Method;
  248.42 +import java.lang.reflect.Modifier;
  248.43 +import java.util.ArrayList;
  248.44 +import java.util.Arrays;
  248.45 +import java.util.Collections;
  248.46 +import java.util.HashMap;
  248.47 +import java.util.HashSet;
  248.48 +import java.util.LinkedList;
  248.49 +import java.util.Map;
  248.50 +import java.util.Set;
  248.51 +import java.util.List;
  248.52 +import java.util.ListIterator;
  248.53 +import java.util.WeakHashMap;
  248.54 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  248.55 +import org.apidesign.bck2brwsr.emul.reflect.MethodImpl;
  248.56 +
  248.57 +/**
  248.58 + * {@code Proxy} provides static methods for creating dynamic proxy
  248.59 + * classes and instances, and it is also the superclass of all
  248.60 + * dynamic proxy classes created by those methods.
  248.61 + *
  248.62 + * <p>To create a proxy for some interface {@code Foo}:
  248.63 + * <pre>
  248.64 + *     InvocationHandler handler = new MyInvocationHandler(...);
  248.65 + *     Class proxyClass = Proxy.getProxyClass(
  248.66 + *         Foo.class.getClassLoader(), new Class[] { Foo.class });
  248.67 + *     Foo f = (Foo) proxyClass.
  248.68 + *         getConstructor(new Class[] { InvocationHandler.class }).
  248.69 + *         newInstance(new Object[] { handler });
  248.70 + * </pre>
  248.71 + * or more simply:
  248.72 + * <pre>
  248.73 + *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
  248.74 + *                                          new Class[] { Foo.class },
  248.75 + *                                          handler);
  248.76 + * </pre>
  248.77 + *
  248.78 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
  248.79 + * class</i> below) is a class that implements a list of interfaces
  248.80 + * specified at runtime when the class is created, with behavior as
  248.81 + * described below.
  248.82 + *
  248.83 + * A <i>proxy interface</i> is such an interface that is implemented
  248.84 + * by a proxy class.
  248.85 + *
  248.86 + * A <i>proxy instance</i> is an instance of a proxy class.
  248.87 + *
  248.88 + * Each proxy instance has an associated <i>invocation handler</i>
  248.89 + * object, which implements the interface {@link InvocationHandler}.
  248.90 + * A method invocation on a proxy instance through one of its proxy
  248.91 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
  248.92 + * invoke} method of the instance's invocation handler, passing the proxy
  248.93 + * instance, a {@code java.lang.reflect.Method} object identifying
  248.94 + * the method that was invoked, and an array of type {@code Object}
  248.95 + * containing the arguments.  The invocation handler processes the
  248.96 + * encoded method invocation as appropriate and the result that it
  248.97 + * returns will be returned as the result of the method invocation on
  248.98 + * the proxy instance.
  248.99 + *
 248.100 + * <p>A proxy class has the following properties:
 248.101 + *
 248.102 + * <ul>
 248.103 + * <li>Proxy classes are public, final, and not abstract.
 248.104 + *
 248.105 + * <li>The unqualified name of a proxy class is unspecified.  The space
 248.106 + * of class names that begin with the string {@code "$Proxy"}
 248.107 + * should be, however, reserved for proxy classes.
 248.108 + *
 248.109 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
 248.110 + *
 248.111 + * <li>A proxy class implements exactly the interfaces specified at its
 248.112 + * creation, in the same order.
 248.113 + *
 248.114 + * <li>If a proxy class implements a non-public interface, then it will
 248.115 + * be defined in the same package as that interface.  Otherwise, the
 248.116 + * package of a proxy class is also unspecified.  Note that package
 248.117 + * sealing will not prevent a proxy class from being successfully defined
 248.118 + * in a particular package at runtime, and neither will classes already
 248.119 + * defined by the same class loader and the same package with particular
 248.120 + * signers.
 248.121 + *
 248.122 + * <li>Since a proxy class implements all of the interfaces specified at
 248.123 + * its creation, invoking {@code getInterfaces} on its
 248.124 + * {@code Class} object will return an array containing the same
 248.125 + * list of interfaces (in the order specified at its creation), invoking
 248.126 + * {@code getMethods} on its {@code Class} object will return
 248.127 + * an array of {@code Method} objects that include all of the
 248.128 + * methods in those interfaces, and invoking {@code getMethod} will
 248.129 + * find methods in the proxy interfaces as would be expected.
 248.130 + *
 248.131 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
 248.132 + * return true if it is passed a proxy class-- a class returned by
 248.133 + * {@code Proxy.getProxyClass} or the class of an object returned by
 248.134 + * {@code Proxy.newProxyInstance}-- and false otherwise.
 248.135 + *
 248.136 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
 248.137 + * is the same as that of system classes loaded by the bootstrap class
 248.138 + * loader, such as {@code java.lang.Object}, because the code for a
 248.139 + * proxy class is generated by trusted system code.  This protection
 248.140 + * domain will typically be granted
 248.141 + * {@code java.security.AllPermission}.
 248.142 + *
 248.143 + * <li>Each proxy class has one public constructor that takes one argument,
 248.144 + * an implementation of the interface {@link InvocationHandler}, to set
 248.145 + * the invocation handler for a proxy instance.  Rather than having to use
 248.146 + * the reflection API to access the public constructor, a proxy instance
 248.147 + * can be also be created by calling the {@link Proxy#newProxyInstance
 248.148 + * Proxy.newProxyInstance} method, which combines the actions of calling
 248.149 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
 248.150 + * constructor with an invocation handler.
 248.151 + * </ul>
 248.152 + *
 248.153 + * <p>A proxy instance has the following properties:
 248.154 + *
 248.155 + * <ul>
 248.156 + * <li>Given a proxy instance {@code proxy} and one of the
 248.157 + * interfaces implemented by its proxy class {@code Foo}, the
 248.158 + * following expression will return true:
 248.159 + * <pre>
 248.160 + *     {@code proxy instanceof Foo}
 248.161 + * </pre>
 248.162 + * and the following cast operation will succeed (rather than throwing
 248.163 + * a {@code ClassCastException}):
 248.164 + * <pre>
 248.165 + *     {@code (Foo) proxy}
 248.166 + * </pre>
 248.167 + *
 248.168 + * <li>Each proxy instance has an associated invocation handler, the one
 248.169 + * that was passed to its constructor.  The static
 248.170 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
 248.171 + * will return the invocation handler associated with the proxy instance
 248.172 + * passed as its argument.
 248.173 + *
 248.174 + * <li>An interface method invocation on a proxy instance will be
 248.175 + * encoded and dispatched to the invocation handler's {@link
 248.176 + * InvocationHandler#invoke invoke} method as described in the
 248.177 + * documentation for that method.
 248.178 + *
 248.179 + * <li>An invocation of the {@code hashCode},
 248.180 + * {@code equals}, or {@code toString} methods declared in
 248.181 + * {@code java.lang.Object} on a proxy instance will be encoded and
 248.182 + * dispatched to the invocation handler's {@code invoke} method in
 248.183 + * the same manner as interface method invocations are encoded and
 248.184 + * dispatched, as described above.  The declaring class of the
 248.185 + * {@code Method} object passed to {@code invoke} will be
 248.186 + * {@code java.lang.Object}.  Other public methods of a proxy
 248.187 + * instance inherited from {@code java.lang.Object} are not
 248.188 + * overridden by a proxy class, so invocations of those methods behave
 248.189 + * like they do for instances of {@code java.lang.Object}.
 248.190 + * </ul>
 248.191 + *
 248.192 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
 248.193 + *
 248.194 + * <p>When two or more interfaces of a proxy class contain a method with
 248.195 + * the same name and parameter signature, the order of the proxy class's
 248.196 + * interfaces becomes significant.  When such a <i>duplicate method</i>
 248.197 + * is invoked on a proxy instance, the {@code Method} object passed
 248.198 + * to the invocation handler will not necessarily be the one whose
 248.199 + * declaring class is assignable from the reference type of the interface
 248.200 + * that the proxy's method was invoked through.  This limitation exists
 248.201 + * because the corresponding method implementation in the generated proxy
 248.202 + * class cannot determine which interface it was invoked through.
 248.203 + * Therefore, when a duplicate method is invoked on a proxy instance,
 248.204 + * the {@code Method} object for the method in the foremost interface
 248.205 + * that contains the method (either directly or inherited through a
 248.206 + * superinterface) in the proxy class's list of interfaces is passed to
 248.207 + * the invocation handler's {@code invoke} method, regardless of the
 248.208 + * reference type through which the method invocation occurred.
 248.209 + *
 248.210 + * <p>If a proxy interface contains a method with the same name and
 248.211 + * parameter signature as the {@code hashCode}, {@code equals},
 248.212 + * or {@code toString} methods of {@code java.lang.Object},
 248.213 + * when such a method is invoked on a proxy instance, the
 248.214 + * {@code Method} object passed to the invocation handler will have
 248.215 + * {@code java.lang.Object} as its declaring class.  In other words,
 248.216 + * the public, non-final methods of {@code java.lang.Object}
 248.217 + * logically precede all of the proxy interfaces for the determination of
 248.218 + * which {@code Method} object to pass to the invocation handler.
 248.219 + *
 248.220 + * <p>Note also that when a duplicate method is dispatched to an
 248.221 + * invocation handler, the {@code invoke} method may only throw
 248.222 + * checked exception types that are assignable to one of the exception
 248.223 + * types in the {@code throws} clause of the method in <i>all</i> of
 248.224 + * the proxy interfaces that it can be invoked through.  If the
 248.225 + * {@code invoke} method throws a checked exception that is not
 248.226 + * assignable to any of the exception types declared by the method in one
 248.227 + * of the proxy interfaces that it can be invoked through, then an
 248.228 + * unchecked {@code UndeclaredThrowableException} will be thrown by
 248.229 + * the invocation on the proxy instance.  This restriction means that not
 248.230 + * all of the exception types returned by invoking
 248.231 + * {@code getExceptionTypes} on the {@code Method} object
 248.232 + * passed to the {@code invoke} method can necessarily be thrown
 248.233 + * successfully by the {@code invoke} method.
 248.234 + *
 248.235 + * @author      Peter Jones
 248.236 + * @see         InvocationHandler
 248.237 + * @since       1.3
 248.238 + */
 248.239 +public final class ProxyImpl implements java.io.Serializable {
 248.240 +
 248.241 +    private static final long serialVersionUID = -2222568056686623797L;
 248.242 +
 248.243 +    /** prefix for all proxy class names */
 248.244 +    private final static String proxyClassNamePrefix = "$Proxy";
 248.245 +
 248.246 +    /** parameter types of a proxy class constructor */
 248.247 +    private final static Class[] constructorParams =
 248.248 +        { InvocationHandler.class };
 248.249 +
 248.250 +    /** maps a class loader to the proxy class cache for that loader */
 248.251 +    private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
 248.252 +        = new WeakHashMap<>();
 248.253 +
 248.254 +    /** marks that a particular proxy class is currently being generated */
 248.255 +    private static Object pendingGenerationMarker = new Object();
 248.256 +
 248.257 +    /** next number to use for generation of unique proxy class names */
 248.258 +    private static long nextUniqueNumber = 0;
 248.259 +    private static Object nextUniqueNumberLock = new Object();
 248.260 +
 248.261 +    /** set of all generated proxy classes, for isProxyClass implementation */
 248.262 +    private static Map<Class<?>, Void> proxyClasses =
 248.263 +        Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
 248.264 +
 248.265 +    /**
 248.266 +     * the invocation handler for this proxy instance.
 248.267 +     * @serial
 248.268 +     */
 248.269 +    protected InvocationHandler h;
 248.270 +
 248.271 +    /**
 248.272 +     * Prohibits instantiation.
 248.273 +     */
 248.274 +    private ProxyImpl() {
 248.275 +    }
 248.276 +
 248.277 +    /**
 248.278 +     * Constructs a new {@code Proxy} instance from a subclass
 248.279 +     * (typically, a dynamic proxy class) with the specified value
 248.280 +     * for its invocation handler.
 248.281 +     *
 248.282 +     * @param   h the invocation handler for this proxy instance
 248.283 +     */
 248.284 +    protected ProxyImpl(InvocationHandler h) {
 248.285 +        this.h = h;
 248.286 +    }
 248.287 +
 248.288 +    /**
 248.289 +     * Returns the {@code java.lang.Class} object for a proxy class
 248.290 +     * given a class loader and an array of interfaces.  The proxy class
 248.291 +     * will be defined by the specified class loader and will implement
 248.292 +     * all of the supplied interfaces.  If a proxy class for the same
 248.293 +     * permutation of interfaces has already been defined by the class
 248.294 +     * loader, then the existing proxy class will be returned; otherwise,
 248.295 +     * a proxy class for those interfaces will be generated dynamically
 248.296 +     * and defined by the class loader.
 248.297 +     *
 248.298 +     * <p>There are several restrictions on the parameters that may be
 248.299 +     * passed to {@code Proxy.getProxyClass}:
 248.300 +     *
 248.301 +     * <ul>
 248.302 +     * <li>All of the {@code Class} objects in the
 248.303 +     * {@code interfaces} array must represent interfaces, not
 248.304 +     * classes or primitive types.
 248.305 +     *
 248.306 +     * <li>No two elements in the {@code interfaces} array may
 248.307 +     * refer to identical {@code Class} objects.
 248.308 +     *
 248.309 +     * <li>All of the interface types must be visible by name through the
 248.310 +     * specified class loader.  In other words, for class loader
 248.311 +     * {@code cl} and every interface {@code i}, the following
 248.312 +     * expression must be true:
 248.313 +     * <pre>
 248.314 +     *     Class.forName(i.getName(), false, cl) == i
 248.315 +     * </pre>
 248.316 +     *
 248.317 +     * <li>All non-public interfaces must be in the same package;
 248.318 +     * otherwise, it would not be possible for the proxy class to
 248.319 +     * implement all of the interfaces, regardless of what package it is
 248.320 +     * defined in.
 248.321 +     *
 248.322 +     * <li>For any set of member methods of the specified interfaces
 248.323 +     * that have the same signature:
 248.324 +     * <ul>
 248.325 +     * <li>If the return type of any of the methods is a primitive
 248.326 +     * type or void, then all of the methods must have that same
 248.327 +     * return type.
 248.328 +     * <li>Otherwise, one of the methods must have a return type that
 248.329 +     * is assignable to all of the return types of the rest of the
 248.330 +     * methods.
 248.331 +     * </ul>
 248.332 +     *
 248.333 +     * <li>The resulting proxy class must not exceed any limits imposed
 248.334 +     * on classes by the virtual machine.  For example, the VM may limit
 248.335 +     * the number of interfaces that a class may implement to 65535; in
 248.336 +     * that case, the size of the {@code interfaces} array must not
 248.337 +     * exceed 65535.
 248.338 +     * </ul>
 248.339 +     *
 248.340 +     * <p>If any of these restrictions are violated,
 248.341 +     * {@code Proxy.getProxyClass} will throw an
 248.342 +     * {@code IllegalArgumentException}.  If the {@code interfaces}
 248.343 +     * array argument or any of its elements are {@code null}, a
 248.344 +     * {@code NullPointerException} will be thrown.
 248.345 +     *
 248.346 +     * <p>Note that the order of the specified proxy interfaces is
 248.347 +     * significant: two requests for a proxy class with the same combination
 248.348 +     * of interfaces but in a different order will result in two distinct
 248.349 +     * proxy classes.
 248.350 +     *
 248.351 +     * @param   loader the class loader to define the proxy class
 248.352 +     * @param   interfaces the list of interfaces for the proxy class
 248.353 +     *          to implement
 248.354 +     * @return  a proxy class that is defined in the specified class loader
 248.355 +     *          and that implements the specified interfaces
 248.356 +     * @throws  IllegalArgumentException if any of the restrictions on the
 248.357 +     *          parameters that may be passed to {@code getProxyClass}
 248.358 +     *          are violated
 248.359 +     * @throws  NullPointerException if the {@code interfaces} array
 248.360 +     *          argument or any of its elements are {@code null}
 248.361 +     */
 248.362 +    public static Class<?> getProxyClass(ClassLoader loader,
 248.363 +                                         Class<?>... interfaces)
 248.364 +        throws IllegalArgumentException
 248.365 +    {
 248.366 +        if (interfaces.length > 65535) {
 248.367 +            throw new IllegalArgumentException("interface limit exceeded");
 248.368 +        }
 248.369 +
 248.370 +        Class<?> proxyClass = null;
 248.371 +
 248.372 +        /* collect interface names to use as key for proxy class cache */
 248.373 +        String[] interfaceNames = new String[interfaces.length];
 248.374 +
 248.375 +        // for detecting duplicates
 248.376 +        Set<Class<?>> interfaceSet = new HashSet<>();
 248.377 +
 248.378 +        for (int i = 0; i < interfaces.length; i++) {
 248.379 +            /*
 248.380 +             * Verify that the class loader resolves the name of this
 248.381 +             * interface to the same Class object.
 248.382 +             */
 248.383 +            String interfaceName = interfaces[i].getName();
 248.384 +            Class<?> interfaceClass = null;
 248.385 +            try {
 248.386 +                interfaceClass = Class.forName(interfaceName, false, loader);
 248.387 +            } catch (ClassNotFoundException e) {
 248.388 +            }
 248.389 +            if (interfaceClass != interfaces[i]) {
 248.390 +                throw new IllegalArgumentException(
 248.391 +                    interfaces[i] + " is not visible from class loader");
 248.392 +            }
 248.393 +
 248.394 +            /*
 248.395 +             * Verify that the Class object actually represents an
 248.396 +             * interface.
 248.397 +             */
 248.398 +            if (!interfaceClass.isInterface()) {
 248.399 +                throw new IllegalArgumentException(
 248.400 +                    interfaceClass.getName() + " is not an interface");
 248.401 +            }
 248.402 +
 248.403 +            /*
 248.404 +             * Verify that this interface is not a duplicate.
 248.405 +             */
 248.406 +            if (interfaceSet.contains(interfaceClass)) {
 248.407 +                throw new IllegalArgumentException(
 248.408 +                    "repeated interface: " + interfaceClass.getName());
 248.409 +            }
 248.410 +            interfaceSet.add(interfaceClass);
 248.411 +
 248.412 +            interfaceNames[i] = interfaceName;
 248.413 +        }
 248.414 +
 248.415 +        /*
 248.416 +         * Using string representations of the proxy interfaces as
 248.417 +         * keys in the proxy class cache (instead of their Class
 248.418 +         * objects) is sufficient because we require the proxy
 248.419 +         * interfaces to be resolvable by name through the supplied
 248.420 +         * class loader, and it has the advantage that using a string
 248.421 +         * representation of a class makes for an implicit weak
 248.422 +         * reference to the class.
 248.423 +         */
 248.424 +        List<String> key = Arrays.asList(interfaceNames);
 248.425 +
 248.426 +        /*
 248.427 +         * Find or create the proxy class cache for the class loader.
 248.428 +         */
 248.429 +        Map<List<String>, Object> cache;
 248.430 +        synchronized (loaderToCache) {
 248.431 +            cache = loaderToCache.get(loader);
 248.432 +            if (cache == null) {
 248.433 +                cache = new HashMap<>();
 248.434 +                loaderToCache.put(loader, cache);
 248.435 +            }
 248.436 +            /*
 248.437 +             * This mapping will remain valid for the duration of this
 248.438 +             * method, without further synchronization, because the mapping
 248.439 +             * will only be removed if the class loader becomes unreachable.
 248.440 +             */
 248.441 +        }
 248.442 +
 248.443 +        /*
 248.444 +         * Look up the list of interfaces in the proxy class cache using
 248.445 +         * the key.  This lookup will result in one of three possible
 248.446 +         * kinds of values:
 248.447 +         *     null, if there is currently no proxy class for the list of
 248.448 +         *         interfaces in the class loader,
 248.449 +         *     the pendingGenerationMarker object, if a proxy class for the
 248.450 +         *         list of interfaces is currently being generated,
 248.451 +         *     or a weak reference to a Class object, if a proxy class for
 248.452 +         *         the list of interfaces has already been generated.
 248.453 +         */
 248.454 +        synchronized (cache) {
 248.455 +            /*
 248.456 +             * Note that we need not worry about reaping the cache for
 248.457 +             * entries with cleared weak references because if a proxy class
 248.458 +             * has been garbage collected, its class loader will have been
 248.459 +             * garbage collected as well, so the entire cache will be reaped
 248.460 +             * from the loaderToCache map.
 248.461 +             */
 248.462 +            do {
 248.463 +                Object value = cache.get(key);
 248.464 +                if (value instanceof Reference) {
 248.465 +                    proxyClass = (Class<?>) ((Reference) value).get();
 248.466 +                }
 248.467 +                if (proxyClass != null) {
 248.468 +                    // proxy class already generated: return it
 248.469 +                    return proxyClass;
 248.470 +                } else if (value == pendingGenerationMarker) {
 248.471 +                    // proxy class being generated: wait for it
 248.472 +                    try {
 248.473 +                        cache.wait();
 248.474 +                    } catch (InterruptedException e) {
 248.475 +                        /*
 248.476 +                         * The class generation that we are waiting for should
 248.477 +                         * take a small, bounded time, so we can safely ignore
 248.478 +                         * thread interrupts here.
 248.479 +                         */
 248.480 +                    }
 248.481 +                    continue;
 248.482 +                } else {
 248.483 +                    /*
 248.484 +                     * No proxy class for this list of interfaces has been
 248.485 +                     * generated or is being generated, so we will go and
 248.486 +                     * generate it now.  Mark it as pending generation.
 248.487 +                     */
 248.488 +                    cache.put(key, pendingGenerationMarker);
 248.489 +                    break;
 248.490 +                }
 248.491 +            } while (true);
 248.492 +        }
 248.493 +
 248.494 +        try {
 248.495 +            String proxyPkg = null;     // package to define proxy class in
 248.496 +
 248.497 +            /*
 248.498 +             * Record the package of a non-public proxy interface so that the
 248.499 +             * proxy class will be defined in the same package.  Verify that
 248.500 +             * all non-public proxy interfaces are in the same package.
 248.501 +             */
 248.502 +            for (int i = 0; i < interfaces.length; i++) {
 248.503 +                int flags = interfaces[i].getModifiers();
 248.504 +                if (!Modifier.isPublic(flags)) {
 248.505 +                    String name = interfaces[i].getName();
 248.506 +                    int n = name.lastIndexOf('.');
 248.507 +                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
 248.508 +                    if (proxyPkg == null) {
 248.509 +                        proxyPkg = pkg;
 248.510 +                    } else if (!pkg.equals(proxyPkg)) {
 248.511 +                        throw new IllegalArgumentException(
 248.512 +                            "non-public interfaces from different packages");
 248.513 +                    }
 248.514 +                }
 248.515 +            }
 248.516 +
 248.517 +            if (proxyPkg == null) {     // if no non-public proxy interfaces,
 248.518 +                proxyPkg = "";          // use the unnamed package
 248.519 +            }
 248.520 +
 248.521 +            {
 248.522 +                /*
 248.523 +                 * Choose a name for the proxy class to generate.
 248.524 +                 */
 248.525 +                long num;
 248.526 +                synchronized (nextUniqueNumberLock) {
 248.527 +                    num = nextUniqueNumber++;
 248.528 +                }
 248.529 +                String proxyName = proxyPkg + proxyClassNamePrefix + num;
 248.530 +                /*
 248.531 +                 * Verify that the class loader hasn't already
 248.532 +                 * defined a class with the chosen name.
 248.533 +                 */
 248.534 +
 248.535 +                /*
 248.536 +                 * Generate the specified proxy class.
 248.537 +                 */
 248.538 +                Generator gen = new Generator(proxyName, interfaces);
 248.539 +                final byte[] proxyClassFile = gen.generateClassFile();
 248.540 +                try {
 248.541 +                    proxyClass = defineClass0(loader, proxyName,
 248.542 +                        proxyClassFile);
 248.543 +                } catch (ClassFormatError e) {
 248.544 +                    /*
 248.545 +                     * A ClassFormatError here means that (barring bugs in the
 248.546 +                     * proxy class generation code) there was some other
 248.547 +                     * invalid aspect of the arguments supplied to the proxy
 248.548 +                     * class creation (such as virtual machine limitations
 248.549 +                     * exceeded).
 248.550 +                     */
 248.551 +                    throw new IllegalArgumentException(e.toString());
 248.552 +                }
 248.553 +                gen.fillInMethods(proxyClass);
 248.554 +            }
 248.555 +            // add to set of all generated proxy classes, for isProxyClass
 248.556 +            proxyClasses.put(proxyClass, null);
 248.557 +
 248.558 +        } finally {
 248.559 +            /*
 248.560 +             * We must clean up the "pending generation" state of the proxy
 248.561 +             * class cache entry somehow.  If a proxy class was successfully
 248.562 +             * generated, store it in the cache (with a weak reference);
 248.563 +             * otherwise, remove the reserved entry.  In all cases, notify
 248.564 +             * all waiters on reserved entries in this cache.
 248.565 +             */
 248.566 +            synchronized (cache) {
 248.567 +                if (proxyClass != null) {
 248.568 +                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
 248.569 +                } else {
 248.570 +                    cache.remove(key);
 248.571 +                }
 248.572 +                cache.notifyAll();
 248.573 +            }
 248.574 +        }
 248.575 +        return proxyClass;
 248.576 +    }
 248.577 +
 248.578 +    /**
 248.579 +     * Returns an instance of a proxy class for the specified interfaces
 248.580 +     * that dispatches method invocations to the specified invocation
 248.581 +     * handler.  This method is equivalent to:
 248.582 +     * <pre>
 248.583 +     *     Proxy.getProxyClass(loader, interfaces).
 248.584 +     *         getConstructor(new Class[] { InvocationHandler.class }).
 248.585 +     *         newInstance(new Object[] { handler });
 248.586 +     * </pre>
 248.587 +     *
 248.588 +     * <p>{@code Proxy.newProxyInstance} throws
 248.589 +     * {@code IllegalArgumentException} for the same reasons that
 248.590 +     * {@code Proxy.getProxyClass} does.
 248.591 +     *
 248.592 +     * @param   loader the class loader to define the proxy class
 248.593 +     * @param   interfaces the list of interfaces for the proxy class
 248.594 +     *          to implement
 248.595 +     * @param   h the invocation handler to dispatch method invocations to
 248.596 +     * @return  a proxy instance with the specified invocation handler of a
 248.597 +     *          proxy class that is defined by the specified class loader
 248.598 +     *          and that implements the specified interfaces
 248.599 +     * @throws  IllegalArgumentException if any of the restrictions on the
 248.600 +     *          parameters that may be passed to {@code getProxyClass}
 248.601 +     *          are violated
 248.602 +     * @throws  NullPointerException if the {@code interfaces} array
 248.603 +     *          argument or any of its elements are {@code null}, or
 248.604 +     *          if the invocation handler, {@code h}, is
 248.605 +     *          {@code null}
 248.606 +     */
 248.607 +    public static Object newProxyInstance(ClassLoader loader,
 248.608 +                                          Class<?>[] interfaces,
 248.609 +                                          InvocationHandler h)
 248.610 +        throws IllegalArgumentException
 248.611 +    {
 248.612 +        if (h == null) {
 248.613 +            throw new NullPointerException();
 248.614 +        }
 248.615 +
 248.616 +        /*
 248.617 +         * Look up or generate the designated proxy class.
 248.618 +         */
 248.619 +        Class<?> cl = getProxyClass(loader, interfaces);
 248.620 +
 248.621 +        /*
 248.622 +         * Invoke its constructor with the designated invocation handler.
 248.623 +         */
 248.624 +        try {
 248.625 +            Constructor cons = cl.getConstructor(constructorParams);
 248.626 +            return cons.newInstance(new Object[] { h });
 248.627 +        } catch (NoSuchMethodException e) {
 248.628 +            throw new InternalError(e.toString());
 248.629 +        } catch (IllegalAccessException e) {
 248.630 +            throw new InternalError(e.toString());
 248.631 +        } catch (InstantiationException e) {
 248.632 +            throw new InternalError(e.toString());
 248.633 +        } catch (InvocationTargetException e) {
 248.634 +            throw new InternalError(e.toString());
 248.635 +        }
 248.636 +    }
 248.637 +
 248.638 +    /**
 248.639 +     * Returns true if and only if the specified class was dynamically
 248.640 +     * generated to be a proxy class using the {@code getProxyClass}
 248.641 +     * method or the {@code newProxyInstance} method.
 248.642 +     *
 248.643 +     * <p>The reliability of this method is important for the ability
 248.644 +     * to use it to make security decisions, so its implementation should
 248.645 +     * not just test if the class in question extends {@code Proxy}.
 248.646 +     *
 248.647 +     * @param   cl the class to test
 248.648 +     * @return  {@code true} if the class is a proxy class and
 248.649 +     *          {@code false} otherwise
 248.650 +     * @throws  NullPointerException if {@code cl} is {@code null}
 248.651 +     */
 248.652 +    public static boolean isProxyClass(Class<?> cl) {
 248.653 +        if (cl == null) {
 248.654 +            throw new NullPointerException();
 248.655 +        }
 248.656 +
 248.657 +        return proxyClasses.containsKey(cl);
 248.658 +    }
 248.659 +
 248.660 +    /**
 248.661 +     * Returns the invocation handler for the specified proxy instance.
 248.662 +     *
 248.663 +     * @param   proxy the proxy instance to return the invocation handler for
 248.664 +     * @return  the invocation handler for the proxy instance
 248.665 +     * @throws  IllegalArgumentException if the argument is not a
 248.666 +     *          proxy instance
 248.667 +     */
 248.668 +    public static InvocationHandler getInvocationHandler(Object proxy)
 248.669 +        throws IllegalArgumentException
 248.670 +    {
 248.671 +        /*
 248.672 +         * Verify that the object is actually a proxy instance.
 248.673 +         */
 248.674 +        if (!isProxyClass(proxy.getClass())) {
 248.675 +            throw new IllegalArgumentException("not a proxy instance");
 248.676 +        }
 248.677 +
 248.678 +        ProxyImpl p = (ProxyImpl) proxy;
 248.679 +        return p.h;
 248.680 +    }
 248.681 +
 248.682 +    @JavaScriptBody(args = { "ignore", "name", "byteCode" }, 
 248.683 +        body = "return vm._reload(name, byteCode).constructor.$class;"
 248.684 +    )
 248.685 +    private static native Class defineClass0(
 248.686 +        ClassLoader loader, String name, byte[] b
 248.687 +    );
 248.688 +    
 248.689 +    private static class Generator {
 248.690 +        /*
 248.691 +         * In the comments below, "JVMS" refers to The Java Virtual Machine
 248.692 +         * Specification Second Edition and "JLS" refers to the original
 248.693 +         * version of The Java Language Specification, unless otherwise
 248.694 +         * specified.
 248.695 +         */
 248.696 +
 248.697 +        /* need 1.6 bytecode */
 248.698 +        private static final int CLASSFILE_MAJOR_VERSION = 50;
 248.699 +        private static final int CLASSFILE_MINOR_VERSION = 0;
 248.700 +
 248.701 +        /*
 248.702 +         * beginning of constants copied from
 248.703 +         * sun.tools.java.RuntimeConstants (which no longer exists):
 248.704 +         */
 248.705 +
 248.706 +        /* constant pool tags */
 248.707 +        private static final int CONSTANT_UTF8 = 1;
 248.708 +        private static final int CONSTANT_UNICODE = 2;
 248.709 +        private static final int CONSTANT_INTEGER = 3;
 248.710 +        private static final int CONSTANT_FLOAT = 4;
 248.711 +        private static final int CONSTANT_LONG = 5;
 248.712 +        private static final int CONSTANT_DOUBLE = 6;
 248.713 +        private static final int CONSTANT_CLASS = 7;
 248.714 +        private static final int CONSTANT_STRING = 8;
 248.715 +        private static final int CONSTANT_FIELD = 9;
 248.716 +        private static final int CONSTANT_METHOD = 10;
 248.717 +        private static final int CONSTANT_INTERFACEMETHOD = 11;
 248.718 +        private static final int CONSTANT_NAMEANDTYPE = 12;
 248.719 +
 248.720 +        /* access and modifier flags */
 248.721 +        private static final int ACC_PUBLIC = 0x00000001;
 248.722 +        private static final int ACC_FINAL = 0x00000010;
 248.723 +        private static final int ACC_SUPER = 0x00000020;
 248.724 +
 248.725 +    // end of constants copied from sun.tools.java.RuntimeConstants
 248.726 +        /**
 248.727 +         * name of the superclass of proxy classes
 248.728 +         */
 248.729 +        private final static String superclassName = "java/lang/reflect/Proxy";
 248.730 +
 248.731 +        /**
 248.732 +         * name of field for storing a proxy instance's invocation handler
 248.733 +         */
 248.734 +        private final static String handlerFieldName = "h";
 248.735 +
 248.736 +        /* preloaded Method objects for methods in java.lang.Object */
 248.737 +        private static Method hashCodeMethod;
 248.738 +        private static Method equalsMethod;
 248.739 +        private static Method toStringMethod;
 248.740 +
 248.741 +        static {
 248.742 +            try {
 248.743 +                hashCodeMethod = Object.class.getMethod("hashCode");
 248.744 +                equalsMethod
 248.745 +                    = Object.class.getMethod("equals", new Class[]{Object.class});
 248.746 +                toStringMethod = Object.class.getMethod("toString");
 248.747 +            } catch (NoSuchMethodException e) {
 248.748 +                throw new IllegalStateException(e.getMessage());
 248.749 +            }
 248.750 +        }
 248.751 +
 248.752 +        /**
 248.753 +         * name of proxy class
 248.754 +         */
 248.755 +        private String className;
 248.756 +
 248.757 +        /**
 248.758 +         * proxy interfaces
 248.759 +         */
 248.760 +        private Class[] interfaces;
 248.761 +
 248.762 +        /**
 248.763 +         * constant pool of class being generated
 248.764 +         */
 248.765 +        private ConstantPool cp = new ConstantPool();
 248.766 +
 248.767 +        /**
 248.768 +         * maps method signature string to list of ProxyMethod objects for proxy
 248.769 +         * methods with that signature
 248.770 +         */
 248.771 +        private Map<String, List<ProxyMethod>> proxyMethods
 248.772 +            = new HashMap<String, List<ProxyMethod>>();
 248.773 +
 248.774 +        /**
 248.775 +         * count of ProxyMethod objects added to proxyMethods
 248.776 +         */
 248.777 +        private int proxyMethodCount = 0;
 248.778 +
 248.779 +        /**
 248.780 +         * Construct a ProxyGenerator to generate a proxy class with the
 248.781 +         * specified name and for the given interfaces.
 248.782 +         *
 248.783 +         * A ProxyGenerator object contains the state for the ongoing generation
 248.784 +         * of a particular proxy class.
 248.785 +         */
 248.786 +        private Generator(String className, Class[] interfaces) {
 248.787 +            this.className = className;
 248.788 +            this.interfaces = interfaces;
 248.789 +        }
 248.790 +
 248.791 +        /**
 248.792 +         * Generate a class file for the proxy class. This method drives the
 248.793 +         * class file generation process.
 248.794 +         */
 248.795 +        private byte[] generateClassFile() {
 248.796 +
 248.797 +            /* ============================================================
 248.798 +             * Step 1: Assemble ProxyMethod objects for all methods to
 248.799 +             * generate proxy dispatching code for.
 248.800 +             */
 248.801 +
 248.802 +            /*
 248.803 +             * Record that proxy methods are needed for the hashCode, equals,
 248.804 +             * and toString methods of java.lang.Object.  This is done before
 248.805 +             * the methods from the proxy interfaces so that the methods from
 248.806 +             * java.lang.Object take precedence over duplicate methods in the
 248.807 +             * proxy interfaces.
 248.808 +             */
 248.809 +            addProxyMethod(hashCodeMethod, Object.class);
 248.810 +            addProxyMethod(equalsMethod, Object.class);
 248.811 +            addProxyMethod(toStringMethod, Object.class);
 248.812 +
 248.813 +            /*
 248.814 +             * Now record all of the methods from the proxy interfaces, giving
 248.815 +             * earlier interfaces precedence over later ones with duplicate
 248.816 +             * methods.
 248.817 +             */
 248.818 +            for (int i = 0; i < interfaces.length; i++) {
 248.819 +                Method[] methods = interfaces[i].getMethods();
 248.820 +                for (int j = 0; j < methods.length; j++) {
 248.821 +                    addProxyMethod(methods[j], interfaces[i]);
 248.822 +                }
 248.823 +            }
 248.824 +
 248.825 +            /*
 248.826 +             * For each set of proxy methods with the same signature,
 248.827 +             * verify that the methods' return types are compatible.
 248.828 +             */
 248.829 +            for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 248.830 +                checkReturnTypes(sigmethods);
 248.831 +            }
 248.832 +
 248.833 +            /* ============================================================
 248.834 +             * Step 2: Assemble FieldInfo and MethodInfo structs for all of
 248.835 +             * fields and methods in the class we are generating.
 248.836 +             */
 248.837 +            
 248.838 +            // will be done in fillInMethods
 248.839 +
 248.840 +            /* ============================================================
 248.841 +             * Step 3: Write the final class file.
 248.842 +             */
 248.843 +
 248.844 +            /*
 248.845 +             * Make sure that constant pool indexes are reserved for the
 248.846 +             * following items before starting to write the final class file.
 248.847 +             */
 248.848 +            cp.getClass(dotToSlash(className));
 248.849 +            cp.getClass(superclassName);
 248.850 +            for (int i = 0; i < interfaces.length; i++) {
 248.851 +                cp.getClass(dotToSlash(interfaces[i].getName()));
 248.852 +            }
 248.853 +
 248.854 +            /*
 248.855 +             * Disallow new constant pool additions beyond this point, since
 248.856 +             * we are about to write the final constant pool table.
 248.857 +             */
 248.858 +            cp.setReadOnly();
 248.859 +
 248.860 +            ByteArrayOutputStream bout = new ByteArrayOutputStream();
 248.861 +            DataOutputStream dout = new DataOutputStream(bout);
 248.862 +
 248.863 +            try {
 248.864 +                /*
 248.865 +                 * Write all the items of the "ClassFile" structure.
 248.866 +                 * See JVMS section 4.1.
 248.867 +                 */
 248.868 +                // u4 magic;
 248.869 +                dout.writeInt(0xCAFEBABE);
 248.870 +                // u2 minor_version;
 248.871 +                dout.writeShort(CLASSFILE_MINOR_VERSION);
 248.872 +                // u2 major_version;
 248.873 +                dout.writeShort(CLASSFILE_MAJOR_VERSION);
 248.874 +
 248.875 +                cp.write(dout);             // (write constant pool)
 248.876 +
 248.877 +                // u2 access_flags;
 248.878 +                dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
 248.879 +                // u2 this_class;
 248.880 +                dout.writeShort(cp.getClass(dotToSlash(className)));
 248.881 +                // u2 super_class;
 248.882 +                dout.writeShort(cp.getClass(superclassName));
 248.883 +
 248.884 +                // u2 interfaces_count;
 248.885 +                dout.writeShort(interfaces.length);
 248.886 +                // u2 interfaces[interfaces_count];
 248.887 +                for (int i = 0; i < interfaces.length; i++) {
 248.888 +                    dout.writeShort(cp.getClass(
 248.889 +                        dotToSlash(interfaces[i].getName())));
 248.890 +                }
 248.891 +
 248.892 +                // u2 fields_count;
 248.893 +                dout.writeShort(0);
 248.894 +
 248.895 +                // u2 methods_count;
 248.896 +                dout.writeShort(0);
 248.897 +
 248.898 +                // u2 attributes_count;
 248.899 +                dout.writeShort(0); // (no ClassFile attributes for proxy classes)
 248.900 +
 248.901 +            } catch (IOException e) {
 248.902 +                throw new InternalError("unexpected I/O Exception");
 248.903 +            }
 248.904 +
 248.905 +            return bout.toByteArray();
 248.906 +        }
 248.907 +
 248.908 +        @JavaScriptBody(args = { "c", "sig", "method", "primitive" }, body = 
 248.909 +            "var p = c.cnstr.prototype;\n" +
 248.910 +            "p[sig] = function() {\n" +
 248.911 +            "  var h = this._h();\n" +
 248.912 +            "  var res = h.invoke__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_reflect_Method_2_3Ljava_lang_Object_2(this, method, arguments);\n" +
 248.913 +            "  \n" +
 248.914 +            "  \n" +
 248.915 +            "  return res;\n" +
 248.916 +            "};"
 248.917 +        )
 248.918 +        private static native void defineMethod(Class<?> proxyClass, String sig, Method method, boolean primitive);
 248.919 +
 248.920 +        @JavaScriptBody(args = "c", body = 
 248.921 +              "var h = c.cnstr.cons__VLjava_lang_reflect_InvocationHandler_2 = function(h) {\n"
 248.922 +            + "  c.superclass.cnstr.cons__VLjava_lang_reflect_InvocationHandler_2.call(this, h);\n"
 248.923 +            + "}\n"
 248.924 +            + "h.cls = c.cnstr;\n"
 248.925 +        )
 248.926 +        private static native void defineConstructor(Class<?> proxyClass);
 248.927 +        
 248.928 +        final void fillInMethods(Class<?> proxyClass) {
 248.929 +            for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 248.930 +                for (ProxyMethod pm : sigmethods) {
 248.931 +                    String sig = MethodImpl.toSignature(pm.method);
 248.932 +                    defineMethod(proxyClass, sig, pm.method, pm.method.getReturnType().isPrimitive());
 248.933 +                }
 248.934 +            }
 248.935 +            defineConstructor(proxyClass);
 248.936 +        }
 248.937 +
 248.938 +        /**
 248.939 +         * Add another method to be proxied, either by creating a new
 248.940 +         * ProxyMethod object or augmenting an old one for a duplicate method.
 248.941 +         *
 248.942 +         * "fromClass" indicates the proxy interface that the method was found
 248.943 +         * through, which may be different from (a subinterface of) the method's
 248.944 +         * "declaring class". Note that the first Method object passed for a
 248.945 +         * given name and descriptor identifies the Method object (and thus the
 248.946 +         * declaring class) that will be passed to the invocation handler's
 248.947 +         * "invoke" method for a given set of duplicate methods.
 248.948 +         */
 248.949 +        private void addProxyMethod(Method m, Class fromClass) {
 248.950 +            String name = m.getName();
 248.951 +            Class[] parameterTypes = m.getParameterTypes();
 248.952 +            Class returnType = m.getReturnType();
 248.953 +            Class[] exceptionTypes = m.getExceptionTypes();
 248.954 +
 248.955 +            String sig = MethodImpl.toSignature(m);
 248.956 +            List<ProxyMethod> sigmethods = proxyMethods.get(sig);
 248.957 +            if (sigmethods != null) {
 248.958 +                for (ProxyMethod pm : sigmethods) {
 248.959 +                    if (returnType == pm.returnType) {
 248.960 +                        /*
 248.961 +                         * Found a match: reduce exception types to the
 248.962 +                         * greatest set of exceptions that can thrown
 248.963 +                         * compatibly with the throws clauses of both
 248.964 +                         * overridden methods.
 248.965 +                         */
 248.966 +                        List<Class<?>> legalExceptions = new ArrayList<Class<?>>();
 248.967 +                        collectCompatibleTypes(
 248.968 +                            exceptionTypes, pm.exceptionTypes, legalExceptions);
 248.969 +                        collectCompatibleTypes(
 248.970 +                            pm.exceptionTypes, exceptionTypes, legalExceptions);
 248.971 +                        pm.exceptionTypes = new Class[legalExceptions.size()];
 248.972 +                        pm.exceptionTypes
 248.973 +                            = legalExceptions.toArray(pm.exceptionTypes);
 248.974 +                        return;
 248.975 +                    }
 248.976 +                }
 248.977 +            } else {
 248.978 +                sigmethods = new ArrayList<ProxyMethod>(3);
 248.979 +                proxyMethods.put(sig, sigmethods);
 248.980 +            }
 248.981 +            sigmethods.add(new ProxyMethod(m, name, parameterTypes, returnType,
 248.982 +                exceptionTypes, fromClass));
 248.983 +        }
 248.984 +
 248.985 +        /**
 248.986 +         * For a given set of proxy methods with the same signature, check that
 248.987 +         * their return types are compatible according to the Proxy
 248.988 +         * specification.
 248.989 +         *
 248.990 +         * Specifically, if there is more than one such method, then all of the
 248.991 +         * return types must be reference types, and there must be one return
 248.992 +         * type that is assignable to each of the rest of them.
 248.993 +         */
 248.994 +        private static void checkReturnTypes(List<ProxyMethod> methods) {
 248.995 +            /*
 248.996 +             * If there is only one method with a given signature, there
 248.997 +             * cannot be a conflict.  This is the only case in which a
 248.998 +             * primitive (or void) return type is allowed.
 248.999 +             */
248.1000 +            if (methods.size() < 2) {
248.1001 +                return;
248.1002 +            }
248.1003 +
248.1004 +            /*
248.1005 +             * List of return types that are not yet known to be
248.1006 +             * assignable from ("covered" by) any of the others.
248.1007 +             */
248.1008 +            LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<Class<?>>();
248.1009 +
248.1010 +            nextNewReturnType:
248.1011 +            for (ProxyMethod pm : methods) {
248.1012 +                Class<?> newReturnType = pm.returnType;
248.1013 +                if (newReturnType.isPrimitive()) {
248.1014 +                    throw new IllegalArgumentException(
248.1015 +                        "methods with same signature "
248.1016 +                        + getFriendlyMethodSignature(pm.methodName,
248.1017 +                            pm.parameterTypes)
248.1018 +                        + " but incompatible return types: "
248.1019 +                        + newReturnType.getName() + " and others");
248.1020 +                }
248.1021 +                boolean added = false;
248.1022 +
248.1023 +                /*
248.1024 +                 * Compare the new return type to the existing uncovered
248.1025 +                 * return types.
248.1026 +                 */
248.1027 +                ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
248.1028 +                while (liter.hasNext()) {
248.1029 +                    Class<?> uncoveredReturnType = liter.next();
248.1030 +
248.1031 +                    /*
248.1032 +                     * If an existing uncovered return type is assignable
248.1033 +                     * to this new one, then we can forget the new one.
248.1034 +                     */
248.1035 +                    if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
248.1036 +                        assert !added;
248.1037 +                        continue nextNewReturnType;
248.1038 +                    }
248.1039 +
248.1040 +                    /*
248.1041 +                     * If the new return type is assignable to an existing
248.1042 +                     * uncovered one, then should replace the existing one
248.1043 +                     * with the new one (or just forget the existing one,
248.1044 +                     * if the new one has already be put in the list).
248.1045 +                     */
248.1046 +                    if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
248.1047 +                        // (we can assume that each return type is unique)
248.1048 +                        if (!added) {
248.1049 +                            liter.set(newReturnType);
248.1050 +                            added = true;
248.1051 +                        } else {
248.1052 +                            liter.remove();
248.1053 +                        }
248.1054 +                    }
248.1055 +                }
248.1056 +
248.1057 +                /*
248.1058 +                 * If we got through the list of existing uncovered return
248.1059 +                 * types without an assignability relationship, then add
248.1060 +                 * the new return type to the list of uncovered ones.
248.1061 +                 */
248.1062 +                if (!added) {
248.1063 +                    uncoveredReturnTypes.add(newReturnType);
248.1064 +                }
248.1065 +            }
248.1066 +
248.1067 +            /*
248.1068 +             * We shouldn't end up with more than one return type that is
248.1069 +             * not assignable from any of the others.
248.1070 +             */
248.1071 +            if (uncoveredReturnTypes.size() > 1) {
248.1072 +                ProxyMethod pm = methods.get(0);
248.1073 +                throw new IllegalArgumentException(
248.1074 +                    "methods with same signature "
248.1075 +                    + getFriendlyMethodSignature(pm.methodName, pm.parameterTypes)
248.1076 +                    + " but incompatible return types: " + uncoveredReturnTypes);
248.1077 +            }
248.1078 +        }
248.1079 +
248.1080 +
248.1081 +        /**
248.1082 +         * A ProxyMethod object represents a proxy method in the proxy class
248.1083 +         * being generated: a method whose implementation will encode and
248.1084 +         * dispatch invocations to the proxy instance's invocation handler.
248.1085 +         */
248.1086 +        private class ProxyMethod {
248.1087 +
248.1088 +            private final Method method;
248.1089 +            public String methodName;
248.1090 +            public Class[] parameterTypes;
248.1091 +            public Class returnType;
248.1092 +            public Class[] exceptionTypes;
248.1093 +            public Class fromClass;
248.1094 +            public String methodFieldName;
248.1095 +
248.1096 +            private ProxyMethod(Method m, 
248.1097 +                String methodName, Class[] parameterTypes, 
248.1098 +                Class returnType, Class[] exceptionTypes, 
248.1099 +                Class fromClass
248.1100 +            ) {
248.1101 +                this.method = m;
248.1102 +                this.methodName = methodName;
248.1103 +                this.parameterTypes = parameterTypes;
248.1104 +                this.returnType = returnType;
248.1105 +                this.exceptionTypes = exceptionTypes;
248.1106 +                this.fromClass = fromClass;
248.1107 +                this.methodFieldName = "m" + proxyMethodCount++;
248.1108 +            }
248.1109 +
248.1110 +        }
248.1111 +
248.1112 +        /*
248.1113 +         * ==================== General Utility Methods ====================
248.1114 +         */
248.1115 +        /**
248.1116 +         * Convert a fully qualified class name that uses '.' as the package
248.1117 +         * separator, the external representation used by the Java language and
248.1118 +         * APIs, to a fully qualified class name that uses '/' as the package
248.1119 +         * separator, the representation used in the class file format (see JVMS
248.1120 +         * section 4.2).
248.1121 +         */
248.1122 +        private static String dotToSlash(String name) {
248.1123 +            return name.replace('.', '/');
248.1124 +        }
248.1125 +
248.1126 +        /**
248.1127 +         * Return the list of "parameter descriptor" strings enclosed in
248.1128 +         * parentheses corresponding to the given parameter types (in other
248.1129 +         * words, a method descriptor without a return descriptor). This string
248.1130 +         * is useful for constructing string keys for methods without regard to
248.1131 +         * their return type.
248.1132 +         */
248.1133 +        private static String getParameterDescriptors(Class[] parameterTypes) {
248.1134 +            StringBuilder desc = new StringBuilder("(");
248.1135 +            for (int i = 0; i < parameterTypes.length; i++) {
248.1136 +                desc.append(getFieldType(parameterTypes[i]));
248.1137 +            }
248.1138 +            desc.append(')');
248.1139 +            return desc.toString();
248.1140 +        }
248.1141 +
248.1142 +        /**
248.1143 +         * Return the "field type" string for the given type, appropriate for a
248.1144 +         * field descriptor, a parameter descriptor, or a return descriptor
248.1145 +         * other than "void". See JVMS section 4.3.2.
248.1146 +         */
248.1147 +        private static String getFieldType(Class type) {
248.1148 +            if (type.isPrimitive()) {
248.1149 +                return PrimitiveTypeInfo.get(type).baseTypeString;
248.1150 +            } else if (type.isArray()) {
248.1151 +                /*
248.1152 +                 * According to JLS 20.3.2, the getName() method on Class does
248.1153 +                 * return the VM type descriptor format for array classes (only);
248.1154 +                 * using that should be quicker than the otherwise obvious code:
248.1155 +                 *
248.1156 +                 *     return "[" + getTypeDescriptor(type.getComponentType());
248.1157 +                 */
248.1158 +                return type.getName().replace('.', '/');
248.1159 +            } else {
248.1160 +                return "L" + dotToSlash(type.getName()) + ";";
248.1161 +            }
248.1162 +        }
248.1163 +
248.1164 +        /**
248.1165 +         * Returns a human-readable string representing the signature of a
248.1166 +         * method with the given name and parameter types.
248.1167 +         */
248.1168 +        private static String getFriendlyMethodSignature(String name,
248.1169 +            Class[] parameterTypes) {
248.1170 +            StringBuilder sig = new StringBuilder(name);
248.1171 +            sig.append('(');
248.1172 +            for (int i = 0; i < parameterTypes.length; i++) {
248.1173 +                if (i > 0) {
248.1174 +                    sig.append(',');
248.1175 +                }
248.1176 +                Class parameterType = parameterTypes[i];
248.1177 +                int dimensions = 0;
248.1178 +                while (parameterType.isArray()) {
248.1179 +                    parameterType = parameterType.getComponentType();
248.1180 +                    dimensions++;
248.1181 +                }
248.1182 +                sig.append(parameterType.getName());
248.1183 +                while (dimensions-- > 0) {
248.1184 +                    sig.append("[]");
248.1185 +                }
248.1186 +            }
248.1187 +            sig.append(')');
248.1188 +            return sig.toString();
248.1189 +        }
248.1190 +
248.1191 +        /**
248.1192 +         * Add to the given list all of the types in the "from" array that are
248.1193 +         * not already contained in the list and are assignable to at least one
248.1194 +         * of the types in the "with" array.
248.1195 +         *
248.1196 +         * This method is useful for computing the greatest common set of
248.1197 +         * declared exceptions from duplicate methods inherited from different
248.1198 +         * interfaces.
248.1199 +         */
248.1200 +        private static void collectCompatibleTypes(Class<?>[] from,
248.1201 +            Class<?>[] with,
248.1202 +            List<Class<?>> list) {
248.1203 +            for (int i = 0; i < from.length; i++) {
248.1204 +                if (!list.contains(from[i])) {
248.1205 +                    for (int j = 0; j < with.length; j++) {
248.1206 +                        if (with[j].isAssignableFrom(from[i])) {
248.1207 +                            list.add(from[i]);
248.1208 +                            break;
248.1209 +                        }
248.1210 +                    }
248.1211 +                }
248.1212 +            }
248.1213 +        }
248.1214 +
248.1215 +
248.1216 +        /**
248.1217 +         * A PrimitiveTypeInfo object contains assorted information about a
248.1218 +         * primitive type in its public fields. The struct for a particular
248.1219 +         * primitive type can be obtained using the static "get" method.
248.1220 +         */
248.1221 +        private static class PrimitiveTypeInfo {
248.1222 +
248.1223 +            /**
248.1224 +             * "base type" used in various descriptors (see JVMS section 4.3.2)
248.1225 +             */
248.1226 +            public String baseTypeString;
248.1227 +
248.1228 +            /**
248.1229 +             * name of corresponding wrapper class
248.1230 +             */
248.1231 +            public String wrapperClassName;
248.1232 +
248.1233 +            /**
248.1234 +             * method descriptor for wrapper class "valueOf" factory method
248.1235 +             */
248.1236 +            public String wrapperValueOfDesc;
248.1237 +
248.1238 +            /**
248.1239 +             * name of wrapper class method for retrieving primitive value
248.1240 +             */
248.1241 +            public String unwrapMethodName;
248.1242 +
248.1243 +            /**
248.1244 +             * descriptor of same method
248.1245 +             */
248.1246 +            public String unwrapMethodDesc;
248.1247 +
248.1248 +            private static Map<Class, PrimitiveTypeInfo> table
248.1249 +                = new HashMap<Class, PrimitiveTypeInfo>();
248.1250 +
248.1251 +            static {
248.1252 +                add(byte.class, Byte.class);
248.1253 +                add(char.class, Character.class);
248.1254 +                add(double.class, Double.class);
248.1255 +                add(float.class, Float.class);
248.1256 +                add(int.class, Integer.class);
248.1257 +                add(long.class, Long.class);
248.1258 +                add(short.class, Short.class);
248.1259 +                add(boolean.class, Boolean.class);
248.1260 +            }
248.1261 +
248.1262 +            private static void add(Class primitiveClass, Class wrapperClass) {
248.1263 +                table.put(primitiveClass,
248.1264 +                    new PrimitiveTypeInfo(primitiveClass, wrapperClass));
248.1265 +            }
248.1266 +
248.1267 +            private PrimitiveTypeInfo(Class primitiveClass, Class wrapperClass) {
248.1268 +                assert primitiveClass.isPrimitive();
248.1269 +
248.1270 +                baseTypeString
248.1271 +                    = Array.newInstance(primitiveClass, 0)
248.1272 +                    .getClass().getName().substring(1);
248.1273 +                wrapperClassName = dotToSlash(wrapperClass.getName());
248.1274 +                wrapperValueOfDesc
248.1275 +                    = "(" + baseTypeString + ")L" + wrapperClassName + ";";
248.1276 +                unwrapMethodName = primitiveClass.getName() + "Value";
248.1277 +                unwrapMethodDesc = "()" + baseTypeString;
248.1278 +            }
248.1279 +
248.1280 +            public static PrimitiveTypeInfo get(Class cl) {
248.1281 +                return table.get(cl);
248.1282 +            }
248.1283 +        }
248.1284 +
248.1285 +        /**
248.1286 +         * A ConstantPool object represents the constant pool of a class file
248.1287 +         * being generated. This representation of a constant pool is designed
248.1288 +         * specifically for use by ProxyGenerator; in particular, it assumes
248.1289 +         * that constant pool entries will not need to be resorted (for example,
248.1290 +         * by their type, as the Java compiler does), so that the final index
248.1291 +         * value can be assigned and used when an entry is first created.
248.1292 +         *
248.1293 +         * Note that new entries cannot be created after the constant pool has
248.1294 +         * been written to a class file. To prevent such logic errors, a
248.1295 +         * ConstantPool instance can be marked "read only", so that further
248.1296 +         * attempts to add new entries will fail with a runtime exception.
248.1297 +         *
248.1298 +         * See JVMS section 4.4 for more information about the constant pool of
248.1299 +         * a class file.
248.1300 +         */
248.1301 +        private static class ConstantPool {
248.1302 +
248.1303 +            /**
248.1304 +             * list of constant pool entries, in constant pool index order.
248.1305 +             *
248.1306 +             * This list is used when writing the constant pool to a stream and
248.1307 +             * for assigning the next index value. Note that element 0 of this
248.1308 +             * list corresponds to constant pool index 1.
248.1309 +             */
248.1310 +            private List<Entry> pool = new ArrayList<Entry>(32);
248.1311 +
248.1312 +            /**
248.1313 +             * maps constant pool data of all types to constant pool indexes.
248.1314 +             *
248.1315 +             * This map is used to look up the index of an existing entry for
248.1316 +             * values of all types.
248.1317 +             */
248.1318 +            private Map<Object, Short> map = new HashMap<Object, Short>(16);
248.1319 +
248.1320 +            /**
248.1321 +             * true if no new constant pool entries may be added
248.1322 +             */
248.1323 +            private boolean readOnly = false;
248.1324 +
248.1325 +            /**
248.1326 +             * Get or assign the index for a CONSTANT_Utf8 entry.
248.1327 +             */
248.1328 +            public short getUtf8(String s) {
248.1329 +                if (s == null) {
248.1330 +                    throw new NullPointerException();
248.1331 +                }
248.1332 +                return getValue(s);
248.1333 +            }
248.1334 +
248.1335 +            /**
248.1336 +             * Get or assign the index for a CONSTANT_Integer entry.
248.1337 +             */
248.1338 +            public short getInteger(int i) {
248.1339 +                return getValue(new Integer(i));
248.1340 +            }
248.1341 +
248.1342 +            /**
248.1343 +             * Get or assign the index for a CONSTANT_Float entry.
248.1344 +             */
248.1345 +            public short getFloat(float f) {
248.1346 +                return getValue(new Float(f));
248.1347 +            }
248.1348 +
248.1349 +            /**
248.1350 +             * Get or assign the index for a CONSTANT_Class entry.
248.1351 +             */
248.1352 +            public short getClass(String name) {
248.1353 +                short utf8Index = getUtf8(name);
248.1354 +                return getIndirect(new IndirectEntry(
248.1355 +                    CONSTANT_CLASS, utf8Index));
248.1356 +            }
248.1357 +
248.1358 +            /**
248.1359 +             * Get or assign the index for a CONSTANT_String entry.
248.1360 +             */
248.1361 +            public short getString(String s) {
248.1362 +                short utf8Index = getUtf8(s);
248.1363 +                return getIndirect(new IndirectEntry(
248.1364 +                    CONSTANT_STRING, utf8Index));
248.1365 +            }
248.1366 +
248.1367 +            /**
248.1368 +             * Get or assign the index for a CONSTANT_FieldRef entry.
248.1369 +             */
248.1370 +            public short getFieldRef(String className,
248.1371 +                String name, String descriptor) {
248.1372 +                short classIndex = getClass(className);
248.1373 +                short nameAndTypeIndex = getNameAndType(name, descriptor);
248.1374 +                return getIndirect(new IndirectEntry(
248.1375 +                    CONSTANT_FIELD, classIndex, nameAndTypeIndex));
248.1376 +            }
248.1377 +
248.1378 +            /**
248.1379 +             * Get or assign the index for a CONSTANT_MethodRef entry.
248.1380 +             */
248.1381 +            public short getMethodRef(String className,
248.1382 +                String name, String descriptor) {
248.1383 +                short classIndex = getClass(className);
248.1384 +                short nameAndTypeIndex = getNameAndType(name, descriptor);
248.1385 +                return getIndirect(new IndirectEntry(
248.1386 +                    CONSTANT_METHOD, classIndex, nameAndTypeIndex));
248.1387 +            }
248.1388 +
248.1389 +            /**
248.1390 +             * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
248.1391 +             */
248.1392 +            public short getInterfaceMethodRef(String className, String name,
248.1393 +                String descriptor) {
248.1394 +                short classIndex = getClass(className);
248.1395 +                short nameAndTypeIndex = getNameAndType(name, descriptor);
248.1396 +                return getIndirect(new IndirectEntry(
248.1397 +                    CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
248.1398 +            }
248.1399 +
248.1400 +            /**
248.1401 +             * Get or assign the index for a CONSTANT_NameAndType entry.
248.1402 +             */
248.1403 +            public short getNameAndType(String name, String descriptor) {
248.1404 +                short nameIndex = getUtf8(name);
248.1405 +                short descriptorIndex = getUtf8(descriptor);
248.1406 +                return getIndirect(new IndirectEntry(
248.1407 +                    CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
248.1408 +            }
248.1409 +
248.1410 +            /**
248.1411 +             * Set this ConstantPool instance to be "read only".
248.1412 +             *
248.1413 +             * After this method has been called, further requests to get an
248.1414 +             * index for a non-existent entry will cause an InternalError to be
248.1415 +             * thrown instead of creating of the entry.
248.1416 +             */
248.1417 +            public void setReadOnly() {
248.1418 +                readOnly = true;
248.1419 +            }
248.1420 +
248.1421 +            /**
248.1422 +             * Write this constant pool to a stream as part of the class file
248.1423 +             * format.
248.1424 +             *
248.1425 +             * This consists of writing the "constant_pool_count" and
248.1426 +             * "constant_pool[]" items of the "ClassFile" structure, as
248.1427 +             * described in JVMS section 4.1.
248.1428 +             */
248.1429 +            public void write(OutputStream out) throws IOException {
248.1430 +                DataOutputStream dataOut = new DataOutputStream(out);
248.1431 +
248.1432 +                // constant_pool_count: number of entries plus one
248.1433 +                dataOut.writeShort(pool.size() + 1);
248.1434 +
248.1435 +                for (Entry e : pool) {
248.1436 +                    e.write(dataOut);
248.1437 +                }
248.1438 +            }
248.1439 +
248.1440 +            /**
248.1441 +             * Add a new constant pool entry and return its index.
248.1442 +             */
248.1443 +            private short addEntry(Entry entry) {
248.1444 +                pool.add(entry);
248.1445 +                /*
248.1446 +                 * Note that this way of determining the index of the
248.1447 +                 * added entry is wrong if this pool supports
248.1448 +                 * CONSTANT_Long or CONSTANT_Double entries.
248.1449 +                 */
248.1450 +                if (pool.size() >= 65535) {
248.1451 +                    throw new IllegalArgumentException(
248.1452 +                        "constant pool size limit exceeded");
248.1453 +                }
248.1454 +                return (short) pool.size();
248.1455 +            }
248.1456 +
248.1457 +            /**
248.1458 +             * Get or assign the index for an entry of a type that contains a
248.1459 +             * direct value. The type of the given object determines the type of
248.1460 +             * the desired entry as follows:
248.1461 +             *
248.1462 +             * java.lang.String CONSTANT_Utf8 java.lang.Integer CONSTANT_Integer
248.1463 +             * java.lang.Float CONSTANT_Float java.lang.Long CONSTANT_Long
248.1464 +             * java.lang.Double CONSTANT_DOUBLE
248.1465 +             */
248.1466 +            private short getValue(Object key) {
248.1467 +                Short index = map.get(key);
248.1468 +                if (index != null) {
248.1469 +                    return index.shortValue();
248.1470 +                } else {
248.1471 +                    if (readOnly) {
248.1472 +                        throw new InternalError(
248.1473 +                            "late constant pool addition: " + key);
248.1474 +                    }
248.1475 +                    short i = addEntry(new ValueEntry(key));
248.1476 +                    map.put(key, new Short(i));
248.1477 +                    return i;
248.1478 +                }
248.1479 +            }
248.1480 +
248.1481 +            /**
248.1482 +             * Get or assign the index for an entry of a type that contains
248.1483 +             * references to other constant pool entries.
248.1484 +             */
248.1485 +            private short getIndirect(IndirectEntry e) {
248.1486 +                Short index = map.get(e);
248.1487 +                if (index != null) {
248.1488 +                    return index.shortValue();
248.1489 +                } else {
248.1490 +                    if (readOnly) {
248.1491 +                        throw new InternalError("late constant pool addition");
248.1492 +                    }
248.1493 +                    short i = addEntry(e);
248.1494 +                    map.put(e, new Short(i));
248.1495 +                    return i;
248.1496 +                }
248.1497 +            }
248.1498 +
248.1499 +            /**
248.1500 +             * Entry is the abstact superclass of all constant pool entry types
248.1501 +             * that can be stored in the "pool" list; its purpose is to define a
248.1502 +             * common method for writing constant pool entries to a class file.
248.1503 +             */
248.1504 +            private static abstract class Entry {
248.1505 +
248.1506 +                public abstract void write(DataOutputStream out)
248.1507 +                    throws IOException;
248.1508 +            }
248.1509 +
248.1510 +            /**
248.1511 +             * ValueEntry represents a constant pool entry of a type that
248.1512 +             * contains a direct value (see the comments for the "getValue"
248.1513 +             * method for a list of such types).
248.1514 +             *
248.1515 +             * ValueEntry objects are not used as keys for their entries in the
248.1516 +             * Map "map", so no useful hashCode or equals methods are defined.
248.1517 +             */
248.1518 +            private static class ValueEntry extends Entry {
248.1519 +
248.1520 +                private Object value;
248.1521 +
248.1522 +                public ValueEntry(Object value) {
248.1523 +                    this.value = value;
248.1524 +                }
248.1525 +
248.1526 +                public void write(DataOutputStream out) throws IOException {
248.1527 +                    if (value instanceof String) {
248.1528 +                        out.writeByte(CONSTANT_UTF8);
248.1529 +                        out.writeUTF((String) value);
248.1530 +                    } else if (value instanceof Integer) {
248.1531 +                        out.writeByte(CONSTANT_INTEGER);
248.1532 +                        out.writeInt(((Integer) value).intValue());
248.1533 +                    } else if (value instanceof Float) {
248.1534 +                        out.writeByte(CONSTANT_FLOAT);
248.1535 +                        out.writeFloat(((Float) value).floatValue());
248.1536 +                    } else if (value instanceof Long) {
248.1537 +                        out.writeByte(CONSTANT_LONG);
248.1538 +                        out.writeLong(((Long) value).longValue());
248.1539 +                    } else if (value instanceof Double) {
248.1540 +                        out.writeDouble(CONSTANT_DOUBLE);
248.1541 +                        out.writeDouble(((Double) value).doubleValue());
248.1542 +                    } else {
248.1543 +                        throw new InternalError("bogus value entry: " + value);
248.1544 +                    }
248.1545 +                }
248.1546 +            }
248.1547 +
248.1548 +            /**
248.1549 +             * IndirectEntry represents a constant pool entry of a type that
248.1550 +             * references other constant pool entries, i.e., the following
248.1551 +             * types:
248.1552 +             *
248.1553 +             * CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
248.1554 +             * CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
248.1555 +             * CONSTANT_NameAndType.
248.1556 +             *
248.1557 +             * Each of these entry types contains either one or two indexes of
248.1558 +             * other constant pool entries.
248.1559 +             *
248.1560 +             * IndirectEntry objects are used as the keys for their entries in
248.1561 +             * the Map "map", so the hashCode and equals methods are overridden
248.1562 +             * to allow matching.
248.1563 +             */
248.1564 +            private static class IndirectEntry extends Entry {
248.1565 +
248.1566 +                private int tag;
248.1567 +                private short index0;
248.1568 +                private short index1;
248.1569 +
248.1570 +                /**
248.1571 +                 * Construct an IndirectEntry for a constant pool entry type
248.1572 +                 * that contains one index of another entry.
248.1573 +                 */
248.1574 +                public IndirectEntry(int tag, short index) {
248.1575 +                    this.tag = tag;
248.1576 +                    this.index0 = index;
248.1577 +                    this.index1 = 0;
248.1578 +                }
248.1579 +
248.1580 +                /**
248.1581 +                 * Construct an IndirectEntry for a constant pool entry type
248.1582 +                 * that contains two indexes for other entries.
248.1583 +                 */
248.1584 +                public IndirectEntry(int tag, short index0, short index1) {
248.1585 +                    this.tag = tag;
248.1586 +                    this.index0 = index0;
248.1587 +                    this.index1 = index1;
248.1588 +                }
248.1589 +
248.1590 +                public void write(DataOutputStream out) throws IOException {
248.1591 +                    out.writeByte(tag);
248.1592 +                    out.writeShort(index0);
248.1593 +                    /*
248.1594 +                     * If this entry type contains two indexes, write
248.1595 +                     * out the second, too.
248.1596 +                     */
248.1597 +                    if (tag == CONSTANT_FIELD
248.1598 +                        || tag == CONSTANT_METHOD
248.1599 +                        || tag == CONSTANT_INTERFACEMETHOD
248.1600 +                        || tag == CONSTANT_NAMEANDTYPE) {
248.1601 +                        out.writeShort(index1);
248.1602 +                    }
248.1603 +                }
248.1604 +
248.1605 +                public int hashCode() {
248.1606 +                    return tag + index0 + index1;
248.1607 +                }
248.1608 +
248.1609 +                public boolean equals(Object obj) {
248.1610 +                    if (obj instanceof IndirectEntry) {
248.1611 +                        IndirectEntry other = (IndirectEntry) obj;
248.1612 +                        if (tag == other.tag
248.1613 +                            && index0 == other.index0 && index1 == other.index1) {
248.1614 +                            return true;
248.1615 +                        }
248.1616 +                    }
248.1617 +                    return false;
248.1618 +                }
248.1619 +            }
248.1620 +        }
248.1621 +    }
248.1622 +    
248.1623 +}
   249.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ReaderTest.java	Tue Apr 29 15:25:58 2014 +0200
   249.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ReaderTest.java	Wed Apr 30 15:04:10 2014 +0200
   249.3 @@ -18,8 +18,10 @@
   249.4  package org.apidesign.bck2brwsr.compact.tck;
   249.5  
   249.6  import java.io.ByteArrayInputStream;
   249.7 +import java.io.ByteArrayOutputStream;
   249.8  import java.io.IOException;
   249.9  import java.io.InputStreamReader;
  249.10 +import java.io.OutputStreamWriter;
  249.11  import java.io.UnsupportedEncodingException;
  249.12  import java.util.Arrays;
  249.13  import org.apidesign.bck2brwsr.vmtest.Compare;
  249.14 @@ -40,7 +42,10 @@
  249.15          };
  249.16          ByteArrayInputStream is = new ByteArrayInputStream(arr);
  249.17          InputStreamReader r = new InputStreamReader(is, "UTF-8");
  249.18 -        
  249.19 +        return readReader(r);        
  249.20 +    }
  249.21 +
  249.22 +    private String readReader(InputStreamReader r) throws IOException {
  249.23          StringBuilder sb = new StringBuilder();
  249.24          for (;;) {
  249.25              int ch = r.read();
  249.26 @@ -52,7 +57,19 @@
  249.27          return sb.toString().toString();
  249.28      }
  249.29      @Compare public String stringToBytes() throws UnsupportedEncodingException {
  249.30 -        return Arrays.toString("\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("UTF-8"));
  249.31 +        return Arrays.toString(YellowHorse.getBytes("UTF-8"));
  249.32 +    }
  249.33 +    private final String YellowHorse = "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148";
  249.34 +    
  249.35 +    @Compare public String readAndWrite() throws Exception {
  249.36 +        ByteArrayOutputStream arr = new ByteArrayOutputStream();
  249.37 +        OutputStreamWriter w = new OutputStreamWriter(arr);
  249.38 +        w.write(YellowHorse);
  249.39 +        w.close();
  249.40 +        
  249.41 +        ByteArrayInputStream is = new ByteArrayInputStream(arr.toByteArray());
  249.42 +        InputStreamReader r = new InputStreamReader(is, "UTF-8");
  249.43 +        return readReader(r);
  249.44      }
  249.45      
  249.46      @Factory public static Object[] create() {
   250.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   250.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/AtomicTest.java	Wed Apr 30 15:04:10 2014 +0200
   250.3 @@ -0,0 +1,54 @@
   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.tck;
  250.22 +
  250.23 +import java.util.concurrent.atomic.AtomicBoolean;
  250.24 +import java.util.concurrent.atomic.AtomicInteger;
  250.25 +import java.util.concurrent.atomic.AtomicReference;
  250.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
  250.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  250.28 +import org.testng.annotations.Factory;
  250.29 +
  250.30 +/**
  250.31 + *
  250.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  250.33 + */
  250.34 +public class AtomicTest {
  250.35 +    @Compare public boolean atomicBoolean() {
  250.36 +        AtomicBoolean ab = new AtomicBoolean();
  250.37 +        ab.set(true);
  250.38 +        return ab.compareAndSet(true, false);
  250.39 +    }
  250.40 +
  250.41 +    @Compare public int atomicInt() {
  250.42 +        AtomicInteger ab = new AtomicInteger();
  250.43 +        ab.set(30);
  250.44 +        assert ab.compareAndSet(30, 10);
  250.45 +        return ab.get();
  250.46 +    }
  250.47 +    
  250.48 +    @Compare public String atomicRef() {
  250.49 +        AtomicReference<String> ar = new AtomicReference<String>("Ahoj");
  250.50 +        assert ar.compareAndSet("Ahoj", "Hello");
  250.51 +        return ar.getAndSet("Other");
  250.52 +    }
  250.53 +    
  250.54 +    @Factory public static Object[] create() {
  250.55 +        return VMTest.create(AtomicTest.class);
  250.56 +    }
  250.57 +}
   251.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   251.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CharacterTest.java	Wed Apr 30 15:04:10 2014 +0200
   251.3 @@ -0,0 +1,61 @@
   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.tck;
  251.22 +
  251.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  251.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  251.25 +import org.testng.annotations.Factory;
  251.26 +
  251.27 +/**
  251.28 + *
  251.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  251.30 + */
  251.31 +public class CharacterTest {
  251.32 +    @Compare public boolean dolarJavaStart() {
  251.33 +        return Character.isJavaIdentifierStart('$');
  251.34 +    }
  251.35 +
  251.36 +    @Compare public boolean dolarJavaPart() {
  251.37 +        return Character.isJavaIdentifierPart('$');
  251.38 +    }
  251.39 +
  251.40 +    @Compare public boolean numberJavaStart() {
  251.41 +        return Character.isJavaIdentifierStart('3');
  251.42 +    }
  251.43 +
  251.44 +    @Compare public boolean numberJavaPart() {
  251.45 +        return Character.isJavaIdentifierPart('3');
  251.46 +    }
  251.47 +
  251.48 +    @Compare public String testWhiteSpaces() {
  251.49 +        StringBuilder sb = new StringBuilder();
  251.50 +        for (int i = 1; i < 128; i++) {
  251.51 +            char ch = (char)i;
  251.52 +            if (Character.isWhitespace(ch)) {
  251.53 +                sb.append(i).append(",");
  251.54 +            }
  251.55 +        }
  251.56 +        return sb.toString();
  251.57 +    }
  251.58 +    
  251.59 +    @Factory
  251.60 +    public static Object[] create() {
  251.61 +        return VMTest.create(CharacterTest.class);
  251.62 +    }
  251.63 +
  251.64 +}
   252.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   252.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ClassLoaderTest.java	Wed Apr 30 15:04:10 2014 +0200
   252.3 @@ -0,0 +1,41 @@
   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.tck;
  252.22 +
  252.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  252.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  252.25 +import org.testng.annotations.Factory;
  252.26 +
  252.27 +/**
  252.28 + *
  252.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  252.30 + */
  252.31 +public class ClassLoaderTest {
  252.32 +    @Compare public Object unknownResource() {
  252.33 +        return ClassLoader.getSystemResource("really/unknown/resource.txt");
  252.34 +    }
  252.35 +    
  252.36 +    @Compare public boolean indenpotentSetOfClassloaderIsOK() {
  252.37 +        Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
  252.38 +        return Thread.currentThread().getContextClassLoader() == ClassLoader.getSystemClassLoader();
  252.39 +    }
  252.40 +
  252.41 +    @Factory public static Object[] create() {
  252.42 +        return VMTest.create(ClassLoaderTest.class);
  252.43 +    }
  252.44 +}
   253.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Tue Apr 29 15:25:58 2014 +0200
   253.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Wed Apr 30 15:04:10 2014 +0200
   253.3 @@ -30,6 +30,16 @@
   253.4          return "Ahoj".hashCode();
   253.5      }
   253.6      
   253.7 +    @Compare public boolean hashOfIntegerDifferentToOwnHash() {
   253.8 +        Integer i = 120;
   253.9 +        return System.identityHashCode(i) != i.hashCode();
  253.10 +    }
  253.11 +
  253.12 +    @Compare public int hashOfObjectSameAsOwnHash() {
  253.13 +        Object o = new Object();
  253.14 +        return System.identityHashCode(o) - o.hashCode();
  253.15 +    }
  253.16 +    
  253.17      @Compare public int hashRemainsYieldsZero() {
  253.18          Object o = new Object();
  253.19          return o.hashCode() - o.hashCode();
   254.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Tue Apr 29 15:25:58 2014 +0200
   254.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Wed Apr 30 15:04:10 2014 +0200
   254.3 @@ -19,7 +19,9 @@
   254.4  
   254.5  import java.io.UnsupportedEncodingException;
   254.6  import java.net.MalformedURLException;
   254.7 +import java.net.URISyntaxException;
   254.8  import java.net.URL;
   254.9 +import java.util.Locale;
  254.10  import org.apidesign.bck2brwsr.vmtest.Compare;
  254.11  import org.apidesign.bck2brwsr.vmtest.VMTest;
  254.12  import org.testng.annotations.Factory;
  254.13 @@ -47,6 +49,14 @@
  254.14          return "Ahoj".equals(null);
  254.15      }
  254.16      
  254.17 +    @Compare public boolean internIsSame() {
  254.18 +        return new String("Ahoj").intern() == another();
  254.19 +    }
  254.20 +    
  254.21 +    private static String another() {
  254.22 +        return new String("Ahoj").intern();
  254.23 +    }
  254.24 +    
  254.25      @Compare public int highByteLenght() {
  254.26          byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
  254.27          return new String(arr, 0).length();
  254.28 @@ -63,6 +73,10 @@
  254.29      @Compare public static Object compareURLs() throws MalformedURLException {
  254.30          return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
  254.31      }
  254.32 +
  254.33 +    @Compare public static Object compareURLsViaURIs() throws Exception {
  254.34 +        return new URL("http://apidesign.org:8080/wiki/").toURI().toString();
  254.35 +    }
  254.36      
  254.37      @Compare public String deleteLastTwoCharacters() {
  254.38          StringBuilder sb = new StringBuilder();
  254.39 @@ -161,7 +175,28 @@
  254.40          assert res.equals("ba") : "Expecting ba: " + res;
  254.41          return res;
  254.42      }
  254.43 +    
  254.44 +    @Compare public String localeUS() {
  254.45 +        return Locale.US.toString();
  254.46 +    }
  254.47 +    
  254.48 +    @Compare public String localeFrench() {
  254.49 +        return Locale.FRENCH.toString();
  254.50 +    }
  254.51 +    
  254.52 +    
  254.53 +    @Compare public String formatSimple() {
  254.54 +        return String.format((Locale)null, "Hello %s!", "World");
  254.55 +    }
  254.56  
  254.57 +    @Compare public String replaceWithItself() {
  254.58 +        return "org.apidesign.bck2brwsr.core.JavaScriptBody".replace(".", "\\.");
  254.59 +    }
  254.60 +    
  254.61 +    @Compare public boolean matchWithComplicatedRegExp() {
  254.62 +        return "Activates this model instance.".matches("(?sm).*^\\s*@deprecated( |$).*");
  254.63 +    }
  254.64 +    
  254.65      @Factory
  254.66      public static Object[] create() {
  254.67          return VMTest.create(CompareStringsTest.class);
   255.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   255.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ConcurrentTest.java	Wed Apr 30 15:04:10 2014 +0200
   255.3 @@ -0,0 +1,40 @@
   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.tck;
  255.22 +
  255.23 +import java.util.concurrent.ConcurrentHashMap;
  255.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  255.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  255.26 +import org.testng.annotations.Factory;
  255.27 +
  255.28 +/**
  255.29 + *
  255.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  255.31 + */
  255.32 +public class ConcurrentTest {
  255.33 +    @Compare public String mapIfAbsent() {
  255.34 +        ConcurrentHashMap<String,String> m = new ConcurrentHashMap<>();
  255.35 +        m.putIfAbsent("Ahoj", "Jardo");
  255.36 +        m.putIfAbsent("Ahoj", "Dardo");
  255.37 +        return m.get("Ahoj");
  255.38 +    }
  255.39 +    
  255.40 +    @Factory public static Object[] create() {
  255.41 +        return VMTest.create(ConcurrentTest.class);
  255.42 +    }
  255.43 +}
   256.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java	Tue Apr 29 15:25:58 2014 +0200
   256.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java	Wed Apr 30 15:04:10 2014 +0200
   256.3 @@ -26,6 +26,14 @@
   256.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
   256.5   */
   256.6  public class DoubleTest {
   256.7 +    @Compare public boolean parsedDoubleIsDouble() {
   256.8 +        return Double.valueOf("1.1") instanceof Double;
   256.9 +    }
  256.10 +
  256.11 +    @Compare public boolean parsedFloatIsFloat() {
  256.12 +        return Float.valueOf("1.1") instanceof Float;
  256.13 +    }
  256.14 +    
  256.15      @Compare public String integerToString() {
  256.16          return toStr(1);
  256.17      }
   257.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   257.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/EnumsTest.java	Wed Apr 30 15:04:10 2014 +0200
   257.3 @@ -0,0 +1,76 @@
   257.4 +/**
   257.5 + * Back 2 Browser Bytecode Translator
   257.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   257.7 + *
   257.8 + * This program is free software: you can redistribute it and/or modify
   257.9 + * it under the terms of the GNU General Public License as published by
  257.10 + * the Free Software Foundation, version 2 of the License.
  257.11 + *
  257.12 + * This program is distributed in the hope that it will be useful,
  257.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  257.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  257.15 + * GNU General Public License for more details.
  257.16 + *
  257.17 + * You should have received a copy of the GNU General Public License
  257.18 + * along with this program. Look for COPYING file in the top folder.
  257.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  257.20 + */
  257.21 +package org.apidesign.bck2brwsr.tck;
  257.22 +
  257.23 +import java.util.EnumMap;
  257.24 +import java.util.EnumSet;
  257.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
  257.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  257.27 +import org.testng.annotations.Factory;
  257.28 +
  257.29 +/**
  257.30 + *
  257.31 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  257.32 + */
  257.33 +public class EnumsTest {
  257.34 +    enum Color {
  257.35 +        B, W;
  257.36 +    }
  257.37 +
  257.38 +    @Compare public String enumSet() {
  257.39 +        try { throw new Exception(); } catch (Exception ex) {}
  257.40 +        EnumSet<Color> c = EnumSet.allOf(Color.class);
  257.41 +        return c.toString();
  257.42 +    }
  257.43 +
  257.44 +    @Compare public String enumSetOneByOne() {
  257.45 +        EnumSet<Color> c = EnumSet.of(Color.B, Color.W);
  257.46 +        return c.toString();
  257.47 +    }
  257.48 +
  257.49 +    @Compare public boolean enumFirstContains() {
  257.50 +        EnumSet<Color> c = EnumSet.of(Color.B);
  257.51 +        return c.contains(Color.B);
  257.52 +    }
  257.53 +
  257.54 +    @Compare public boolean enumFirstDoesNotContains() {
  257.55 +        EnumSet<Color> c = EnumSet.of(Color.B);
  257.56 +        return c.contains(Color.W);
  257.57 +    }
  257.58 +
  257.59 +    @Compare public boolean enumSndContains() {
  257.60 +        EnumSet<Color> c = EnumSet.of(Color.W);
  257.61 +        return c.contains(Color.W);
  257.62 +    }
  257.63 +
  257.64 +    @Compare public boolean enumSecondDoesNotContains() {
  257.65 +        EnumSet<Color> c = EnumSet.of(Color.W);
  257.66 +        return c.contains(Color.B);
  257.67 +    }
  257.68 +
  257.69 +    @Compare public String enumMap() {
  257.70 +        EnumMap<Color,String> c = new EnumMap(Color.class);
  257.71 +        c.put(Color.B, "Black");
  257.72 +        c.put(Color.W, "White");
  257.73 +        return c.toString();
  257.74 +    }
  257.75 +    
  257.76 +    @Factory public static Object[] create() {
  257.77 +        return VMTest.create(EnumsTest.class);
  257.78 +    }
  257.79 +}
   258.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   258.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ExceptionsTest.java	Wed Apr 30 15:04:10 2014 +0200
   258.3 @@ -0,0 +1,68 @@
   258.4 +/**
   258.5 + * Back 2 Browser Bytecode Translator
   258.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   258.7 + *
   258.8 + * This program is free software: you can redistribute it and/or modify
   258.9 + * it under the terms of the GNU General Public License as published by
  258.10 + * the Free Software Foundation, version 2 of the License.
  258.11 + *
  258.12 + * This program is distributed in the hope that it will be useful,
  258.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  258.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  258.15 + * GNU General Public License for more details.
  258.16 + *
  258.17 + * You should have received a copy of the GNU General Public License
  258.18 + * along with this program. Look for COPYING file in the top folder.
  258.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  258.20 + */
  258.21 +package org.apidesign.bck2brwsr.tck;
  258.22 +
  258.23 +import java.io.ByteArrayOutputStream;
  258.24 +import java.io.PrintStream;
  258.25 +import java.io.PrintWriter;
  258.26 +import java.io.StringWriter;
  258.27 +import java.io.UnsupportedEncodingException;
  258.28 +import org.apidesign.bck2brwsr.vmtest.Compare;
  258.29 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  258.30 +import org.testng.annotations.Factory;
  258.31 +
  258.32 +/**
  258.33 + *
  258.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  258.35 + */
  258.36 +public class ExceptionsTest {
  258.37 +    @Compare public String firstLineIsTheSame() throws UnsupportedEncodingException {
  258.38 +        MyException ex = new MyException("Hello");
  258.39 +        ByteArrayOutputStream out = new ByteArrayOutputStream();
  258.40 +        PrintStream ps = new PrintStream(out);
  258.41 +        ex.printStackTrace(ps);
  258.42 +        ps.flush();
  258.43 +        
  258.44 +        String s = new String(out.toByteArray(), "UTF-8");
  258.45 +        int newLine = s.indexOf('\n');
  258.46 +        return s.substring(0, newLine);
  258.47 +    }
  258.48 +
  258.49 +    @Compare public String firstLineIsTheSameWithWriter() throws UnsupportedEncodingException {
  258.50 +        MyException ex = new MyException("Hello");
  258.51 +        StringWriter sw = new StringWriter();
  258.52 +        PrintWriter pw = new PrintWriter(sw);
  258.53 +        ex.printStackTrace(pw);
  258.54 +        pw.flush();
  258.55 +        
  258.56 +        String s = sw.toString();
  258.57 +        int newLine = s.indexOf('\n');
  258.58 +        return s.substring(0, newLine);
  258.59 +    }
  258.60 +    
  258.61 +    static class MyException extends Exception {
  258.62 +        public MyException(String message) {
  258.63 +            super(message);
  258.64 +        }
  258.65 +    }
  258.66 +    
  258.67 +    
  258.68 +    @Factory public static Object[] create() {
  258.69 +        return VMTest.create(ExceptionsTest.class);
  258.70 +    }
  258.71 +}
   259.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   259.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LoggerTest.java	Wed Apr 30 15:04:10 2014 +0200
   259.3 @@ -0,0 +1,43 @@
   259.4 +/**
   259.5 + * Back 2 Browser Bytecode Translator
   259.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   259.7 + *
   259.8 + * This program is free software: you can redistribute it and/or modify
   259.9 + * it under the terms of the GNU General Public License as published by
  259.10 + * the Free Software Foundation, version 2 of the License.
  259.11 + *
  259.12 + * This program is distributed in the hope that it will be useful,
  259.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  259.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  259.15 + * GNU General Public License for more details.
  259.16 + *
  259.17 + * You should have received a copy of the GNU General Public License
  259.18 + * along with this program. Look for COPYING file in the top folder.
  259.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  259.20 + */
  259.21 +package org.apidesign.bck2brwsr.tck;
  259.22 +
  259.23 +import java.util.logging.Logger;
  259.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  259.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  259.26 +import org.testng.annotations.Factory;
  259.27 +
  259.28 +/**
  259.29 + *
  259.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  259.31 + */
  259.32 +public class LoggerTest {
  259.33 +    @Compare public String parentLogger() {
  259.34 +        Logger lx = Logger.getLogger("x");
  259.35 +        assert lx != null;
  259.36 +        assert lx.getName().equals("x") : "Right name: " + lx.getName();
  259.37 +        Logger lxyz = Logger.getLogger("x.y.z");
  259.38 +        assert lxyz != null;
  259.39 +        assert lxyz.getName().equals("x.y.z") : "xyz name: " + lxyz.getName();
  259.40 +        return lxyz.getParent().getName();
  259.41 +    }
  259.42 +    
  259.43 +    @Factory public static Object[] create() {
  259.44 +        return VMTest.create(LoggerTest.class);
  259.45 +    }
  259.46 +}
   260.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Tue Apr 29 15:25:58 2014 +0200
   260.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Wed Apr 30 15:04:10 2014 +0200
   260.3 @@ -304,6 +304,14 @@
   260.4      @Compare public long shiftL3() {
   260.5          return shl(0x00fa37d7763e0ca1l, 45);
   260.6      }
   260.7 +    
   260.8 +    @Compare public long shiftL4() {
   260.9 +        return shl(0x00fa37d7763e0ca1l, 0);
  260.10 +    }
  260.11 +    
  260.12 +    @Compare public long shiftL5() {
  260.13 +        return shl(0x00fa37d7763e0ca1l, 70);
  260.14 +    }
  260.15  
  260.16      @Compare public long shiftR1() {
  260.17          return shr(0x00fa37d7763e0ca1l, 5);
  260.18 @@ -316,6 +324,14 @@
  260.19      @Compare public long shiftR3() {
  260.20          return shr(0x00fa37d7763e0ca1l, 45);
  260.21      }
  260.22 +    
  260.23 +    @Compare public long shiftR4() {
  260.24 +        return shr(0x00fa37d7763e0ca1l, 0);
  260.25 +    }
  260.26 +    
  260.27 +    @Compare public long shiftR5() {
  260.28 +        return shr(0x00fa37d7763e0ca1l, 70);
  260.29 +    }
  260.30  
  260.31      @Compare public long uShiftR1() {
  260.32          return ushr(0x00fa37d7763e0ca1l, 5);
  260.33 @@ -324,14 +340,30 @@
  260.34      @Compare public long uShiftR2() {
  260.35          return ushr(0x00fa37d7763e0ca1l, 45);
  260.36      }
  260.37 +    
  260.38 +    @Compare public long uShiftR3() {
  260.39 +        return ushr(0x00fa37d7763e0ca1l, 0);
  260.40 +    }
  260.41 +    
  260.42 +    @Compare public long uShiftR4() {
  260.43 +        return ushr(0x00fa37d7763e0ca1l, 70);
  260.44 +    }
  260.45  
  260.46 -    @Compare public long uShiftR3() {
  260.47 +    @Compare public long uShiftR5() {
  260.48          return ushr(0xf0fa37d7763e0ca1l, 5);
  260.49      }
  260.50  
  260.51 -    @Compare public long uShiftR4() {
  260.52 +    @Compare public long uShiftR6() {
  260.53          return ushr(0xf0fa37d7763e0ca1l, 45);
  260.54      }
  260.55 +    
  260.56 +    @Compare public long uShiftR7() {
  260.57 +        return ushr(0xf0fa37d7763e0ca1l, 0);
  260.58 +    }
  260.59 +    
  260.60 +    @Compare public long uShiftR8() {
  260.61 +        return ushr(0xf0fa37d7763e0ca1l, 70);
  260.62 +    }
  260.63  
  260.64      @Compare public long and1() {
  260.65          return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
   261.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   261.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/NotifyWaitTest.java	Wed Apr 30 15:04:10 2014 +0200
   261.3 @@ -0,0 +1,63 @@
   261.4 +/**
   261.5 + * Back 2 Browser Bytecode Translator
   261.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   261.7 + *
   261.8 + * This program is free software: you can redistribute it and/or modify
   261.9 + * it under the terms of the GNU General Public License as published by
  261.10 + * the Free Software Foundation, version 2 of the License.
  261.11 + *
  261.12 + * This program is distributed in the hope that it will be useful,
  261.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  261.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  261.15 + * GNU General Public License for more details.
  261.16 + *
  261.17 + * You should have received a copy of the GNU General Public License
  261.18 + * along with this program. Look for COPYING file in the top folder.
  261.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  261.20 + */
  261.21 +package org.apidesign.bck2brwsr.tck;
  261.22 +
  261.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  261.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  261.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  261.26 +import org.testng.annotations.Factory;
  261.27 +
  261.28 +/**
  261.29 + *
  261.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  261.31 + */
  261.32 +public class NotifyWaitTest {
  261.33 +    
  261.34 +
  261.35 +    @Compare public synchronized String canCallNotify() throws Exception {
  261.36 +        notify();
  261.37 +        return "OK";
  261.38 +    }
  261.39 +
  261.40 +    @Compare public synchronized String canCallNotifyAll() throws Exception {
  261.41 +        notifyAll();
  261.42 +        return "OK";
  261.43 +    }
  261.44 +    
  261.45 +    @BrwsrTest public synchronized String throwsInterruptedException() {
  261.46 +        try {
  261.47 +            wait();
  261.48 +            throw new IllegalStateException();
  261.49 +        } catch (InterruptedException ex) {
  261.50 +            return "OK";
  261.51 +        }
  261.52 +    }
  261.53 +
  261.54 +    @BrwsrTest public synchronized String waitMsThrowsInterruptedException() {
  261.55 +        try {
  261.56 +            wait(32);
  261.57 +            throw new IllegalStateException();
  261.58 +        } catch (InterruptedException ex) {
  261.59 +            return "OK";
  261.60 +        }
  261.61 +    }
  261.62 +    
  261.63 +    @Factory public static Object[] create() {
  261.64 +        return VMTest.create(NotifyWaitTest.class);
  261.65 +    }
  261.66 +}
   262.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   262.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ProxyTest.java	Wed Apr 30 15:04:10 2014 +0200
   262.3 @@ -0,0 +1,71 @@
   262.4 +/**
   262.5 + * Back 2 Browser Bytecode Translator
   262.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   262.7 + *
   262.8 + * This program is free software: you can redistribute it and/or modify
   262.9 + * it under the terms of the GNU General Public License as published by
  262.10 + * the Free Software Foundation, version 2 of the License.
  262.11 + *
  262.12 + * This program is distributed in the hope that it will be useful,
  262.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  262.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  262.15 + * GNU General Public License for more details.
  262.16 + *
  262.17 + * You should have received a copy of the GNU General Public License
  262.18 + * along with this program. Look for COPYING file in the top folder.
  262.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  262.20 + */
  262.21 +package org.apidesign.bck2brwsr.tck;
  262.22 +
  262.23 +import java.lang.reflect.InvocationHandler;
  262.24 +import java.lang.reflect.Method;
  262.25 +import java.lang.reflect.Proxy;
  262.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
  262.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  262.28 +import org.testng.annotations.Factory;
  262.29 +
  262.30 +/**
  262.31 + *
  262.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  262.33 + */
  262.34 +public class ProxyTest {
  262.35 +    @Compare public String generateAnnotation() throws Exception {
  262.36 +        class InvHandler implements InvocationHandler {
  262.37 +            @Override
  262.38 +            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  262.39 +                return "Joe Hacker";
  262.40 +            }
  262.41 +        }
  262.42 +        Anno anno = (Anno) Proxy.newProxyInstance(
  262.43 +            Anno.class.getClassLoader(), 
  262.44 +            new Class[] { Anno.class }, 
  262.45 +            new InvHandler()
  262.46 +        );
  262.47 +        return anno.name();
  262.48 +    }
  262.49 +
  262.50 +    @Compare public int getPrimitiveType() throws Exception {
  262.51 +        class InvHandler implements InvocationHandler {
  262.52 +            @Override
  262.53 +            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  262.54 +                return 40;
  262.55 +            }
  262.56 +        }
  262.57 +        Anno anno = (Anno) Proxy.newProxyInstance(
  262.58 +            Anno.class.getClassLoader(), 
  262.59 +            new Class[] { Anno.class }, 
  262.60 +            new InvHandler()
  262.61 +        );
  262.62 +        return 2 + anno.age();
  262.63 +    }
  262.64 +    
  262.65 +    public static @interface Anno {
  262.66 +        public String name();
  262.67 +        public int age();
  262.68 +    }
  262.69 +    
  262.70 +    @Factory
  262.71 +    public static Object[] create() {
  262.72 +        return VMTest.create(ProxyTest.class);
  262.73 +    }
  262.74 +}
   263.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java	Tue Apr 29 15:25:58 2014 +0200
   263.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java	Wed Apr 30 15:04:10 2014 +0200
   263.3 @@ -34,6 +34,11 @@
   263.4          return arr.length;
   263.5      }
   263.6      
   263.7 +    @Compare public String indexOutOfBounds() {
   263.8 +        String[] arr = { null, null };
   263.9 +        return arr[2];
  263.10 +    }
  263.11 +    
  263.12      @Compare public int reflectiveLengthOfStringArray() {
  263.13          Object arr = Array.newInstance(String.class, 10);
  263.14          return Array.getLength(arr);
   264.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Tue Apr 29 15:25:58 2014 +0200
   264.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Wed Apr 30 15:04:10 2014 +0200
   264.3 @@ -19,7 +19,9 @@
   264.4  
   264.5  import java.lang.annotation.Retention;
   264.6  import java.lang.annotation.RetentionPolicy;
   264.7 +import java.lang.reflect.Constructor;
   264.8  import java.lang.reflect.Method;
   264.9 +import java.lang.reflect.Proxy;
  264.10  import java.util.Arrays;
  264.11  import java.util.Collections;
  264.12  import java.util.List;
  264.13 @@ -72,6 +74,18 @@
  264.14      @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
  264.15          return Runnable.class.getMethod("run").getName();
  264.16      }
  264.17 +
  264.18 +    @Compare public String isRunnableDeclaresRunMethod() throws NoSuchMethodException {
  264.19 +        return Runnable.class.getDeclaredMethod("run").getName();
  264.20 +    }
  264.21 +    
  264.22 +    @Compare public String intValue() throws Exception {
  264.23 +        return Integer.class.getConstructor(int.class).newInstance(10).toString();
  264.24 +    }
  264.25 +    
  264.26 +    @Compare public String getMethodWithArray() throws Exception {
  264.27 +        return Proxy.class.getMethod("getProxyClass", ClassLoader.class, Class[].class).getName();
  264.28 +    }
  264.29      
  264.30      @Compare public String namesOfMethods() {
  264.31          StringBuilder sb = new StringBuilder();
  264.32 @@ -86,6 +100,19 @@
  264.33          return sb.toString();
  264.34      }
  264.35  
  264.36 +    @Compare public String paramsOfConstructors() {
  264.37 +        StringBuilder sb = new StringBuilder();
  264.38 +        String[] arr = new String[20];
  264.39 +        int i = 0;
  264.40 +        for (Constructor<?> m : StaticUse.class.getConstructors()) {
  264.41 +            arr[i++] = m.getName();
  264.42 +        }
  264.43 +        for (String s : sort(arr, i)) {
  264.44 +            sb.append(s).append("\n");
  264.45 +        }
  264.46 +        return sb.toString();
  264.47 +    }
  264.48 +
  264.49      @Compare public String namesOfDeclaringClassesOfMethods() {
  264.50          StringBuilder sb = new StringBuilder();
  264.51          String[] arr = new String[20];
  264.52 @@ -223,6 +250,17 @@
  264.53          }
  264.54      }
  264.55      
  264.56 +    @Compare public int callAbst() throws Exception {
  264.57 +        class Impl extends Abst {
  264.58 +            @Override
  264.59 +            public int abst() {
  264.60 +                return 10;
  264.61 +            }
  264.62 +        }
  264.63 +        Abst impl = new Impl();
  264.64 +        return (int) Abst.class.getMethod("abst").invoke(impl);
  264.65 +    }
  264.66 +    
  264.67      @Compare public String componentGetNameForObjectArray() {
  264.68          return (new Object[3]).getClass().getComponentType().getName();
  264.69      }
  264.70 @@ -269,4 +307,7 @@
  264.71          return VMTest.create(ReflectionTest.class);
  264.72      }
  264.73      
  264.74 +    public static abstract class Abst {
  264.75 +        public abstract int abst();
  264.76 +    }
  264.77  }
   265.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   265.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/RegExpReplaceAllTest.java	Wed Apr 30 15:04:10 2014 +0200
   265.3 @@ -0,0 +1,54 @@
   265.4 +/**
   265.5 + * Back 2 Browser Bytecode Translator
   265.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   265.7 + *
   265.8 + * This program is free software: you can redistribute it and/or modify
   265.9 + * it under the terms of the GNU General Public License as published by
  265.10 + * the Free Software Foundation, version 2 of the License.
  265.11 + *
  265.12 + * This program is distributed in the hope that it will be useful,
  265.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  265.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  265.15 + * GNU General Public License for more details.
  265.16 + *
  265.17 + * You should have received a copy of the GNU General Public License
  265.18 + * along with this program. Look for COPYING file in the top folder.
  265.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  265.20 + */
  265.21 +package org.apidesign.bck2brwsr.tck;
  265.22 +
  265.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  265.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  265.25 +import org.testng.annotations.Factory;
  265.26 +
  265.27 +/**
  265.28 + *
  265.29 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  265.30 + */
  265.31 +public class RegExpReplaceAllTest {
  265.32 +
  265.33 +    @Compare public String replaceAll() {
  265.34 +        return "JavaScript".replaceAll("Script", "One");
  265.35 +    }
  265.36 +
  265.37 +    @Compare public String replaceAllTwice() {
  265.38 +        return "Script JavaScript!".replaceAll("Script", "One");
  265.39 +    }
  265.40 +
  265.41 +    
  265.42 +    @Compare public String replaceAllRegexp() {
  265.43 +        return "JavaScript".replaceAll("S....t", "One");
  265.44 +    }
  265.45 +
  265.46 +    @Compare public String replaceAllRegexpTwice() {
  265.47 +        return "Script JavaScript!".replaceAll("S....t", "One");
  265.48 +    }
  265.49 +
  265.50 +    @Compare public String replaceFirstRegexpOnly() {
  265.51 +        return "Script JavaScript!".replaceFirst("S....t", "One");
  265.52 +    }
  265.53 +    
  265.54 +    @Factory public static Object[] create() {
  265.55 +        return VMTest.create(RegExpReplaceAllTest.class);
  265.56 +    }
  265.57 +}
   266.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   266.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/RegExpSplitTest.java	Wed Apr 30 15:04:10 2014 +0200
   266.3 @@ -0,0 +1,54 @@
   266.4 +/**
   266.5 + * Back 2 Browser Bytecode Translator
   266.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   266.7 + *
   266.8 + * This program is free software: you can redistribute it and/or modify
   266.9 + * it under the terms of the GNU General Public License as published by
  266.10 + * the Free Software Foundation, version 2 of the License.
  266.11 + *
  266.12 + * This program is distributed in the hope that it will be useful,
  266.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  266.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  266.15 + * GNU General Public License for more details.
  266.16 + *
  266.17 + * You should have received a copy of the GNU General Public License
  266.18 + * along with this program. Look for COPYING file in the top folder.
  266.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  266.20 + */
  266.21 +package org.apidesign.bck2brwsr.tck;
  266.22 +
  266.23 +import java.util.Arrays;
  266.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  266.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  266.26 +import org.testng.annotations.Factory;
  266.27 +
  266.28 +/**
  266.29 + *
  266.30 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  266.31 + */
  266.32 +public class RegExpSplitTest {
  266.33 +
  266.34 +    public @Compare Object splitSpace() {
  266.35 +        return Arrays.asList("How are you today?".split(" "));
  266.36 +    }
  266.37 +
  266.38 +    public @Compare String splitNewline() {
  266.39 +        return Arrays.toString("initializer must be able to complete normally".split("\n"));
  266.40 +    }
  266.41 +
  266.42 +    public @Compare Object splitSpaceTrimMinusOne() {
  266.43 +        return Arrays.asList(" How are you today? ".split(" ", -1));
  266.44 +    }
  266.45 +
  266.46 +    public @Compare Object splitSpaceTrimZero() {
  266.47 +        return Arrays.asList(" How are you today? ".split(" ", 0));
  266.48 +    }
  266.49 +
  266.50 +    public @Compare Object splitSpaceLimit2() {
  266.51 +        return Arrays.asList("How are you today?".split(" ", 2));
  266.52 +    }
  266.53 +    
  266.54 +    @Factory public static Object[] create() {
  266.55 +        return VMTest.create(RegExpSplitTest.class);
  266.56 +    }
  266.57 +}
   267.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   267.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourceBundleTest.java	Wed Apr 30 15:04:10 2014 +0200
   267.3 @@ -0,0 +1,45 @@
   267.4 +/**
   267.5 + * Back 2 Browser Bytecode Translator
   267.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   267.7 + *
   267.8 + * This program is free software: you can redistribute it and/or modify
   267.9 + * it under the terms of the GNU General Public License as published by
  267.10 + * the Free Software Foundation, version 2 of the License.
  267.11 + *
  267.12 + * This program is distributed in the hope that it will be useful,
  267.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  267.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  267.15 + * GNU General Public License for more details.
  267.16 + *
  267.17 + * You should have received a copy of the GNU General Public License
  267.18 + * along with this program. Look for COPYING file in the top folder.
  267.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  267.20 + */
  267.21 +package org.apidesign.bck2brwsr.tck;
  267.22 +
  267.23 +import java.net.URL;
  267.24 +import java.util.ResourceBundle;
  267.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
  267.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  267.27 +import org.testng.annotations.Factory;
  267.28 +
  267.29 +/**
  267.30 + *
  267.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  267.32 + */
  267.33 +public class ResourceBundleTest {
  267.34 +    
  267.35 +    @Compare public String readFromBundle() throws Exception {
  267.36 +        ResourceBundle b = ResourceBundle.getBundle("org/apidesign/bck2brwsr/tck/Bundle");
  267.37 +        return b.getString("KEY");
  267.38 +    }
  267.39 +    
  267.40 +    @Compare public String toURIFromURL() throws Exception {
  267.41 +        URL u = new URL("http://apidesign.org");
  267.42 +        return u.toURI().toString();
  267.43 +    }
  267.44 +    
  267.45 +    @Factory public static Object[] create() {
  267.46 +        return VMTest.create(ResourceBundleTest.class);
  267.47 +    }
  267.48 +}
   268.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java	Tue Apr 29 15:25:58 2014 +0200
   268.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java	Wed Apr 30 15:04:10 2014 +0200
   268.3 @@ -17,7 +17,10 @@
   268.4   */
   268.5  package org.apidesign.bck2brwsr.tck;
   268.6  
   268.7 +import java.io.IOException;
   268.8  import java.io.InputStream;
   268.9 +import java.net.URL;
  268.10 +import java.util.Enumeration;
  268.11  import org.apidesign.bck2brwsr.vmtest.Compare;
  268.12  import org.apidesign.bck2brwsr.vmtest.VMTest;
  268.13  import org.testng.annotations.Factory;
  268.14 @@ -27,17 +30,62 @@
  268.15   * @author Jaroslav Tulach <jtulach@netbeans.org>
  268.16   */
  268.17  public class ResourcesTest {
  268.18 +    @Compare public String allManifests() throws Exception {
  268.19 +        Enumeration<URL> en = ClassLoader.getSystemResources("META-INF/MANIFEST.MF");
  268.20 +        assert en.hasMoreElements() : "Should have at least one manifest";
  268.21 +        String first = readString(en.nextElement().openStream());
  268.22 +        boolean different = false;
  268.23 +        int cnt = 1;
  268.24 +        while (en.hasMoreElements()) {
  268.25 +            URL url = en.nextElement();
  268.26 +            String now = readString(url.openStream());
  268.27 +            if (!first.equals(now)) {
  268.28 +                different = true;
  268.29 +            }
  268.30 +            cnt++;
  268.31 +            if (cnt > 500) {
  268.32 +                throw new IllegalStateException(
  268.33 +                    "Giving up. First manifest:\n" + first + 
  268.34 +                    "\nLast manifest:\n" + now
  268.35 +                );
  268.36 +            }
  268.37 +        }
  268.38 +        assert different : "Not all manifests should look like first one:\n" + first;
  268.39 +        return "" + cnt;
  268.40 +    }
  268.41      
  268.42      @Compare public String readResourceAsStream() throws Exception {
  268.43          InputStream is = getClass().getResourceAsStream("Resources.txt");
  268.44 -        assert is != null : "The stream for Resources.txt should be found";
  268.45 -        byte[] b = new byte[30];
  268.46 -        int len = is.read(b);
  268.47 +        return readString(is);
  268.48 +    }
  268.49 +    
  268.50 +    @Compare public String readResourceViaConnection() throws Exception {
  268.51 +        InputStream is = getClass().getResource("Resources.txt").openConnection().getInputStream();
  268.52 +        return readString(is);
  268.53 +    }
  268.54 +
  268.55 +    private String readString(InputStream is) throws IOException {
  268.56          StringBuilder sb = new StringBuilder();
  268.57 -        for (int i = 0; i < len; i++) {
  268.58 -            sb.append((char)b[i]);
  268.59 +        byte[] b = new byte[512];
  268.60 +        for (;;) { 
  268.61 +            int len = is.read(b);
  268.62 +            if (len == -1) {
  268.63 +                return sb.toString();
  268.64 +            }
  268.65 +            for (int i = 0; i < len; i++) {
  268.66 +                sb.append((char)b[i]);
  268.67 +            }
  268.68          }
  268.69 -        return sb.toString();
  268.70 +    }
  268.71 +
  268.72 +    @Compare public String readResourceAsStreamFromClassLoader() throws Exception {
  268.73 +        InputStream is = getClass().getClassLoader().getResourceAsStream("org/apidesign/bck2brwsr/tck/Resources.txt");
  268.74 +        return readString(is);
  268.75 +    }
  268.76 +    
  268.77 +    @Compare public String toURIFromURL() throws Exception {
  268.78 +        URL u = new URL("http://apidesign.org");
  268.79 +        return u.toURI().toString();
  268.80      }
  268.81      
  268.82      @Factory public static Object[] create() {
   269.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   269.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/SystemTest.java	Wed Apr 30 15:04:10 2014 +0200
   269.3 @@ -0,0 +1,65 @@
   269.4 +/**
   269.5 + * Back 2 Browser Bytecode Translator
   269.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   269.7 + *
   269.8 + * This program is free software: you can redistribute it and/or modify
   269.9 + * it under the terms of the GNU General Public License as published by
  269.10 + * the Free Software Foundation, version 2 of the License.
  269.11 + *
  269.12 + * This program is distributed in the hope that it will be useful,
  269.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  269.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  269.15 + * GNU General Public License for more details.
  269.16 + *
  269.17 + * You should have received a copy of the GNU General Public License
  269.18 + * along with this program. Look for COPYING file in the top folder.
  269.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  269.20 + */
  269.21 +package org.apidesign.bck2brwsr.tck;
  269.22 +
  269.23 +import java.io.ByteArrayOutputStream;
  269.24 +import java.io.PrintStream;
  269.25 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
  269.26 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  269.27 +import org.apidesign.bck2brwsr.vmtest.Compare;
  269.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  269.29 +import org.testng.annotations.Factory;
  269.30 +
  269.31 +/**
  269.32 + *
  269.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  269.34 + */
  269.35 +@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/tck/console.js")
  269.36 +public class SystemTest {
  269.37 +    @Compare public boolean nonNullOSName() {
  269.38 +        return System.getProperty("os.name") != null;
  269.39 +    }
  269.40 +
  269.41 +    @Compare public String captureStdOut() throws Exception {
  269.42 +        Object capture = initCapture();
  269.43 +        System.out.println("Ahoj");
  269.44 +        return textCapture(capture);
  269.45 +    }
  269.46 +    
  269.47 +    @JavaScriptBody(args = {}, body = ""
  269.48 +        + "var lines = [];"
  269.49 +        + "console.log = function(l) { lines.push(l); };"
  269.50 +        + "return lines;")
  269.51 +    Object initCapture() {
  269.52 +        ByteArrayOutputStream os = new ByteArrayOutputStream();
  269.53 +        PrintStream ps = new PrintStream(os);
  269.54 +        
  269.55 +        System.setOut(ps);
  269.56 +        return os;
  269.57 +    }
  269.58 +    
  269.59 +    @JavaScriptBody(args = { "o" }, body = "return o.join('');")
  269.60 +    String textCapture(Object o) throws java.io.IOException {
  269.61 +        ByteArrayOutputStream b = (ByteArrayOutputStream) o;
  269.62 +        return new String(b.toByteArray(), "UTF-8");
  269.63 +    }
  269.64 +    
  269.65 +    @Factory public static Object[] create() {
  269.66 +        return VMTest.create(SystemTest.class);
  269.67 +    }
  269.68 +}
   270.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   270.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/TimerTest.java	Wed Apr 30 15:04:10 2014 +0200
   270.3 @@ -0,0 +1,81 @@
   270.4 +/**
   270.5 + * Back 2 Browser Bytecode Translator
   270.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   270.7 + *
   270.8 + * This program is free software: you can redistribute it and/or modify
   270.9 + * it under the terms of the GNU General Public License as published by
  270.10 + * the Free Software Foundation, version 2 of the License.
  270.11 + *
  270.12 + * This program is distributed in the hope that it will be useful,
  270.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  270.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  270.15 + * GNU General Public License for more details.
  270.16 + *
  270.17 + * You should have received a copy of the GNU General Public License
  270.18 + * along with this program. Look for COPYING file in the top folder.
  270.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  270.20 + */
  270.21 +package org.apidesign.bck2brwsr.tck;
  270.22 +
  270.23 +import java.util.Timer;
  270.24 +import java.util.TimerTask;
  270.25 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  270.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  270.27 +import org.testng.annotations.Factory;
  270.28 +
  270.29 +/**
  270.30 + *
  270.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  270.32 + */
  270.33 +public class TimerTest {
  270.34 +    int miss;
  270.35 +    int exec;
  270.36 +    
  270.37 +    public TimerTest() {
  270.38 +    }
  270.39 +    
  270.40 +    @BrwsrTest public void scheduleTick() throws Exception {
  270.41 +        Timer t = new Timer("MyTest");
  270.42 +        class TT extends TimerTask {
  270.43 +            @Override
  270.44 +            public void run() {
  270.45 +                exec++;
  270.46 +            }
  270.47 +        }
  270.48 +        TT task = new TT();
  270.49 +        t.schedule(task, 15);
  270.50 +        
  270.51 +        if (exec == 0) {
  270.52 +            miss++;
  270.53 +            throw new InterruptedException();
  270.54 +        }
  270.55 +        
  270.56 +        assert exec == 1 : "One exec: " + exec;
  270.57 +        assert miss == 1 : "One miss: " + miss;
  270.58 +    }
  270.59 +    
  270.60 +    @BrwsrTest public void repeatedTicks() throws Exception {
  270.61 +        Timer t = new Timer("MyTest");
  270.62 +        class TT extends TimerTask {
  270.63 +            @Override
  270.64 +            public void run() {
  270.65 +                exec++;
  270.66 +            }
  270.67 +        }
  270.68 +        TT task = new TT();
  270.69 +        t.scheduleAtFixedRate(task, 15, 10);
  270.70 +        
  270.71 +        if (exec != 2) {
  270.72 +            miss++;
  270.73 +            throw new InterruptedException();
  270.74 +        }
  270.75 +        
  270.76 +        assert exec == 2 : "Two execs: " + exec;
  270.77 +        assert miss == 2 : "Two misses: " + miss;
  270.78 +    }
  270.79 +    
  270.80 +    @Factory public static Object[] create() {
  270.81 +        return VMTest.create(TimerTest.class);
  270.82 +    }
  270.83 +    
  270.84 +}
   271.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   271.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/HtmlAnnotations.java	Wed Apr 30 15:04:10 2014 +0200
   271.3 @@ -0,0 +1,86 @@
   271.4 +/**
   271.5 + * Back 2 Browser Bytecode Translator
   271.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   271.7 + *
   271.8 + * This program is free software: you can redistribute it and/or modify
   271.9 + * it under the terms of the GNU General Public License as published by
  271.10 + * the Free Software Foundation, version 2 of the License.
  271.11 + *
  271.12 + * This program is distributed in the hope that it will be useful,
  271.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  271.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  271.15 + * GNU General Public License for more details.
  271.16 + *
  271.17 + * You should have received a copy of the GNU General Public License
  271.18 + * along with this program. Look for COPYING file in the top folder.
  271.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  271.20 + */
  271.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  271.22 +
  271.23 +import net.java.html.js.JavaScriptBody;
  271.24 +import net.java.html.js.JavaScriptResource;
  271.25 +
  271.26 +/**
  271.27 + *
  271.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  271.29 + */
  271.30 +@JavaScriptResource("htmlannotations.js")
  271.31 +public class HtmlAnnotations {
  271.32 +    private Object callback;
  271.33 +    
  271.34 +    
  271.35 +    @JavaScriptBody(args = {}, body = "return 42;")
  271.36 +    public static int fourtyTwo() {
  271.37 +        return -1;
  271.38 +    }
  271.39 +    
  271.40 +    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
  271.41 +    public static native int useExternalMul(int x, int y);
  271.42 +    
  271.43 +    public static int callback() {
  271.44 +        final int[] arr = { 0 };
  271.45 +        callback(new Runnable() {
  271.46 +            @Override
  271.47 +            public void run() {
  271.48 +                arr[0]++;
  271.49 +            }
  271.50 +        });
  271.51 +        return arr[0];
  271.52 +    }
  271.53 +    
  271.54 +    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()()")
  271.55 +    private static native void callback(Runnable r);
  271.56 +
  271.57 +    @JavaScriptBody(args = {  }, javacall = true, body = "return @org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::callback()();")
  271.58 +    public static native int staticCallback();
  271.59 +    
  271.60 +    
  271.61 +    protected long chooseLong(boolean takeFirst, boolean takeSecond, long first, long second) {
  271.62 +        long l = 0;
  271.63 +        if (takeFirst) l += first;
  271.64 +        if (takeSecond) l += second;
  271.65 +        return l;
  271.66 +    }
  271.67 +    
  271.68 +    protected void onError(Object obj) throws Exception {
  271.69 +        callback = obj;
  271.70 +    }
  271.71 +    
  271.72 +    Object getError() {
  271.73 +        return callback;
  271.74 +    }
  271.75 +    
  271.76 +    public static Object create() {
  271.77 +        return new HtmlAnnotations();
  271.78 +    }
  271.79 +    @JavaScriptBody(args = { "impl", "a", "b" }, javacall = true, body = 
  271.80 +        "return impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::chooseLong(ZZJJ)(true, false, a, b);"
  271.81 +    )
  271.82 +    public static native long first(Object impl, long a, long b);
  271.83 +    
  271.84 +    @JavaScriptBody(args = { "impl", "d" }, javacall = true, body = 
  271.85 +        "impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::onError(Ljava/lang/Object;)(d);" +
  271.86 +        "return impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::getError()();"
  271.87 +    )
  271.88 +    public static native Double onError(Object impl, Double d);
  271.89 +}
   272.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   272.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/HtmlAnnotationsTest.java	Wed Apr 30 15:04:10 2014 +0200
   272.3 @@ -0,0 +1,71 @@
   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.bck2brwsr.vmtest.impl;
  272.22 +
  272.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  272.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  272.25 +import org.testng.annotations.Factory;
  272.26 +
  272.27 +/** Verify cooperation with net.java.html.js annotations.
  272.28 + *
  272.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  272.30 + */
  272.31 +public class HtmlAnnotationsTest {
  272.32 +    @BrwsrTest public void fourtyTwo() throws Exception {
  272.33 +        assertEquals(HtmlAnnotations.fourtyTwo(), 42);
  272.34 +    }
  272.35 +    
  272.36 +    @BrwsrTest public void externalMul() throws Exception {
  272.37 +        assertEquals(HtmlAnnotations.useExternalMul(7, 6), 42);
  272.38 +    }
  272.39 +
  272.40 +    @BrwsrTest public void callRunnableFromJS() throws Exception {
  272.41 +        assertEquals(HtmlAnnotations.callback(), 1);
  272.42 +    }
  272.43 +
  272.44 +    @BrwsrTest public void callStaticMethodFromJS() throws Exception {
  272.45 +        assertEquals(HtmlAnnotations.staticCallback(), 1);
  272.46 +    }
  272.47 +
  272.48 +    @BrwsrTest public void callbackWithFourParamsAndReturnType() throws Exception {
  272.49 +        Object instance = HtmlAnnotations.create();
  272.50 +        assertNotNull(instance, "Instance created");
  272.51 +        assertEquals(HtmlAnnotations.first(instance, 42, 31), 42);
  272.52 +    }
  272.53 +
  272.54 +    @BrwsrTest public void callbackWithObjectParamsAndReturnType() throws Exception {
  272.55 +        Object instance = HtmlAnnotations.create();
  272.56 +        assertNotNull(instance, "Instance created");
  272.57 +        assertEquals(HtmlAnnotations.onError(instance, 42.0), 42.0);
  272.58 +    }
  272.59 +    
  272.60 +    private static void assertEquals(double real, double exp) {
  272.61 +        if (real - exp < 0.01) {
  272.62 +            return;
  272.63 +        }
  272.64 +        assert false : "Expecting " + exp + " but was " + real;
  272.65 +    }
  272.66 +
  272.67 +    private static void assertNotNull(Object obj, String msg) {
  272.68 +        assert obj != null : msg;
  272.69 +    }
  272.70 +    
  272.71 +    @Factory public static Object[] create() {
  272.72 +        return VMTest.create(HtmlAnnotationsTest.class);
  272.73 +    }
  272.74 +}
   273.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   273.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Bundle.properties	Wed Apr 30 15:04:10 2014 +0200
   273.3 @@ -0,0 +1,2 @@
   273.4 +KEY=Value
   273.5 +
   274.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   274.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/console.js	Wed Apr 30 15:04:10 2014 +0200
   274.3 @@ -0,0 +1,22 @@
   274.4 +/**
   274.5 + * Back 2 Browser Bytecode Translator
   274.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   274.7 + *
   274.8 + * This program is free software: you can redistribute it and/or modify
   274.9 + * it under the terms of the GNU General Public License as published by
  274.10 + * the Free Software Foundation, version 2 of the License.
  274.11 + *
  274.12 + * This program is distributed in the hope that it will be useful,
  274.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  274.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  274.15 + * GNU General Public License for more details.
  274.16 + *
  274.17 + * You should have received a copy of the GNU General Public License
  274.18 + * along with this program. Look for COPYING file in the top folder.
  274.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  274.20 + */
  274.21 +
  274.22 +if (typeof console === 'undefined') {
  274.23 +    console = {};
  274.24 +}
  274.25 +
   275.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   275.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/vmtest/impl/htmlannotations.js	Wed Apr 30 15:04:10 2014 +0200
   275.3 @@ -0,0 +1,20 @@
   275.4 +/*
   275.5 + * Back 2 Browser Bytecode Translator
   275.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   275.7 + *
   275.8 + * This program is free software: you can redistribute it and/or modify
   275.9 + * it under the terms of the GNU General Public License as published by
  275.10 + * the Free Software Foundation, version 2 of the License.
  275.11 + *
  275.12 + * This program is distributed in the hope that it will be useful,
  275.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  275.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  275.15 + * GNU General Public License for more details.
  275.16 + *
  275.17 + * You should have received a copy of the GNU General Public License
  275.18 + * along with this program. Look for COPYING file in the top folder.
  275.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  275.20 + */
  275.21 +
  275.22 +function mul(x, y) { return x * y; }
  275.23 +window.mul = mul;
   276.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   276.2 +++ b/rt/emul/fake/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   276.3 @@ -0,0 +1,28 @@
   276.4 +<?xml version="1.0" encoding="UTF-8"?>
   276.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">
   276.6 +    <modelVersion>4.0.0</modelVersion>
   276.7 +    <parent>
   276.8 +        <groupId>org.apidesign.bck2brwsr</groupId>
   276.9 +        <artifactId>emul.pom</artifactId>
  276.10 +        <version>0.9-SNAPSHOT</version>
  276.11 +    </parent>
  276.12 +    <artifactId>fake</artifactId>
  276.13 +    <packaging>jar</packaging>
  276.14 +    <name>Fake Stubs of Java APIs</name>
  276.15 +    <description>
  276.16 +        The minimal emulation classes have certain references
  276.17 +        to less essential classes in the JDK. This module provides
  276.18 +        their stubs for purpose of compilation.
  276.19 +    </description> 
  276.20 +    <build>
  276.21 +        <plugins>
  276.22 +            <plugin>
  276.23 +                <artifactId>maven-deploy-plugin</artifactId>
  276.24 +                <version>2.7</version>
  276.25 +                <configuration>
  276.26 +                    <skip>true</skip>
  276.27 +                </configuration>
  276.28 +            </plugin>
  276.29 +        </plugins>
  276.30 +    </build>
  276.31 +</project>
   277.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   277.2 +++ b/rt/emul/fake/src/main/java/java/io/PrintStream.java	Wed Apr 30 15:04:10 2014 +0200
   277.3 @@ -0,0 +1,26 @@
   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 java.io;
  277.22 +
  277.23 +/** Fake signature of an existing Java class.
  277.24 + * @author Jaroslav Tulach
  277.25 + */
  277.26 +public abstract class PrintStream {
  277.27 +    public abstract void print(String s);
  277.28 +    public abstract void println(String s);
  277.29 +}
   278.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   278.2 +++ b/rt/emul/fake/src/main/java/java/io/PrintWriter.java	Wed Apr 30 15:04:10 2014 +0200
   278.3 @@ -0,0 +1,26 @@
   278.4 +/**
   278.5 + * Back 2 Browser Bytecode Translator
   278.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   278.7 + *
   278.8 + * This program is free software: you can redistribute it and/or modify
   278.9 + * it under the terms of the GNU General Public License as published by
  278.10 + * the Free Software Foundation, version 2 of the License.
  278.11 + *
  278.12 + * This program is distributed in the hope that it will be useful,
  278.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  278.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  278.15 + * GNU General Public License for more details.
  278.16 + *
  278.17 + * You should have received a copy of the GNU General Public License
  278.18 + * along with this program. Look for COPYING file in the top folder.
  278.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  278.20 + */
  278.21 +package java.io;
  278.22 +
  278.23 +/** Fake signature of an existing Java class.
  278.24 + * @author Jaroslav Tulach
  278.25 + */
  278.26 +public abstract class PrintWriter {
  278.27 +    public abstract PrintWriter append(String s);
  278.28 +    public abstract void println(String s);
  278.29 +}
   279.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   279.2 +++ b/rt/emul/fake/src/main/java/java/net/URI.java	Wed Apr 30 15:04:10 2014 +0200
   279.3 @@ -0,0 +1,26 @@
   279.4 +/**
   279.5 + * Back 2 Browser Bytecode Translator
   279.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   279.7 + *
   279.8 + * This program is free software: you can redistribute it and/or modify
   279.9 + * it under the terms of the GNU General Public License as published by
  279.10 + * the Free Software Foundation, version 2 of the License.
  279.11 + *
  279.12 + * This program is distributed in the hope that it will be useful,
  279.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  279.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  279.15 + * GNU General Public License for more details.
  279.16 + *
  279.17 + * You should have received a copy of the GNU General Public License
  279.18 + * along with this program. Look for COPYING file in the top folder.
  279.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  279.20 + */
  279.21 +package java.net;
  279.22 +
  279.23 +/** Fake signature of an existing Java class.
  279.24 + * @author Jaroslav Tulach
  279.25 + */
  279.26 +public class URI {
  279.27 +    public URI(String url) {
  279.28 +    }
  279.29 +}
   280.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   280.2 +++ b/rt/emul/fake/src/main/java/java/net/URISyntaxException.java	Wed Apr 30 15:04:10 2014 +0200
   280.3 @@ -0,0 +1,25 @@
   280.4 +/**
   280.5 + * Back 2 Browser Bytecode Translator
   280.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   280.7 + *
   280.8 + * This program is free software: you can redistribute it and/or modify
   280.9 + * it under the terms of the GNU General Public License as published by
  280.10 + * the Free Software Foundation, version 2 of the License.
  280.11 + *
  280.12 + * This program is distributed in the hope that it will be useful,
  280.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  280.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  280.15 + * GNU General Public License for more details.
  280.16 + *
  280.17 + * You should have received a copy of the GNU General Public License
  280.18 + * along with this program. Look for COPYING file in the top folder.
  280.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  280.20 + */
  280.21 +package java.net;
  280.22 +
  280.23 +/** Fake signature of an existing Java class.
  280.24 + * @author Jaroslav Tulach
  280.25 + */
  280.26 +public class URISyntaxException extends Exception {
  280.27 +    
  280.28 +}
   281.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   281.2 +++ b/rt/emul/fake/src/main/java/java/net/URLConnection.java	Wed Apr 30 15:04:10 2014 +0200
   281.3 @@ -0,0 +1,33 @@
   281.4 +/**
   281.5 + * Back 2 Browser Bytecode Translator
   281.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   281.7 + *
   281.8 + * This program is free software: you can redistribute it and/or modify
   281.9 + * it under the terms of the GNU General Public License as published by
  281.10 + * the Free Software Foundation, version 2 of the License.
  281.11 + *
  281.12 + * This program is distributed in the hope that it will be useful,
  281.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  281.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  281.15 + * GNU General Public License for more details.
  281.16 + *
  281.17 + * You should have received a copy of the GNU General Public License
  281.18 + * along with this program. Look for COPYING file in the top folder.
  281.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  281.20 + */
  281.21 +package java.net;
  281.22 +
  281.23 +import java.io.IOException;
  281.24 +import java.io.InputStream;
  281.25 +
  281.26 +/** Fake signature of an existing Java class.
  281.27 + * @author Jaroslav Tulach
  281.28 + */
  281.29 +public abstract class URLConnection {
  281.30 +    protected URL url;
  281.31 +    public URLConnection(URL u) {
  281.32 +    }
  281.33 +    public abstract void connect() throws IOException;
  281.34 +    public abstract InputStream getInputStream() throws IOException;
  281.35 +    
  281.36 +}
   282.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   282.2 +++ b/rt/emul/fake/src/main/java/java/util/Locale.java	Wed Apr 30 15:04:10 2014 +0200
   282.3 @@ -0,0 +1,24 @@
   282.4 +/**
   282.5 + * Back 2 Browser Bytecode Translator
   282.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   282.7 + *
   282.8 + * This program is free software: you can redistribute it and/or modify
   282.9 + * it under the terms of the GNU General Public License as published by
  282.10 + * the Free Software Foundation, version 2 of the License.
  282.11 + *
  282.12 + * This program is distributed in the hope that it will be useful,
  282.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  282.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  282.15 + * GNU General Public License for more details.
  282.16 + *
  282.17 + * You should have received a copy of the GNU General Public License
  282.18 + * along with this program. Look for COPYING file in the top folder.
  282.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  282.20 + */
  282.21 +package java.util;
  282.22 +
  282.23 +/** Fake signature of an existing Java class.
  282.24 + * @author Jaroslav Tulach
  282.25 + */
  282.26 +public abstract class Locale {
  282.27 +}
   283.1 --- a/rt/emul/mini/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   283.2 +++ b/rt/emul/mini/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   283.3 @@ -4,11 +4,11 @@
   283.4    <parent>
   283.5      <groupId>org.apidesign.bck2brwsr</groupId>
   283.6      <artifactId>emul.pom</artifactId>
   283.7 -    <version>0.8-SNAPSHOT</version>
   283.8 +    <version>0.9-SNAPSHOT</version>
   283.9    </parent>
  283.10    <groupId>org.apidesign.bck2brwsr</groupId>
  283.11    <artifactId>emul.mini</artifactId>
  283.12 -  <version>0.8-SNAPSHOT</version>
  283.13 +  <version>0.9-SNAPSHOT</version>
  283.14    <name>Minimal API Profile</name>
  283.15    <url>http://maven.apache.org</url>
  283.16    <properties>
  283.17 @@ -18,13 +18,19 @@
  283.18      <dependency>
  283.19        <groupId>org.apidesign.bck2brwsr</groupId>
  283.20        <artifactId>core</artifactId>
  283.21 -      <version>0.8-SNAPSHOT</version>
  283.22 +      <version>0.9-SNAPSHOT</version>
  283.23 +      <type>jar</type>
  283.24 +    </dependency>
  283.25 +    <dependency>
  283.26 +      <groupId>org.apidesign.bck2brwsr</groupId>
  283.27 +      <artifactId>fake</artifactId>
  283.28 +      <version>0.9-SNAPSHOT</version>
  283.29 +      <scope>provided</scope>
  283.30        <type>jar</type>
  283.31      </dependency>
  283.32      <dependency>
  283.33        <groupId>org.testng</groupId>
  283.34        <artifactId>testng</artifactId>
  283.35 -      <version>6.5.2</version>
  283.36        <scope>test</scope>
  283.37      </dependency>
  283.38    </dependencies>
   284.1 --- a/rt/emul/mini/src/main/java/java/lang/Character.java	Tue Apr 29 15:25:58 2014 +0200
   284.2 +++ b/rt/emul/mini/src/main/java/java/lang/Character.java	Wed Apr 30 15:04:10 2014 +0200
   284.3 @@ -572,6 +572,46 @@
   284.4       */
   284.5      public static final int MAX_CODE_POINT = 0X10FFFF;
   284.6  
   284.7 +    public static boolean isAlphabetic(int ch) {
   284.8 +        throw new UnsupportedOperationException("isAlphabetic: " + (char)ch);
   284.9 +    }
  284.10 +
  284.11 +    public static boolean isIdeographic(int ch) {
  284.12 +        throw new UnsupportedOperationException("isIdeographic: " + (char)ch);
  284.13 +    }
  284.14 +
  284.15 +    public static boolean isLowerCase(int ch) {
  284.16 +        throw new UnsupportedOperationException("isLowerCase: " + (char)ch);
  284.17 +    }
  284.18 +
  284.19 +    public static boolean isUpperCase(int ch) {
  284.20 +        throw new UnsupportedOperationException("isUpperCase: " + (char)ch);
  284.21 +    }
  284.22 +
  284.23 +    public static boolean isMirrored(int ch) {
  284.24 +        throw new UnsupportedOperationException("isMirrored: " + (char)ch);
  284.25 +    }
  284.26 +
  284.27 +    public static boolean isIdentifierIgnorable(int ch) {
  284.28 +        throw new UnsupportedOperationException("isIdentifierIgnorable: " + (char)ch);
  284.29 +    }
  284.30 +
  284.31 +    public static boolean isUnicodeIdentifierPart(int ch) {
  284.32 +        throw new UnsupportedOperationException("isUnicodeIdentifierPart: " + (char)ch);
  284.33 +    }
  284.34 +
  284.35 +    public static boolean isUnicodeIdentifierStart(int ch) {
  284.36 +        throw new UnsupportedOperationException("isUnicodeIdentifierStart: " + (char)ch);
  284.37 +    }
  284.38 +
  284.39 +    public static char toUpperCase(int ch) {
  284.40 +        throw new UnsupportedOperationException("toUpperCase: " + (char)ch);
  284.41 +    }
  284.42 +
  284.43 +    public static int toLowerCase(int ch) {
  284.44 +        throw new UnsupportedOperationException("toLowerCase: " + (char)ch);
  284.45 +    }
  284.46 +
  284.47  
  284.48      /**
  284.49       * Instances of this class represent particular subsets of the Unicode
  284.50 @@ -1892,8 +1932,8 @@
  284.51          return fromCodeChars(codePoint).matches("\\w");
  284.52      }
  284.53      
  284.54 -    static int getType(int x) {
  284.55 -        throw new UnsupportedOperationException();
  284.56 +    public static int getType(int x) {
  284.57 +        throw new UnsupportedOperationException("getType: " + (char)x);
  284.58      }
  284.59   
  284.60      /**
  284.61 @@ -1955,7 +1995,8 @@
  284.62      public static boolean isJavaIdentifierStart(int codePoint) {
  284.63          return 
  284.64              ('A' <= codePoint && codePoint <= 'Z') ||
  284.65 -            ('a' <= codePoint && codePoint <= 'z');
  284.66 +            ('a' <= codePoint && codePoint <= 'z') ||
  284.67 +            codePoint == '$';
  284.68      }
  284.69  
  284.70      /**
  284.71 @@ -2298,6 +2339,10 @@
  284.72       */
  284.73      @Deprecated
  284.74      public static boolean isSpace(char ch) {
  284.75 +        return isSpaceChar(ch);
  284.76 +    }
  284.77 +
  284.78 +    public static boolean isSpaceChar(int ch) {
  284.79          return (ch <= 0x0020) &&
  284.80              (((((1L << 0x0009) |
  284.81              (1L << 0x000A) |
  284.82 @@ -2307,7 +2352,6 @@
  284.83      }
  284.84  
  284.85  
  284.86 -
  284.87      /**
  284.88       * Determines if the specified character is white space according to Java.
  284.89       * A character is a Java whitespace character if and only if it satisfies
  284.90 @@ -2372,7 +2416,14 @@
  284.91       * @since   1.5
  284.92       */
  284.93      public static boolean isWhitespace(int codePoint) {
  284.94 -        throw new UnsupportedOperationException();
  284.95 +        // values up to 128: [9,10,11,12,13,28,29,30,31,32]
  284.96 +        if (9 <= codePoint && 13 >= codePoint) {
  284.97 +            return true;
  284.98 +        }
  284.99 +        if (28 <= codePoint && 32 >= codePoint) {
 284.100 +            return true;
 284.101 +        }
 284.102 +        return false;
 284.103      }
 284.104  
 284.105      /**
   285.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java	Tue Apr 29 15:25:58 2014 +0200
   285.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java	Wed Apr 30 15:04:10 2014 +0200
   285.3 @@ -26,14 +26,16 @@
   285.4  package java.lang;
   285.5  
   285.6  import java.io.ByteArrayInputStream;
   285.7 -import org.apidesign.bck2brwsr.emul.reflect.AnnotationImpl;
   285.8  import java.io.InputStream;
   285.9  import java.lang.annotation.Annotation;
  285.10 +import java.lang.reflect.Array;
  285.11 +import java.lang.reflect.Constructor;
  285.12  import java.lang.reflect.Field;
  285.13  import java.lang.reflect.Method;
  285.14  import java.lang.reflect.TypeVariable;
  285.15  import java.net.URL;
  285.16  import org.apidesign.bck2brwsr.core.JavaScriptBody;
  285.17 +import org.apidesign.bck2brwsr.emul.reflect.AnnotationImpl;
  285.18  import org.apidesign.bck2brwsr.emul.reflect.MethodImpl;
  285.19  
  285.20  /**
  285.21 @@ -155,11 +157,15 @@
  285.22              }
  285.23              return arrType;
  285.24          }
  285.25 -        Class<?> c = loadCls(className, className.replace('.', '_'));
  285.26 -        if (c == null) {
  285.27 -            throw new ClassNotFoundException(className);
  285.28 +        try {
  285.29 +            Class<?> c = loadCls(className, className.replace('.', '_'));
  285.30 +            if (c == null) {
  285.31 +                throw new ClassNotFoundException(className);
  285.32 +            }
  285.33 +            return c;
  285.34 +        } catch (Throwable ex) {
  285.35 +            throw new ClassNotFoundException(className, ex);
  285.36          }
  285.37 -        return c;
  285.38      }
  285.39  
  285.40  
  285.41 @@ -627,6 +633,20 @@
  285.42          return getAccess();
  285.43      }
  285.44  
  285.45 +    /**
  285.46 +     * If the class or interface represented by this {@code Class} object
  285.47 +     * is a member of another class, returns the {@code Class} object
  285.48 +     * representing the class in which it was declared.  This method returns
  285.49 +     * null if this class or interface is not a member of any other class.  If
  285.50 +     * this {@code Class} object represents an array class, a primitive
  285.51 +     * type, or void,then this method returns null.
  285.52 +     *
  285.53 +     * @return the declaring class for this class
  285.54 +     * @since JDK1.1
  285.55 +     */
  285.56 +    public Class<?> getDeclaringClass() {
  285.57 +        throw new SecurityException();
  285.58 +    }
  285.59  
  285.60      /**
  285.61       * Returns the simple name of the underlying class as given in the
  285.62 @@ -971,6 +991,319 @@
  285.63      }
  285.64      
  285.65      /**
  285.66 +     * Returns an array of {@code Field} objects reflecting all the fields
  285.67 +     * declared by the class or interface represented by this
  285.68 +     * {@code Class} object. This includes public, protected, default
  285.69 +     * (package) access, and private fields, but excludes inherited fields.
  285.70 +     * The elements in the array returned are not sorted and are not in any
  285.71 +     * particular order.  This method returns an array of length 0 if the class
  285.72 +     * or interface declares no fields, or if this {@code Class} object
  285.73 +     * represents a primitive type, an array class, or void.
  285.74 +     *
  285.75 +     * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3.
  285.76 +     *
  285.77 +     * @return    the array of {@code Field} objects representing all the
  285.78 +     * declared fields of this class
  285.79 +     * @exception  SecurityException
  285.80 +     *             If a security manager, <i>s</i>, is present and any of the
  285.81 +     *             following conditions is met:
  285.82 +     *
  285.83 +     *             <ul>
  285.84 +     *
  285.85 +     *             <li> invocation of
  285.86 +     *             {@link SecurityManager#checkMemberAccess
  285.87 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
  285.88 +     *             access to the declared fields within this class
  285.89 +     *
  285.90 +     *             <li> the caller's class loader is not the same as or an
  285.91 +     *             ancestor of the class loader for the current class and
  285.92 +     *             invocation of {@link SecurityManager#checkPackageAccess
  285.93 +     *             s.checkPackageAccess()} denies access to the package
  285.94 +     *             of this class
  285.95 +     *
  285.96 +     *             </ul>
  285.97 +     *
  285.98 +     * @since JDK1.1
  285.99 +     */
 285.100 +    public Field[] getDeclaredFields() throws SecurityException {
 285.101 +        throw new SecurityException();
 285.102 +    }
 285.103 +
 285.104 +    /**
 285.105 +     * <b>Bck2Brwsr</b> emulation can only seek public methods, otherwise it
 285.106 +     * throws a {@code SecurityException}.
 285.107 +     * <p>
 285.108 +     * Returns a {@code Method} object that reflects the specified
 285.109 +     * declared method of the class or interface represented by this
 285.110 +     * {@code Class} object. The {@code name} parameter is a
 285.111 +     * {@code String} that specifies the simple name of the desired
 285.112 +     * method, and the {@code parameterTypes} parameter is an array of
 285.113 +     * {@code Class} objects that identify the method's formal parameter
 285.114 +     * types, in declared order.  If more than one method with the same
 285.115 +     * parameter types is declared in a class, and one of these methods has a
 285.116 +     * return type that is more specific than any of the others, that method is
 285.117 +     * returned; otherwise one of the methods is chosen arbitrarily.  If the
 285.118 +     * name is "&lt;init&gt;"or "&lt;clinit&gt;" a {@code NoSuchMethodException}
 285.119 +     * is raised.
 285.120 +     *
 285.121 +     * @param name the name of the method
 285.122 +     * @param parameterTypes the parameter array
 285.123 +     * @return    the {@code Method} object for the method of this class
 285.124 +     * matching the specified name and parameters
 285.125 +     * @exception NoSuchMethodException if a matching method is not found.
 285.126 +     * @exception NullPointerException if {@code name} is {@code null}
 285.127 +     * @exception  SecurityException
 285.128 +     *             If a security manager, <i>s</i>, is present and any of the
 285.129 +     *             following conditions is met:
 285.130 +     *
 285.131 +     *             <ul>
 285.132 +     *
 285.133 +     *             <li> invocation of
 285.134 +     *             {@link SecurityManager#checkMemberAccess
 285.135 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
 285.136 +     *             access to the declared method
 285.137 +     *
 285.138 +     *             <li> the caller's class loader is not the same as or an
 285.139 +     *             ancestor of the class loader for the current class and
 285.140 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.141 +     *             s.checkPackageAccess()} denies access to the package
 285.142 +     *             of this class
 285.143 +     *
 285.144 +     *             </ul>
 285.145 +     *
 285.146 +     * @since JDK1.1
 285.147 +     */
 285.148 +    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
 285.149 +    throws NoSuchMethodException, SecurityException {
 285.150 +        try {
 285.151 +            return getMethod(name, parameterTypes);
 285.152 +        } catch (NoSuchMethodException ex) {
 285.153 +            throw new SecurityException();
 285.154 +        }
 285.155 +    }
 285.156 +
 285.157 +    /**
 285.158 +     * Returns a {@code Field} object that reflects the specified declared
 285.159 +     * field of the class or interface represented by this {@code Class}
 285.160 +     * object. The {@code name} parameter is a {@code String} that
 285.161 +     * specifies the simple name of the desired field.  Note that this method
 285.162 +     * will not reflect the {@code length} field of an array class.
 285.163 +     *
 285.164 +     * @param name the name of the field
 285.165 +     * @return the {@code Field} object for the specified field in this
 285.166 +     * class
 285.167 +     * @exception NoSuchFieldException if a field with the specified name is
 285.168 +     *              not found.
 285.169 +     * @exception NullPointerException if {@code name} is {@code null}
 285.170 +     * @exception  SecurityException
 285.171 +     *             If a security manager, <i>s</i>, is present and any of the
 285.172 +     *             following conditions is met:
 285.173 +     *
 285.174 +     *             <ul>
 285.175 +     *
 285.176 +     *             <li> invocation of
 285.177 +     *             {@link SecurityManager#checkMemberAccess
 285.178 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
 285.179 +     *             access to the declared field
 285.180 +     *
 285.181 +     *             <li> the caller's class loader is not the same as or an
 285.182 +     *             ancestor of the class loader for the current class and
 285.183 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.184 +     *             s.checkPackageAccess()} denies access to the package
 285.185 +     *             of this class
 285.186 +     *
 285.187 +     *             </ul>
 285.188 +     *
 285.189 +     * @since JDK1.1
 285.190 +     */
 285.191 +    public Field getDeclaredField(String name)
 285.192 +    throws SecurityException {
 285.193 +        throw new SecurityException();
 285.194 +    }
 285.195 +    
 285.196 +    /**
 285.197 +     * Returns an array containing {@code Constructor} objects reflecting
 285.198 +     * all the public constructors of the class represented by this
 285.199 +     * {@code Class} object.  An array of length 0 is returned if the
 285.200 +     * class has no public constructors, or if the class is an array class, or
 285.201 +     * if the class reflects a primitive type or void.
 285.202 +     *
 285.203 +     * Note that while this method returns an array of {@code
 285.204 +     * Constructor<T>} objects (that is an array of constructors from
 285.205 +     * this class), the return type of this method is {@code
 285.206 +     * Constructor<?>[]} and <em>not</em> {@code Constructor<T>[]} as
 285.207 +     * might be expected.  This less informative return type is
 285.208 +     * necessary since after being returned from this method, the
 285.209 +     * array could be modified to hold {@code Constructor} objects for
 285.210 +     * different classes, which would violate the type guarantees of
 285.211 +     * {@code Constructor<T>[]}.
 285.212 +     *
 285.213 +     * @return the array of {@code Constructor} objects representing the
 285.214 +     *  public constructors of this class
 285.215 +     * @exception  SecurityException
 285.216 +     *             If a security manager, <i>s</i>, is present and any of the
 285.217 +     *             following conditions is met:
 285.218 +     *
 285.219 +     *             <ul>
 285.220 +     *
 285.221 +     *             <li> invocation of
 285.222 +     *             {@link SecurityManager#checkMemberAccess
 285.223 +     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
 285.224 +     *             access to the constructors within this class
 285.225 +     *
 285.226 +     *             <li> the caller's class loader is not the same as or an
 285.227 +     *             ancestor of the class loader for the current class and
 285.228 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.229 +     *             s.checkPackageAccess()} denies access to the package
 285.230 +     *             of this class
 285.231 +     *
 285.232 +     *             </ul>
 285.233 +     *
 285.234 +     * @since JDK1.1
 285.235 +     */
 285.236 +    public Constructor<?>[] getConstructors() throws SecurityException {
 285.237 +        return MethodImpl.findConstructors(this, 0x01);
 285.238 +    }
 285.239 +
 285.240 +    /**
 285.241 +     * Returns a {@code Constructor} object that reflects the specified
 285.242 +     * public constructor of the class represented by this {@code Class}
 285.243 +     * object. The {@code parameterTypes} parameter is an array of
 285.244 +     * {@code Class} objects that identify the constructor's formal
 285.245 +     * parameter types, in declared order.
 285.246 +     *
 285.247 +     * If this {@code Class} object represents an inner class
 285.248 +     * declared in a non-static context, the formal parameter types
 285.249 +     * include the explicit enclosing instance as the first parameter.
 285.250 +     *
 285.251 +     * <p> The constructor to reflect is the public constructor of the class
 285.252 +     * represented by this {@code Class} object whose formal parameter
 285.253 +     * types match those specified by {@code parameterTypes}.
 285.254 +     *
 285.255 +     * @param parameterTypes the parameter array
 285.256 +     * @return the {@code Constructor} object of the public constructor that
 285.257 +     * matches the specified {@code parameterTypes}
 285.258 +     * @exception NoSuchMethodException if a matching method is not found.
 285.259 +     * @exception  SecurityException
 285.260 +     *             If a security manager, <i>s</i>, is present and any of the
 285.261 +     *             following conditions is met:
 285.262 +     *
 285.263 +     *             <ul>
 285.264 +     *
 285.265 +     *             <li> invocation of
 285.266 +     *             {@link SecurityManager#checkMemberAccess
 285.267 +     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
 285.268 +     *             access to the constructor
 285.269 +     *
 285.270 +     *             <li> the caller's class loader is not the same as or an
 285.271 +     *             ancestor of the class loader for the current class and
 285.272 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.273 +     *             s.checkPackageAccess()} denies access to the package
 285.274 +     *             of this class
 285.275 +     *
 285.276 +     *             </ul>
 285.277 +     *
 285.278 +     * @since JDK1.1
 285.279 +     */
 285.280 +    public Constructor<T> getConstructor(Class<?>... parameterTypes)
 285.281 +    throws NoSuchMethodException, SecurityException {
 285.282 +        Constructor c = MethodImpl.findConstructor(this, parameterTypes);
 285.283 +        if (c == null) {
 285.284 +            StringBuilder sb = new StringBuilder();
 285.285 +            sb.append(getName()).append('(');
 285.286 +            String sep = "";
 285.287 +            for (int i = 0; i < parameterTypes.length; i++) {
 285.288 +                sb.append(sep).append(parameterTypes[i].getName());
 285.289 +                sep = ", ";
 285.290 +            }
 285.291 +            sb.append(')');
 285.292 +            throw new NoSuchMethodException(sb.toString());
 285.293 +        }
 285.294 +        return c;
 285.295 +    }
 285.296 +
 285.297 +    /**
 285.298 +     * Returns an array of {@code Constructor} objects reflecting all the
 285.299 +     * constructors declared by the class represented by this
 285.300 +     * {@code Class} object. These are public, protected, default
 285.301 +     * (package) access, and private constructors.  The elements in the array
 285.302 +     * returned are not sorted and are not in any particular order.  If the
 285.303 +     * class has a default constructor, it is included in the returned array.
 285.304 +     * This method returns an array of length 0 if this {@code Class}
 285.305 +     * object represents an interface, a primitive type, an array class, or
 285.306 +     * void.
 285.307 +     *
 285.308 +     * <p> See <em>The Java Language Specification</em>, section 8.2.
 285.309 +     *
 285.310 +     * @return    the array of {@code Constructor} objects representing all the
 285.311 +     * declared constructors of this class
 285.312 +     * @exception  SecurityException
 285.313 +     *             If a security manager, <i>s</i>, is present and any of the
 285.314 +     *             following conditions is met:
 285.315 +     *
 285.316 +     *             <ul>
 285.317 +     *
 285.318 +     *             <li> invocation of
 285.319 +     *             {@link SecurityManager#checkMemberAccess
 285.320 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
 285.321 +     *             access to the declared constructors within this class
 285.322 +     *
 285.323 +     *             <li> the caller's class loader is not the same as or an
 285.324 +     *             ancestor of the class loader for the current class and
 285.325 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.326 +     *             s.checkPackageAccess()} denies access to the package
 285.327 +     *             of this class
 285.328 +     *
 285.329 +     *             </ul>
 285.330 +     *
 285.331 +     * @since JDK1.1
 285.332 +     */
 285.333 +    public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
 285.334 +        throw new SecurityException();
 285.335 +    }
 285.336 +    /**
 285.337 +     * Returns a {@code Constructor} object that reflects the specified
 285.338 +     * constructor of the class or interface represented by this
 285.339 +     * {@code Class} object.  The {@code parameterTypes} parameter is
 285.340 +     * an array of {@code Class} objects that identify the constructor's
 285.341 +     * formal parameter types, in declared order.
 285.342 +     *
 285.343 +     * If this {@code Class} object represents an inner class
 285.344 +     * declared in a non-static context, the formal parameter types
 285.345 +     * include the explicit enclosing instance as the first parameter.
 285.346 +     *
 285.347 +     * @param parameterTypes the parameter array
 285.348 +     * @return    The {@code Constructor} object for the constructor with the
 285.349 +     * specified parameter list
 285.350 +     * @exception NoSuchMethodException if a matching method is not found.
 285.351 +     * @exception  SecurityException
 285.352 +     *             If a security manager, <i>s</i>, is present and any of the
 285.353 +     *             following conditions is met:
 285.354 +     *
 285.355 +     *             <ul>
 285.356 +     *
 285.357 +     *             <li> invocation of
 285.358 +     *             {@link SecurityManager#checkMemberAccess
 285.359 +     *             s.checkMemberAccess(this, Member.DECLARED)} denies
 285.360 +     *             access to the declared constructor
 285.361 +     *
 285.362 +     *             <li> the caller's class loader is not the same as or an
 285.363 +     *             ancestor of the class loader for the current class and
 285.364 +     *             invocation of {@link SecurityManager#checkPackageAccess
 285.365 +     *             s.checkPackageAccess()} denies access to the package
 285.366 +     *             of this class
 285.367 +     *
 285.368 +     *             </ul>
 285.369 +     *
 285.370 +     * @since JDK1.1
 285.371 +     */
 285.372 +    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
 285.373 +    throws NoSuchMethodException, SecurityException {
 285.374 +        return getConstructor(parameterTypes);
 285.375 +    }
 285.376 +    
 285.377 +    
 285.378 +    /**
 285.379       * Character.isDigit answers {@code true} to some non-ascii
 285.380       * digits.  This one does not.
 285.381       */
 285.382 @@ -1047,15 +1380,10 @@
 285.383       */
 285.384       public InputStream getResourceAsStream(String name) {
 285.385          name = resolveName(name);
 285.386 -        byte[] arr = getResourceAsStream0(name);
 285.387 +        byte[] arr = ClassLoader.getResourceAsStream0(name, 0);
 285.388          return arr == null ? null : new ByteArrayInputStream(arr);
 285.389       }
 285.390 -     
 285.391 -     @JavaScriptBody(args = "name", body = 
 285.392 -         "return (vm.loadBytes) ? vm.loadBytes(name) : null;"
 285.393 -     )
 285.394 -     private static native byte[] getResourceAsStream0(String name);
 285.395 -
 285.396 +    
 285.397      /**
 285.398       * Finds a resource with a given name.  The rules for searching resources
 285.399       * associated with a given class are implemented by the defining
 285.400 @@ -1091,8 +1419,11 @@
 285.401       * @since  JDK1.1
 285.402       */
 285.403      public java.net.URL getResource(String name) {
 285.404 -        InputStream is = getResourceAsStream(name);
 285.405 -        return is == null ? null : newResourceURL(URL.class, "res:/" + name, is);
 285.406 +        return newResourceURL(name, getResourceAsStream(name));
 285.407 +    }
 285.408 +
 285.409 +    static URL newResourceURL(String name, InputStream is) {
 285.410 +        return is == null ? null : newResourceURL0(URL.class, "res:/" + name, is);
 285.411      }
 285.412      
 285.413      @JavaScriptBody(args = { "url", "spec", "is" }, body = 
 285.414 @@ -1100,7 +1431,7 @@
 285.415        + "u.constructor.cons__VLjava_lang_String_2Ljava_io_InputStream_2.call(u, spec, is);\n"
 285.416        + "return u;"
 285.417      )
 285.418 -    private static native URL newResourceURL(Class<URL> url, String spec, InputStream is);
 285.419 +    private static native URL newResourceURL0(Class<URL> url, String spec, InputStream is);
 285.420  
 285.421     /**
 285.422       * Add a package name prefix if the name is not absolute Remove leading "/"
 285.423 @@ -1154,7 +1485,7 @@
 285.424       * @see java.lang.RuntimePermission
 285.425       */
 285.426      public ClassLoader getClassLoader() {
 285.427 -        throw new SecurityException();
 285.428 +        return ClassLoader.getSystemClassLoader();
 285.429      }
 285.430  
 285.431      /**
 285.432 @@ -1331,9 +1662,11 @@
 285.433  
 285.434      @JavaScriptBody(args = { "ac" }, 
 285.435          body = 
 285.436 -          "if (this.anno) {"
 285.437 -        + "  return this.anno['L' + ac.jvmName + ';'];"
 285.438 -        + "} else return null;"
 285.439 +          "if (this.anno) {\n"
 285.440 +        + "  var r = this.anno['L' + ac.jvmName + ';'];\n"
 285.441 +        + "  if (typeof r === 'undefined') r = null;\n"
 285.442 +        + "  return r;\n"
 285.443 +        + "} else return null;\n"
 285.444      )
 285.445      private Object getAnnotationData(Class<?> annotationClass) {
 285.446          throw new UnsupportedOperationException();
 285.447 @@ -1395,4 +1728,50 @@
 285.448          "return vm.desiredAssertionStatus ? vm.desiredAssertionStatus : false;"
 285.449      )
 285.450      public native boolean desiredAssertionStatus();
 285.451 +    
 285.452 +    static void registerNatives() {
 285.453 +        boolean assertsOn = false;
 285.454 +        //       assert assertsOn = true;
 285.455 +        if (assertsOn) {
 285.456 +            try {
 285.457 +                Array.get(null, 0);
 285.458 +            } catch (Throwable ex) {
 285.459 +                // ignore
 285.460 +            }
 285.461 +        }
 285.462 +    }
 285.463 +
 285.464 +    @JavaScriptBody(args = {}, body = "var p = vm.java_lang_Object(false);"
 285.465 +            + "p.toString = function() { return this.toString__Ljava_lang_String_2(); };"
 285.466 +    )
 285.467 +    static native void registerToString();
 285.468 +    
 285.469 +    @JavaScriptBody(args = {"self"}, body
 285.470 +            = "var c = self.constructor.$class;\n"
 285.471 +            + "return c ? c : null;\n"
 285.472 +    )
 285.473 +    static native Class<?> classFor(Object self);
 285.474 +    
 285.475 +    @JavaScriptBody(args = { "self" }, body
 285.476 +            = "if (self.$hashCode) return self.$hashCode;\n"
 285.477 +            + "var h = self.computeHashCode__I ? self.computeHashCode__I() : Math.random() * Math.pow(2, 31);\n"
 285.478 +            + "return self.$hashCode = h & h;"
 285.479 +    )
 285.480 +    static native int defaultHashCode(Object self);
 285.481 +
 285.482 +    @JavaScriptBody(args = "self", body
 285.483 +            = "\nif (!self['$instOf_java_lang_Cloneable']) {"
 285.484 +            + "\n  return null;"
 285.485 +            + "\n} else {"
 285.486 +            + "\n  var clone = self.constructor(true);"
 285.487 +            + "\n  var props = Object.getOwnPropertyNames(self);"
 285.488 +            + "\n  for (var i = 0; i < props.length; i++) {"
 285.489 +            + "\n    var p = props[i];"
 285.490 +            + "\n    clone[p] = self[p];"
 285.491 +            + "\n  };"
 285.492 +            + "\n  return clone;"
 285.493 +            + "\n}"
 285.494 +    )
 285.495 +    static native Object clone(Object self) throws CloneNotSupportedException;
 285.496 +    
 285.497  }
   286.1 --- a/rt/emul/mini/src/main/java/java/lang/ClassLoader.java	Tue Apr 29 15:25:58 2014 +0200
   286.2 +++ b/rt/emul/mini/src/main/java/java/lang/ClassLoader.java	Wed Apr 30 15:04:10 2014 +0200
   286.3 @@ -24,6 +24,7 @@
   286.4   */
   286.5  package java.lang;
   286.6  
   286.7 +import java.io.ByteArrayInputStream;
   286.8  import java.io.InputStream;
   286.9  import java.io.IOException;
  286.10  import java.net.URL;
  286.11 @@ -180,7 +181,7 @@
  286.12       * @since  1.2
  286.13       */
  286.14      protected ClassLoader(ClassLoader parent) {
  286.15 -        throw new SecurityException();
  286.16 +        this.parent = parent;
  286.17      }
  286.18  
  286.19      /**
  286.20 @@ -199,7 +200,7 @@
  286.21       *          of a new class loader.
  286.22       */
  286.23      protected ClassLoader() {
  286.24 -        throw new SecurityException();
  286.25 +        this.parent = null;
  286.26      }
  286.27  
  286.28      // -- Class --
  286.29 @@ -845,8 +846,27 @@
  286.30       * @revised  1.4
  286.31       */
  286.32      public static ClassLoader getSystemClassLoader() {
  286.33 -        throw new SecurityException();
  286.34 +        if (SYSTEM == null) {
  286.35 +            SYSTEM = new ClassLoader() {
  286.36 +                @Override
  286.37 +                protected Enumeration<URL> findResources(String name) throws IOException {
  286.38 +                    return getBootstrapResources(name);
  286.39 +                }
  286.40 +
  286.41 +                @Override
  286.42 +                protected URL findResource(String name) {
  286.43 +                    return getBootstrapResource(name);
  286.44 +                }
  286.45 +
  286.46 +                @Override
  286.47 +                protected Class<?> findClass(String name) throws ClassNotFoundException {
  286.48 +                    return Class.forName(name);
  286.49 +                }
  286.50 +            };
  286.51 +        }
  286.52 +        return SYSTEM;
  286.53      }
  286.54 +    private static ClassLoader SYSTEM;
  286.55  
  286.56      // Returns true if the specified class loader can be found in this class
  286.57      // loader's delegation chain.
  286.58 @@ -870,12 +890,48 @@
  286.59      }
  286.60  
  286.61      private static URL getBootstrapResource(String name) {
  286.62 -        throw new UnsupportedOperationException();
  286.63 +        return Object.class.getResource("/" + name);
  286.64      }
  286.65  
  286.66 +    @JavaScriptBody(args = { "name", "skip" }, body
  286.67 +        = "return (vm.loadBytes) ? vm.loadBytes(name, skip) : null;"
  286.68 +    )
  286.69 +    static native byte[] getResourceAsStream0(String name, int skip);
  286.70 +
  286.71      private static Enumeration<URL> getBootstrapResources(String name) {
  286.72 -        URL u = Object.class.getResource("/" + name);
  286.73 -        return new OneOrZeroEnum(u);
  286.74 +        return new ResEnum(name);
  286.75 +    }
  286.76 +    
  286.77 +    private static class ResEnum implements Enumeration<URL> {
  286.78 +        private final String name;
  286.79 +        private URL next;
  286.80 +        private int skip;
  286.81 +
  286.82 +        public ResEnum(String name) {
  286.83 +            this.name = name;
  286.84 +        }
  286.85 +
  286.86 +
  286.87 +        public boolean hasMoreElements() {
  286.88 +            if (next == null && skip >= 0) {
  286.89 +                byte[] arr = getResourceAsStream0(name, skip++);
  286.90 +                if (arr != null) {
  286.91 +                    next = Class.newResourceURL(name, new ByteArrayInputStream(arr));
  286.92 +                } else {
  286.93 +                    skip = -1;
  286.94 +                }
  286.95 +            }
  286.96 +            return next != null;
  286.97 +        }
  286.98 +
  286.99 +        public URL nextElement() {
 286.100 +            URL r = next;
 286.101 +            if (r == null) {
 286.102 +                throw new NoSuchElementException();
 286.103 +            }
 286.104 +            next = null;
 286.105 +            return r;
 286.106 +        }
 286.107      }
 286.108      
 286.109      private static class OneOrZeroEnum implements Enumeration<URL> {
 286.110 @@ -910,7 +966,7 @@
 286.111          }
 286.112  
 286.113          public boolean hasMoreElements() {
 286.114 -            if (next == null) {
 286.115 +            if (next == null && index < arr.length) {
 286.116                  if (arr[index].hasMoreElements()) {
 286.117                      next = (URL) arr[index].nextElement();
 286.118                  } else {
   287.1 --- a/rt/emul/mini/src/main/java/java/lang/Double.java	Tue Apr 29 15:25:58 2014 +0200
   287.2 +++ b/rt/emul/mini/src/main/java/java/lang/Double.java	Wed Apr 30 15:04:10 2014 +0200
   287.3 @@ -502,10 +502,8 @@
   287.4       * @throws     NumberFormatException  if the string does not contain a
   287.5       *             parsable number.
   287.6       */
   287.7 -    @JavaScriptBody(args="s", body="return parseFloat(s);")
   287.8      public static Double valueOf(String s) throws NumberFormatException {
   287.9 -        throw new UnsupportedOperationException();
  287.10 -//        return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
  287.11 +        return new Double(parseDouble(s));
  287.12      }
  287.13  
  287.14      /**
  287.15 @@ -542,8 +540,7 @@
  287.16       */
  287.17      @JavaScriptBody(args="s", body="return parseFloat(s);")
  287.18      public static double parseDouble(String s) throws NumberFormatException {
  287.19 -        throw new UnsupportedOperationException();
  287.20 -//        return FloatingDecimal.readJavaFormatString(s).doubleValue();
  287.21 +        return 0;
  287.22      }
  287.23  
  287.24      /**
   288.1 --- a/rt/emul/mini/src/main/java/java/lang/Enum.java	Tue Apr 29 15:25:58 2014 +0200
   288.2 +++ b/rt/emul/mini/src/main/java/java/lang/Enum.java	Wed Apr 30 15:04:10 2014 +0200
   288.3 @@ -235,7 +235,7 @@
   288.4          throw new IllegalArgumentException();
   288.5      }
   288.6      
   288.7 -    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
   288.8 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.fld_$VALUES;")
   288.9      private static native Object[] values(Class<?> enumType);
  288.10  
  288.11      /**
   289.1 --- a/rt/emul/mini/src/main/java/java/lang/Float.java	Tue Apr 29 15:25:58 2014 +0200
   289.2 +++ b/rt/emul/mini/src/main/java/java/lang/Float.java	Wed Apr 30 15:04:10 2014 +0200
   289.3 @@ -412,8 +412,7 @@
   289.4       *          parsable number.
   289.5       */
   289.6      public static Float valueOf(String s) throws NumberFormatException {
   289.7 -        throw new UnsupportedOperationException();
   289.8 -//        return new Float(FloatingDecimal.readJavaFormatString(s).floatValue());
   289.9 +        return new Float(parseFloat(s));
  289.10      }
  289.11  
  289.12      /**
  289.13 @@ -447,9 +446,9 @@
  289.14       * @see    java.lang.Float#valueOf(String)
  289.15       * @since 1.2
  289.16       */
  289.17 +    @JavaScriptBody(args="s", body="return parseFloat(s);")
  289.18      public static float parseFloat(String s) throws NumberFormatException {
  289.19 -        throw new UnsupportedOperationException();
  289.20 -//        return FloatingDecimal.readJavaFormatString(s).floatValue();
  289.21 +        return 0;
  289.22      }
  289.23  
  289.24      /**
   290.1 --- a/rt/emul/mini/src/main/java/java/lang/Object.java	Tue Apr 29 15:25:58 2014 +0200
   290.2 +++ b/rt/emul/mini/src/main/java/java/lang/Object.java	Wed Apr 30 15:04:10 2014 +0200
   290.3 @@ -25,7 +25,6 @@
   290.4  
   290.5  package java.lang;
   290.6  
   290.7 -import java.lang.reflect.Array;
   290.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   290.9  import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
  290.10  
  290.11 @@ -40,23 +39,9 @@
  290.12   */
  290.13  @JavaScriptPrototype(container = "Object.prototype", prototype = "new Object")
  290.14  public class Object {
  290.15 -
  290.16 -    private static void registerNatives() {
  290.17 -        boolean assertsOn = false;
  290.18 -        assert assertsOn = false;
  290.19 -        if (assertsOn) try {
  290.20 -            Array.get(null, 0);
  290.21 -        } catch (Throwable ex) {
  290.22 -            // ignore
  290.23 -        }
  290.24 -    }
  290.25 -    @JavaScriptBody(args = {}, body = "var p = vm.java_lang_Object(false);" +
  290.26 -        "p.toString = function() { return this.toString__Ljava_lang_String_2(); };"
  290.27 -    )
  290.28 -    private static native void registerToString();
  290.29      static {
  290.30 -        registerNatives();
  290.31 -        registerToString();
  290.32 +        Class.registerNatives();
  290.33 +        Class.registerToString();
  290.34      }
  290.35  
  290.36      /**
  290.37 @@ -79,8 +64,10 @@
  290.38       * @see    Class Literals, section 15.8.2 of
  290.39       *         <cite>The Java&trade; Language Specification</cite>.
  290.40       */
  290.41 -    @JavaScriptBody(args={}, body="return this.constructor.$class;")
  290.42 -    public final native Class<?> getClass();
  290.43 +    public final Class<?> getClass() {
  290.44 +        Class<?> c = Class.classFor(this);
  290.45 +        return c == null ? Object.class : c;
  290.46 +    }
  290.47  
  290.48      /**
  290.49       * Returns a hash code value for the object. This method is
  290.50 @@ -117,16 +104,10 @@
  290.51       * @see     java.lang.Object#equals(java.lang.Object)
  290.52       * @see     java.lang.System#identityHashCode
  290.53       */
  290.54 -    @JavaScriptBody(args = {}, body = 
  290.55 -        "if (this.$hashCode) return this.$hashCode;\n"
  290.56 -        + "var h = this.computeHashCode__I();\n"
  290.57 -        + "return this.$hashCode = h & h;"
  290.58 -    )
  290.59 -    public native int hashCode();
  290.60 +    public int hashCode() {
  290.61 +        return Class.defaultHashCode(this);
  290.62 +    }
  290.63  
  290.64 -    @JavaScriptBody(args = {}, body = "return Math.random() * Math.pow(2, 32);")
  290.65 -    native int computeHashCode();
  290.66 -    
  290.67      /**
  290.68       * Indicates whether some other object is "equal to" this one.
  290.69       * <p>
  290.70 @@ -238,28 +219,13 @@
  290.71       * @see java.lang.Cloneable
  290.72       */
  290.73      protected Object clone() throws CloneNotSupportedException {
  290.74 -        Object ret = clone(this);
  290.75 +        Object ret = Class.clone(this);
  290.76          if (ret == null) {
  290.77              throw new CloneNotSupportedException(getClass().getName());
  290.78          }
  290.79          return ret;
  290.80      }
  290.81  
  290.82 -    @JavaScriptBody(args = "self", body = 
  290.83 -          "\nif (!self['$instOf_java_lang_Cloneable']) {"
  290.84 -        + "\n  return null;"
  290.85 -        + "\n} else {"
  290.86 -        + "\n  var clone = self.constructor(true);"
  290.87 -        + "\n  var props = Object.getOwnPropertyNames(self);"
  290.88 -        + "\n  for (var i = 0; i < props.length; i++) {"
  290.89 -        + "\n    var p = props[i];"
  290.90 -        + "\n    clone[p] = self[p];"
  290.91 -        + "\n  };"
  290.92 -        + "\n  return clone;"
  290.93 -        + "\n}"
  290.94 -    )
  290.95 -    private static native Object clone(Object self) throws CloneNotSupportedException;
  290.96 -
  290.97      /**
  290.98       * Returns a string representation of the object. In general, the
  290.99       * {@code toString} method returns a string that
 290.100 @@ -317,7 +283,8 @@
 290.101       * @see        java.lang.Object#notifyAll()
 290.102       * @see        java.lang.Object#wait()
 290.103       */
 290.104 -    public final native void notify();
 290.105 +    public final void notify() {
 290.106 +    }
 290.107  
 290.108      /**
 290.109       * Wakes up all threads that are waiting on this object's monitor. A
 290.110 @@ -341,7 +308,8 @@
 290.111       * @see        java.lang.Object#notify()
 290.112       * @see        java.lang.Object#wait()
 290.113       */
 290.114 -    public final native void notifyAll();
 290.115 +    public final void notifyAll() {
 290.116 +    }
 290.117  
 290.118      /**
 290.119       * Causes the current thread to wait until either another thread invokes the
 290.120 @@ -428,7 +396,9 @@
 290.121       * @see        java.lang.Object#notify()
 290.122       * @see        java.lang.Object#notifyAll()
 290.123       */
 290.124 -    public final native void wait(long timeout) throws InterruptedException;
 290.125 +    public final void wait(long timeout) throws InterruptedException {
 290.126 +        throw new InterruptedException();
 290.127 +    }
 290.128  
 290.129      /**
 290.130       * Causes the current thread to wait until another thread invokes the
 290.131 @@ -493,20 +463,7 @@
 290.132       *             this exception is thrown.
 290.133       */
 290.134      public final void wait(long timeout, int nanos) throws InterruptedException {
 290.135 -        if (timeout < 0) {
 290.136 -            throw new IllegalArgumentException("timeout value is negative");
 290.137 -        }
 290.138 -
 290.139 -        if (nanos < 0 || nanos > 999999) {
 290.140 -            throw new IllegalArgumentException(
 290.141 -                                "nanosecond timeout value out of range");
 290.142 -        }
 290.143 -
 290.144 -        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
 290.145 -            timeout++;
 290.146 -        }
 290.147 -
 290.148 -        wait(timeout);
 290.149 +        throw new InterruptedException();
 290.150      }
 290.151  
 290.152      /**
 290.153 @@ -548,7 +505,7 @@
 290.154       * @see        java.lang.Object#notifyAll()
 290.155       */
 290.156      public final void wait() throws InterruptedException {
 290.157 -        wait(0);
 290.158 +        throw new InterruptedException();
 290.159      }
 290.160  
 290.161      /**
   291.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java	Tue Apr 29 15:25:58 2014 +0200
   291.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java	Wed Apr 30 15:04:10 2014 +0200
   291.3 @@ -26,7 +26,10 @@
   291.4  package java.lang;
   291.5  
   291.6  import java.io.UnsupportedEncodingException;
   291.7 +import java.lang.reflect.InvocationTargetException;
   291.8 +import java.lang.reflect.Method;
   291.9  import java.util.Comparator;
  291.10 +import java.util.Locale;
  291.11  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
  291.12  import org.apidesign.bck2brwsr.core.JavaScriptBody;
  291.13  import org.apidesign.bck2brwsr.core.JavaScriptOnly;
  291.14 @@ -2097,13 +2100,31 @@
  291.15       * @since 1.4
  291.16       * @spec JSR-51
  291.17       */
  291.18 +    public boolean matches(String regex) {
  291.19 +        try {
  291.20 +            return matchesViaJS(regex);
  291.21 +        } catch (Throwable t) {
  291.22 +            // fallback to classical behavior
  291.23 +            try {
  291.24 +                Method m = Class.forName("java.util.regex.Pattern").getMethod("matches", String.class, CharSequence.class);
  291.25 +                return (Boolean)m.invoke(null, regex, this);
  291.26 +            } catch (InvocationTargetException ex) {
  291.27 +                if (ex.getTargetException() instanceof RuntimeException) {
  291.28 +                    throw (RuntimeException)ex.getTargetException();
  291.29 +                }
  291.30 +            } catch (Throwable another) {
  291.31 +                // will report the old one
  291.32 +            }
  291.33 +            throw new RuntimeException(t);
  291.34 +        }
  291.35 +    }
  291.36      @JavaScriptBody(args = { "regex" }, body = 
  291.37            "var self = this.toString();\n"
  291.38          + "var re = new RegExp(regex.toString());\n"
  291.39          + "var r = re.exec(self);\n"
  291.40          + "return r != null && r.length > 0 && self.length == r[0].length;"
  291.41      )
  291.42 -    public boolean matches(String regex) {
  291.43 +    private boolean matchesViaJS(String regex) {
  291.44          throw new UnsupportedOperationException();
  291.45      }
  291.46  
  291.47 @@ -2159,6 +2180,14 @@
  291.48       * @since 1.4
  291.49       * @spec JSR-51
  291.50       */
  291.51 +    @JavaScriptBody(args = { "regex", "newText" }, body = 
  291.52 +          "var self = this.toString();\n"
  291.53 +        + "var re = new RegExp(regex.toString());\n"
  291.54 +        + "var r = re.exec(self);\n"
  291.55 +        + "if (r === null || r.length === 0) return this;\n"
  291.56 +        + "var from = self.indexOf(r[0]);\n"
  291.57 +        + "return this.substring(0, from) + newText + this.substring(from + r[0].length);\n"
  291.58 +    )
  291.59      public String replaceFirst(String regex, String replacement) {
  291.60          throw new UnsupportedOperationException();
  291.61      }
  291.62 @@ -2203,7 +2232,14 @@
  291.63       * @spec JSR-51
  291.64       */
  291.65      public String replaceAll(String regex, String replacement) {
  291.66 -        throw new UnsupportedOperationException();
  291.67 +        String p = this;
  291.68 +        for (;;) {
  291.69 +            String n = p.replaceFirst(regex, replacement);
  291.70 +            if (n == p) {
  291.71 +                return n;
  291.72 +            }
  291.73 +            p = n;
  291.74 +        }
  291.75      }
  291.76  
  291.77      /**
  291.78 @@ -2224,12 +2260,14 @@
  291.79            "var s = this.toString();\n"
  291.80          + "target = target.toString();\n"
  291.81          + "replacement = replacement.toString();\n"
  291.82 +        + "var pos = 0;\n"
  291.83          + "for (;;) {\n"
  291.84 -        + "  var ret = s.replace(target, replacement);\n"
  291.85 -        + "  if (ret === s) {\n"
  291.86 -        + "    return ret;\n"
  291.87 +        + "  var indx = s.indexOf(target, pos);\n"
  291.88 +        + "  if (indx === -1) {\n"
  291.89 +        + "    return s;\n"
  291.90          + "  }\n"
  291.91 -        + "  s = ret;\n"
  291.92 +        + "  pos = indx + replacement.length;\n"
  291.93 +        + "  s = s.substring(0, indx) + replacement + s.substring(indx + target.length);\n"
  291.94          + "}"
  291.95      )
  291.96      public native String replace(CharSequence target, CharSequence replacement);
  291.97 @@ -2315,8 +2353,35 @@
  291.98       * @spec JSR-51
  291.99       */
 291.100      public String[] split(String regex, int limit) {
 291.101 -        throw new UnsupportedOperationException("Needs regexp");
 291.102 +        if (limit <= 0) {
 291.103 +            Object[] arr = splitImpl(this, regex, Integer.MAX_VALUE);
 291.104 +            int to = arr.length;
 291.105 +            if (limit == 0 && to > 0) {
 291.106 +                while (to > 0 && ((String)arr[--to]).isEmpty()) {
 291.107 +                }
 291.108 +                to++;
 291.109 +            }
 291.110 +            String[] ret = new String[to];
 291.111 +            System.arraycopy(arr, 0, ret, 0, to);
 291.112 +            return ret;
 291.113 +        } else {
 291.114 +            Object[] arr = splitImpl(this, regex, limit);
 291.115 +            String[] ret = new String[arr.length];
 291.116 +            int pos = 0;
 291.117 +            for (int i = 0; i < arr.length; i++) {
 291.118 +                final String s = (String)arr[i];
 291.119 +                ret[i] = s;
 291.120 +                pos = indexOf(s, pos) + s.length();
 291.121 +            }
 291.122 +            ret[arr.length - 1] += substring(pos);
 291.123 +            return ret;
 291.124 +        }
 291.125      }
 291.126 +    
 291.127 +    @JavaScriptBody(args = { "str", "regex", "limit"}, body = 
 291.128 +        "return str.split(new RegExp(regex), limit);"
 291.129 +    )
 291.130 +    private static native Object[] splitImpl(String str, String regex, int limit);
 291.131  
 291.132      /**
 291.133       * Splits this string around matches of the given <a
 291.134 @@ -2412,7 +2477,9 @@
 291.135       * @see     java.lang.String#toUpperCase(Locale)
 291.136       * @since   1.1
 291.137       */
 291.138 -//    public String toLowerCase(Locale locale) {
 291.139 +    public String toLowerCase(java.util.Locale locale) {
 291.140 +        return toLowerCase();
 291.141 +    }
 291.142  //        if (locale == null) {
 291.143  //            throw new NullPointerException();
 291.144  //        }
 291.145 @@ -2527,7 +2594,7 @@
 291.146       */
 291.147      @JavaScriptBody(args = {}, body = "return this.toLowerCase();")
 291.148      public String toLowerCase() {
 291.149 -        throw new UnsupportedOperationException("Should be supported but without connection to locale");
 291.150 +        return null;
 291.151      }
 291.152  
 291.153      /**
 291.154 @@ -2578,8 +2645,10 @@
 291.155       * @see     java.lang.String#toLowerCase(Locale)
 291.156       * @since   1.1
 291.157       */
 291.158 +    public String toUpperCase(Locale locale) {
 291.159 +        return toUpperCase();
 291.160 +    }
 291.161      /* not for javascript 
 291.162 -    public String toUpperCase(Locale locale) {
 291.163          if (locale == null) {
 291.164              throw new NullPointerException();
 291.165          }
 291.166 @@ -2693,7 +2762,7 @@
 291.167       */
 291.168      @JavaScriptBody(args = {}, body = "return this.toUpperCase();")
 291.169      public String toUpperCase() {
 291.170 -        throw new UnsupportedOperationException();
 291.171 +        return null;
 291.172      }
 291.173  
 291.174      /**
 291.175 @@ -2804,7 +2873,7 @@
 291.176       * @since  1.5
 291.177       */
 291.178      public static String format(String format, Object ... args) {
 291.179 -        throw new UnsupportedOperationException();
 291.180 +        return format((Locale)null, format, args);
 291.181      }
 291.182  
 291.183      /**
 291.184 @@ -2847,9 +2916,15 @@
 291.185       * @see  java.util.Formatter
 291.186       * @since  1.5
 291.187       */
 291.188 -//    public static String format(Locale l, String format, Object ... args) {
 291.189 -//        return new Formatter(l).format(format, args).toString();
 291.190 -//    }
 291.191 +    public static String format(Locale l, String format, Object ... args) {
 291.192 +        String p = format;
 291.193 +        for (int i = 0; i < args.length; i++) {
 291.194 +            String v = args[i] == null ? "null" : args[i].toString();
 291.195 +            p = p.replaceFirst("%s", v);
 291.196 +        }
 291.197 +        return p;
 291.198 +        // return new Formatter(l).format(format, args).toString();
 291.199 +    }
 291.200  
 291.201      /**
 291.202       * Returns the string representation of the <code>Object</code> argument.
 291.203 @@ -3034,6 +3109,14 @@
 291.204       * @return  a string that has the same contents as this string, but is
 291.205       *          guaranteed to be from a pool of unique strings.
 291.206       */
 291.207 +    @JavaScriptBody(args = {}, body = 
 291.208 +        "var s = this.toString().toString();\n" +
 291.209 +        "var i = String.intern || (String.intern = {})\n" + 
 291.210 +        "if (!i[s]) {\n" +
 291.211 +        "  i[s] = s;\n" +
 291.212 +        "}\n" +
 291.213 +        "return i[s];"
 291.214 +    )
 291.215      public native String intern();
 291.216      
 291.217      
   292.1 --- a/rt/emul/mini/src/main/java/java/lang/Throwable.java	Tue Apr 29 15:25:58 2014 +0200
   292.2 +++ b/rt/emul/mini/src/main/java/java/lang/Throwable.java	Wed Apr 30 15:04:10 2014 +0200
   292.3 @@ -638,94 +638,34 @@
   292.4       *          ... 2 more
   292.5       * </pre>
   292.6       */
   292.7 -//    public void printStackTrace() {
   292.8 -//        printStackTrace(System.err);
   292.9 -//    }
  292.10 -//
  292.11 -//    /**
  292.12 -//     * Prints this throwable and its backtrace to the specified print stream.
  292.13 -//     *
  292.14 -//     * @param s {@code PrintStream} to use for output
  292.15 -//     */
  292.16 -//    public void printStackTrace(PrintStream s) {
  292.17 -//        printStackTrace(new WrappedPrintStream(s));
  292.18 -//    }
  292.19 -//
  292.20 -//    private void printStackTrace(PrintStreamOrWriter s) {
  292.21 -//        // Guard against malicious overrides of Throwable.equals by
  292.22 -//        // using a Set with identity equality semantics.
  292.23 -////        Set<Throwable> dejaVu =
  292.24 -////            Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
  292.25 -////        dejaVu.add(this);
  292.26 -//
  292.27 -//        synchronized (s.lock()) {
  292.28 -//            // Print our stack trace
  292.29 -//            s.println(this);
  292.30 -//            StackTraceElement[] trace = getOurStackTrace();
  292.31 -//            for (StackTraceElement traceElement : trace)
  292.32 -//                s.println("\tat " + traceElement);
  292.33 -//
  292.34 -//            // Print suppressed exceptions, if any
  292.35 -////            for (Throwable se : getSuppressed())
  292.36 -////                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
  292.37 -//
  292.38 -//            // Print cause, if any
  292.39 -//            Throwable ourCause = getCause();
  292.40 -////            if (ourCause != null)
  292.41 -////                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
  292.42 -//        }
  292.43 -//    }
  292.44 -//
  292.45 -//    /**
  292.46 -//     * Print our stack trace as an enclosed exception for the specified
  292.47 -//     * stack trace.
  292.48 -//     */
  292.49 -//    private void printEnclosedStackTrace(PrintStreamOrWriter s,
  292.50 -//                                         StackTraceElement[] enclosingTrace,
  292.51 -//                                         String caption,
  292.52 -//                                         String prefix,
  292.53 -//                                         Object dejaVu) {
  292.54 -//        assert Thread.holdsLock(s.lock());
  292.55 -//        {
  292.56 -//            // Compute number of frames in common between this and enclosing trace
  292.57 -//            StackTraceElement[] trace = getOurStackTrace();
  292.58 -//            int m = trace.length - 1;
  292.59 -//            int n = enclosingTrace.length - 1;
  292.60 -//            while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
  292.61 -//                m--; n--;
  292.62 -//            }
  292.63 -//            int framesInCommon = trace.length - 1 - m;
  292.64 -//
  292.65 -//            // Print our stack trace
  292.66 -//            s.println(prefix + caption + this);
  292.67 -//            for (int i = 0; i <= m; i++)
  292.68 -//                s.println(prefix + "\tat " + trace[i]);
  292.69 -//            if (framesInCommon != 0)
  292.70 -//                s.println(prefix + "\t... " + framesInCommon + " more");
  292.71 -//
  292.72 -//            // Print suppressed exceptions, if any
  292.73 -//            for (Throwable se : getSuppressed())
  292.74 -//                se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
  292.75 -//                                           prefix +"\t", dejaVu);
  292.76 -//
  292.77 -//            // Print cause, if any
  292.78 -//            Throwable ourCause = getCause();
  292.79 -//            if (ourCause != null)
  292.80 -//                ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
  292.81 -//        }
  292.82 -//    }
  292.83 -//
  292.84 -//    /**
  292.85 -//     * Prints this throwable and its backtrace to the specified
  292.86 -//     * print writer.
  292.87 -//     *
  292.88 -//     * @param s {@code PrintWriter} to use for output
  292.89 -//     * @since   JDK1.1
  292.90 -//     */
  292.91 -//    public void printStackTrace(PrintWriter s) {
  292.92 -//        printStackTrace(new WrappedPrintWriter(s));
  292.93 -//    }
  292.94 -//
  292.95 +    public void printStackTrace() {
  292.96 +        warn(getClass().getName() + ": " + getMessage());
  292.97 +    }
  292.98 +    @JavaScriptBody(args = { "msg" }, body = "if (console) console.warn(msg.toString());")
  292.99 +    private native void warn(String msg);
 292.100 +
 292.101 +    /**
 292.102 +     * Prints this throwable and its backtrace to the specified print stream.
 292.103 +     *
 292.104 +     * @param s {@code PrintStream} to use for output
 292.105 +     */
 292.106 +    public void printStackTrace(PrintStream s) {
 292.107 +        s.print(getClass().getName());
 292.108 +        s.print(": ");
 292.109 +        s.println(getMessage());
 292.110 +    }
 292.111 +
 292.112 +    /**
 292.113 +     * Prints this throwable and its backtrace to the specified
 292.114 +     * print writer.
 292.115 +     *
 292.116 +     * @param s {@code PrintWriter} to use for output
 292.117 +     * @since   JDK1.1
 292.118 +     */
 292.119 +    public void printStackTrace(PrintWriter s) {
 292.120 +        s.append(getClass().getName()).append(": ").println(getMessage());
 292.121 +    }
 292.122 +
 292.123  //    /**
 292.124  //     * Wrapper class for PrintStream and PrintWriter to enable a single
 292.125  //     * implementation of printStackTrace.
   293.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java	Tue Apr 29 15:25:58 2014 +0200
   293.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java	Wed Apr 30 15:04:10 2014 +0200
   293.3 @@ -107,7 +107,7 @@
   293.4          if (type.getName().equals("void")) {
   293.5              throw new IllegalStateException("Can't create array for " + type);
   293.6          }
   293.7 -        return "[L" + type.getName() + ";";
   293.8 +        return "[L" + type.getName().replace('.', '/') + ";";
   293.9      }
  293.10      /**
  293.11       * Creates a new array
   294.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Tue Apr 29 15:25:58 2014 +0200
   294.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Constructor.java	Wed Apr 30 15:04:10 2014 +0200
   294.3 @@ -26,6 +26,10 @@
   294.4  package java.lang.reflect;
   294.5  
   294.6  import java.lang.annotation.Annotation;
   294.7 +import static java.lang.reflect.Method.fromPrimitive;
   294.8 +import static java.lang.reflect.Method.getAccess;
   294.9 +import static java.lang.reflect.Method.getParameterTypes;
  294.10 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  294.11  import org.apidesign.bck2brwsr.emul.reflect.TypeProvider;
  294.12  
  294.13  /**
  294.14 @@ -53,44 +57,20 @@
  294.15                                                      GenericDeclaration,
  294.16                                                      Member {
  294.17  
  294.18 -    private Class<T>            clazz;
  294.19 -    private int                 slot;
  294.20 -    private Class<?>[]          parameterTypes;
  294.21 -    private Class<?>[]          exceptionTypes;
  294.22 -    private int                 modifiers;
  294.23 -    // Generics and annotations support
  294.24 -    private transient String    signature;
  294.25 -    private byte[]              annotations;
  294.26 -    private byte[]              parameterAnnotations;
  294.27 -
  294.28 -
  294.29 -    // For sharing of ConstructorAccessors. This branching structure
  294.30 -    // is currently only two levels deep (i.e., one root Constructor
  294.31 -    // and potentially many Constructor objects pointing to it.)
  294.32 -    private Constructor<T>      root;
  294.33 +    private final Class<T> clazz;
  294.34 +    private final Object data;
  294.35 +    private final String sig;
  294.36  
  294.37      /**
  294.38       * Package-private constructor used by ReflectAccess to enable
  294.39       * instantiation of these objects in Java code from the java.lang
  294.40       * package via sun.reflect.LangReflectAccess.
  294.41       */
  294.42 -    Constructor(Class<T> declaringClass,
  294.43 -                Class<?>[] parameterTypes,
  294.44 -                Class<?>[] checkedExceptions,
  294.45 -                int modifiers,
  294.46 -                int slot,
  294.47 -                String signature,
  294.48 -                byte[] annotations,
  294.49 -                byte[] parameterAnnotations)
  294.50 +    Constructor(Class<T> declaringClass, Object data, String sig)
  294.51      {
  294.52          this.clazz = declaringClass;
  294.53 -        this.parameterTypes = parameterTypes;
  294.54 -        this.exceptionTypes = checkedExceptions;
  294.55 -        this.modifiers = modifiers;
  294.56 -        this.slot = slot;
  294.57 -        this.signature = signature;
  294.58 -        this.annotations = annotations;
  294.59 -        this.parameterAnnotations = parameterAnnotations;
  294.60 +        this.data = data;
  294.61 +        this.sig = sig;
  294.62      }
  294.63  
  294.64      /**
  294.65 @@ -126,7 +106,7 @@
  294.66       * @see Modifier
  294.67       */
  294.68      public int getModifiers() {
  294.69 -        return modifiers;
  294.70 +        return getAccess(data);
  294.71      }
  294.72  
  294.73      /**
  294.74 @@ -159,7 +139,7 @@
  294.75       * represents
  294.76       */
  294.77      public Class<?>[] getParameterTypes() {
  294.78 -        return (Class<?>[]) parameterTypes.clone();
  294.79 +        return Method.getParameterTypes(sig);
  294.80      }
  294.81  
  294.82  
  294.83 @@ -205,7 +185,7 @@
  294.84       * constructor this object represents
  294.85       */
  294.86      public Class<?>[] getExceptionTypes() {
  294.87 -        return (Class<?>[])exceptionTypes.clone();
  294.88 +        return new Class[0];
  294.89      }
  294.90  
  294.91  
  294.92 @@ -242,20 +222,9 @@
  294.93       * same formal parameter types.
  294.94       */
  294.95      public boolean equals(Object obj) {
  294.96 -        if (obj != null && obj instanceof Constructor) {
  294.97 -            Constructor<?> other = (Constructor<?>)obj;
  294.98 -            if (getDeclaringClass() == other.getDeclaringClass()) {
  294.99 -                /* Avoid unnecessary cloning */
 294.100 -                Class<?>[] params1 = parameterTypes;
 294.101 -                Class<?>[] params2 = other.parameterTypes;
 294.102 -                if (params1.length == params2.length) {
 294.103 -                    for (int i = 0; i < params1.length; i++) {
 294.104 -                        if (params1[i] != params2[i])
 294.105 -                            return false;
 294.106 -                    }
 294.107 -                    return true;
 294.108 -                }
 294.109 -            }
 294.110 +        if (obj instanceof Constructor) {
 294.111 +            Constructor other = (Constructor)obj;
 294.112 +            return data == other.data;
 294.113          }
 294.114          return false;
 294.115      }
 294.116 @@ -293,13 +262,14 @@
 294.117              }
 294.118              sb.append(Field.getTypeName(getDeclaringClass()));
 294.119              sb.append("(");
 294.120 -            Class<?>[] params = parameterTypes; // avoid clone
 294.121 +            Class<?>[] params = getParameterTypes(); // avoid clone
 294.122              for (int j = 0; j < params.length; j++) {
 294.123                  sb.append(Field.getTypeName(params[j]));
 294.124                  if (j < (params.length - 1))
 294.125                      sb.append(",");
 294.126              }
 294.127              sb.append(")");
 294.128 +            /*
 294.129              Class<?>[] exceptions = exceptionTypes; // avoid clone
 294.130              if (exceptions.length > 0) {
 294.131                  sb.append(" throws ");
 294.132 @@ -309,6 +279,7 @@
 294.133                          sb.append(",");
 294.134                  }
 294.135              }
 294.136 +            */
 294.137              return sb.toString();
 294.138          } catch (Exception e) {
 294.139              return "<" + e + ">";
 294.140 @@ -452,9 +423,29 @@
 294.141          throws InstantiationException, IllegalAccessException,
 294.142                 IllegalArgumentException, InvocationTargetException
 294.143      {
 294.144 -        throw new SecurityException();
 294.145 +        Class[] types = getParameterTypes();
 294.146 +        if (types.length != initargs.length) {
 294.147 +            throw new IllegalArgumentException("Types len " + types.length + " args: " + initargs.length);
 294.148 +        } else {
 294.149 +            initargs = initargs.clone();
 294.150 +            for (int i = 0; i < types.length; i++) {
 294.151 +                Class c = types[i];
 294.152 +                if (c.isPrimitive() && initargs[i] != null) {
 294.153 +                    initargs[i] = Method.toPrimitive(initargs[i]);
 294.154 +                }
 294.155 +            }
 294.156 +        }
 294.157 +        return (T) newInstance0(this.getDeclaringClass(), "cons__" + sig, initargs);
 294.158      }
 294.159  
 294.160 +    @JavaScriptBody(args = { "self", "sig", "args" }, body =
 294.161 +          "\nvar c = self.cnstr;"
 294.162 +        + "\nvar inst = c();"
 294.163 +        + "\nc[sig].apply(inst, args);"
 294.164 +        + "\nreturn inst;"
 294.165 +    )
 294.166 +    private static native Object newInstance0(Class<?> self, String sig, Object[] args);
 294.167 +    
 294.168      /**
 294.169       * Returns {@code true} if this constructor was declared to take
 294.170       * a variable number of arguments; returns {@code false}
 294.171 @@ -481,22 +472,6 @@
 294.172          return Modifier.isSynthetic(getModifiers());
 294.173      }
 294.174  
 294.175 -    int getSlot() {
 294.176 -        return slot;
 294.177 -    }
 294.178 -
 294.179 -   String getSignature() {
 294.180 -            return signature;
 294.181 -   }
 294.182 -
 294.183 -    byte[] getRawAnnotations() {
 294.184 -        return annotations;
 294.185 -    }
 294.186 -
 294.187 -    byte[] getRawParameterAnnotations() {
 294.188 -        return parameterAnnotations;
 294.189 -    }
 294.190 -
 294.191      /**
 294.192       * @throws NullPointerException {@inheritDoc}
 294.193       * @since 1.5
 294.194 @@ -532,11 +507,11 @@
 294.195       * @since 1.5
 294.196       */
 294.197      public Annotation[][] getParameterAnnotations() {
 294.198 -        int numParameters = parameterTypes.length;
 294.199 -        if (parameterAnnotations == null)
 294.200 -            return new Annotation[numParameters][0];
 294.201 +//        int numParameters = parameterTypes.length;
 294.202 +//        if (parameterAnnotations == null)
 294.203 +//            return new Annotation[numParameters][0];
 294.204          
 294.205 -        return new Annotation[numParameters][0]; // XXX
 294.206 +        return new Annotation[0][0]; // XXX
 294.207  /*
 294.208          Annotation[][] result = AnnotationParser.parseParameterAnnotations(
 294.209              parameterAnnotations,
   295.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Tue Apr 29 15:25:58 2014 +0200
   295.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Wed Apr 30 15:04:10 2014 +0200
   295.3 @@ -113,7 +113,7 @@
   295.4      }
   295.5      
   295.6      @JavaScriptBody(args = "self", body = "return self.access;")
   295.7 -    private static native int getAccess(Object self);
   295.8 +    static native int getAccess(Object self);
   295.9      
  295.10      /**
  295.11       * Returns an array of {@code TypeVariable} objects that represent the
  295.12 @@ -183,6 +183,10 @@
  295.13       * represents
  295.14       */
  295.15      public Class<?>[] getParameterTypes() {
  295.16 +        return getParameterTypes(sig);
  295.17 +    }
  295.18 +    
  295.19 +    static Class<?>[] getParameterTypes(String sig) {
  295.20          Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1];
  295.21          Enumeration<Class> en = MethodImpl.signatureParser(sig);
  295.22          en.nextElement(); // return type
  295.23 @@ -235,8 +239,7 @@
  295.24       * method this object represents
  295.25       */
  295.26      public Class<?>[] getExceptionTypes() {
  295.27 -        throw new UnsupportedOperationException();
  295.28 -        //return (Class<?>[]) exceptionTypes.clone();
  295.29 +        return new Class[0];
  295.30      }
  295.31  
  295.32      /**
  295.33 @@ -525,15 +528,17 @@
  295.34      }
  295.35      
  295.36      @JavaScriptBody(args = { "st", "method", "self", "args" }, body =
  295.37 -          "var p;\n"
  295.38 +          "var p; var cll;\n"
  295.39          + "if (st) {\n"
  295.40 +        + "  cll = self[method._name() + '__' + method._sig()];\n"
  295.41          + "  p = new Array(1);\n"
  295.42          + "  p[0] = self;\n"
  295.43          + "  p = p.concat(args);\n"
  295.44          + "} else {\n"
  295.45          + "  p = args;\n"
  295.46 +        + "  cll = method._data();"
  295.47          + "}\n"
  295.48 -        + "return method._data().apply(self, p);\n"
  295.49 +        + "return cll.apply(self, p);\n"
  295.50      )
  295.51      private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
  295.52      
  295.53 @@ -583,7 +588,7 @@
  295.54      private static native Integer fromRaw(Class<?> cls, String m, Object o);
  295.55  
  295.56      @JavaScriptBody(args = { "o" }, body = "return o.valueOf();")
  295.57 -    private static native Object toPrimitive(Object o);
  295.58 +    static native Object toPrimitive(Object o);
  295.59      
  295.60      /**
  295.61       * Returns {@code true} if this method is a bridge
  295.62 @@ -692,6 +697,11 @@
  295.63              protected Method create(Class<?> declaringClass, String name, Object data, String sig) {
  295.64                  return new Method(declaringClass, name, data, sig);
  295.65              }
  295.66 +
  295.67 +            @Override
  295.68 +            protected Constructor create(Class<?> declaringClass, Object data, String sig) {
  295.69 +                return new Constructor(declaringClass, data, sig);
  295.70 +            }
  295.71          };
  295.72      }
  295.73  }
   296.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Tue Apr 29 15:25:58 2014 +0200
   296.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Wed Apr 30 15:04:10 2014 +0200
   296.3 @@ -212,7 +212,16 @@
   296.4  
   296.5      private static final long serialVersionUID = -2222568056686623797L;
   296.6  
   296.7 -
   296.8 +    private final static Method getProxyClass;
   296.9 +    static {
  296.10 +        Class<?> pg;
  296.11 +        try {
  296.12 +            pg = Class.forName("org.apidesign.bck2brwsr.emul.reflect.ProxyImpl");
  296.13 +            getProxyClass = pg.getMethod("getProxyClass", ClassLoader.class, Class[].class);
  296.14 +        } catch (Exception ex) {
  296.15 +            throw new IllegalStateException(ex);
  296.16 +        }
  296.17 +    }
  296.18  
  296.19      /**
  296.20       * the invocation handler for this proxy instance.
  296.21 @@ -315,7 +324,13 @@
  296.22                                           Class<?>... interfaces)
  296.23          throws IllegalArgumentException
  296.24      {
  296.25 -        throw new IllegalArgumentException();
  296.26 +        try {
  296.27 +            return (Class<?>) getProxyClass.invoke(null, loader, interfaces);
  296.28 +        } catch (IllegalAccessException ex) {
  296.29 +            throw new IllegalStateException(ex);
  296.30 +        } catch (InvocationTargetException ex) {
  296.31 +            throw (RuntimeException)ex.getTargetException();
  296.32 +        }
  296.33      }
  296.34  
  296.35      /**
  296.36 @@ -355,7 +370,27 @@
  296.37          if (h == null) {
  296.38              throw new NullPointerException();
  296.39          }
  296.40 -        throw new IllegalArgumentException();
  296.41 +
  296.42 +        /*
  296.43 +         * Look up or generate the designated proxy class.
  296.44 +         */
  296.45 +        Class<?> cl = getProxyClass(loader, interfaces);
  296.46 +
  296.47 +        /*
  296.48 +         * Invoke its constructor with the designated invocation handler.
  296.49 +         */
  296.50 +        try {
  296.51 +            Constructor cons = cl.getConstructor(InvocationHandler.class);
  296.52 +            return cons.newInstance(new Object[] { h });
  296.53 +        } catch (NoSuchMethodException e) {
  296.54 +            throw new IllegalStateException(e.toString());
  296.55 +        } catch (IllegalAccessException e) {
  296.56 +            throw new IllegalStateException(e.toString());
  296.57 +        } catch (InstantiationException e) {
  296.58 +            throw new IllegalStateException(e.toString());
  296.59 +        } catch (InvocationTargetException e) {
  296.60 +            throw new IllegalStateException(e.toString());
  296.61 +        }
  296.62      }
  296.63  
  296.64      /**
  296.65 @@ -376,8 +411,7 @@
  296.66          if (cl == null) {
  296.67              throw new NullPointerException();
  296.68          }
  296.69 -
  296.70 -        return false;
  296.71 +        return Proxy.class.isAssignableFrom(cl);
  296.72      }
  296.73  
  296.74      /**
  296.75 @@ -401,7 +435,4 @@
  296.76          Proxy p = (Proxy) proxy;
  296.77          return p.h;
  296.78      }
  296.79 -
  296.80 -    private static native Class defineClass0(ClassLoader loader, String name,
  296.81 -                                             byte[] b, int off, int len);
  296.82  }
   297.1 --- a/rt/emul/mini/src/main/java/java/net/URL.java	Tue Apr 29 15:25:58 2014 +0200
   297.2 +++ b/rt/emul/mini/src/main/java/java/net/URL.java	Wed Apr 30 15:04:10 2014 +0200
   297.3 @@ -920,6 +920,23 @@
   297.4      }
   297.5  
   297.6      /**
   297.7 +     * Returns a {@link java.net.URI} equivalent to this URL.
   297.8 +     * This method functions in the same way as <code>new URI (this.toString())</code>.
   297.9 +     * <p>Note, any URL instance that complies with RFC 2396 can be converted
  297.10 +     * to a URI. However, some URLs that are not strictly in compliance
  297.11 +     * can not be converted to a URI.
  297.12 +     *
  297.13 +     * @exception URISyntaxException if this URL is not formatted strictly according to
  297.14 +     *            to RFC2396 and cannot be converted to a URI.
  297.15 +     *
  297.16 +     * @return    a URI instance equivalent to this URL.
  297.17 +     * @since 1.5
  297.18 +     */
  297.19 +    public URI toURI() throws URISyntaxException {
  297.20 +        return new URI (toString());
  297.21 +    }
  297.22 +
  297.23 +    /**
  297.24       * Returns a {@link java.net.URLConnection URLConnection} instance that
  297.25       * represents a connection to the remote object referred to by the
  297.26       * {@code URL}.
  297.27 @@ -948,9 +965,9 @@
  297.28       * @see        java.net.URL#URL(java.lang.String, java.lang.String,
  297.29       *             int, java.lang.String)
  297.30       */
  297.31 -//    public URLConnection openConnection() throws java.io.IOException {
  297.32 -//        return handler.openConnection(this);
  297.33 -//    }
  297.34 +    public URLConnection openConnection() throws java.io.IOException {
  297.35 +        return handler.openConnection(this);
  297.36 +    }
  297.37  
  297.38  
  297.39      /**
  297.40 @@ -1027,18 +1044,53 @@
  297.41      public final Object getContent(Class[] classes)
  297.42      throws java.io.IOException {
  297.43          for (Class<?> c : classes) {
  297.44 -            if (c == String.class) {
  297.45 -                return loadText(toExternalForm());
  297.46 -            }
  297.47 -            if (c == byte[].class) {
  297.48 -                return loadBytes(toExternalForm(), new byte[0]);
  297.49 +            try {
  297.50 +                if (c == String.class) {
  297.51 +                    return loadText(toExternalForm());
  297.52 +                }
  297.53 +                if (c == byte[].class) {
  297.54 +                    return loadBytes(toExternalForm(), new byte[0]);
  297.55 +                }
  297.56 +            } catch (Throwable t) {
  297.57 +                throw new IOException(t);
  297.58              }
  297.59          }
  297.60          return null;
  297.61      }
  297.62  
  297.63 -    static URLStreamHandler getURLStreamHandler(String protocol) {
  297.64 -        URLStreamHandler universal = new URLStreamHandler() {};
  297.65 +    static URLStreamHandler getURLStreamHandler(final String protocol) {
  297.66 +        URLStreamHandler universal = new URLStreamHandler() {
  297.67 +            @Override
  297.68 +            protected URLConnection openConnection(URL u) throws IOException {
  297.69 +                return new URLConnection(u) {
  297.70 +                    Object stream = url.is;
  297.71 +                    
  297.72 +                    @Override
  297.73 +                    public void connect() throws IOException {
  297.74 +                        if (stream == null) {
  297.75 +                            try {
  297.76 +                                byte[] arr = (byte[]) url.getContent(new Class[]{byte[].class});
  297.77 +                                stream = new ByteArrayInputStream(arr);
  297.78 +                            } catch (IOException ex) {
  297.79 +                                stream = ex;
  297.80 +                                throw ex;
  297.81 +                            }
  297.82 +                        }
  297.83 +                    }
  297.84 +
  297.85 +                    @Override
  297.86 +                    public InputStream getInputStream() throws IOException {
  297.87 +                        connect();
  297.88 +                        if (stream instanceof IOException) {
  297.89 +                            throw (IOException)stream;
  297.90 +                        }
  297.91 +                        return (InputStream)stream;
  297.92 +                    }
  297.93 +                    
  297.94 +                    
  297.95 +                };
  297.96 +            }
  297.97 +        };
  297.98          return universal;
  297.99      }
 297.100  
 297.101 @@ -1053,10 +1105,16 @@
 297.102      }
 297.103      
 297.104      @JavaScriptBody(args = {}, body = 
 297.105 -          "if (typeof window !== 'object') return null;\n"
 297.106 -        + "if (!window.location) return null;\n"
 297.107 -        + "if (!window.location.href) return null;\n"
 297.108 -        + "return window.location.href;\n"
 297.109 +          "var l;\n"
 297.110 +        + "if (typeof location !== 'object') {"
 297.111 +        + "  if (typeof window !== 'object') return null;\n"
 297.112 +        + "  if (!window.location) return null;\n"
 297.113 +        + "  l = window.location;\n"
 297.114 +        + "} else {\n"
 297.115 +        + "  l = location;\n"
 297.116 +        + "}\n"
 297.117 +        + "if (!l.href) return null;\n"
 297.118 +        + "return l.href;\n"
 297.119      )
 297.120      private static native String findBaseURL();
 297.121  }
   298.1 --- a/rt/emul/mini/src/main/java/java/net/URLStreamHandler.java	Tue Apr 29 15:25:58 2014 +0200
   298.2 +++ b/rt/emul/mini/src/main/java/java/net/URLStreamHandler.java	Wed Apr 30 15:04:10 2014 +0200
   298.3 @@ -25,6 +25,8 @@
   298.4  
   298.5  package java.net;
   298.6  
   298.7 +import java.io.IOException;
   298.8 +
   298.9  
  298.10  /**
  298.11   * The abstract class <code>URLStreamHandler</code> is the common
  298.12 @@ -62,7 +64,7 @@
  298.13       * @exception  IOException  if an I/O error occurs while opening the
  298.14       *               connection.
  298.15       */
  298.16 -//    abstract protected URLConnection openConnection(URL u) throws IOException;
  298.17 +    abstract protected URLConnection openConnection(URL u) throws IOException;
  298.18  
  298.19      /**
  298.20       * Same as openConnection(URL), except that the connection will be
   299.1 --- a/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Tue Apr 29 15:25:58 2014 +0200
   299.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Wed Apr 30 15:04:10 2014 +0200
   299.3 @@ -19,6 +19,7 @@
   299.4  
   299.5  import java.lang.reflect.Method;
   299.6  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   299.7 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
   299.8  
   299.9  /**
  299.10   *
  299.11 @@ -71,4 +72,27 @@
  299.12      }
  299.13      @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
  299.14      public static native int identityHashCode(Object obj);
  299.15 +    
  299.16 +    @JavaScriptOnly(name = "toJS", value = "function(v) {\n" + 
  299.17 +        "  if (v === null) return null;\n" +
  299.18 +        "  if (Object.prototype.toString.call(v) === '[object Array]') {\n" +
  299.19 +        "    return vm.org_apidesign_bck2brwsr_emul_lang_System(false).convArray__Ljava_lang_Object_2Ljava_lang_Object_2(v);\n" +
  299.20 +        "  }\n" +
  299.21 +        "  return v.valueOf();\n" +
  299.22 +        "}\n"
  299.23 +    )
  299.24 +    public static native int toJS();
  299.25 +    
  299.26 +    private static Object convArray(Object o) {
  299.27 +        if (o instanceof Object[]) {
  299.28 +            Object[] arr = (Object[]) o;
  299.29 +            final int l = arr.length;
  299.30 +            Object[] ret = new Object[l];
  299.31 +            for (int i = 0; i < l; i++) {
  299.32 +                ret[i] = convArray(arr[i]);
  299.33 +            }
  299.34 +            return ret;
  299.35 +        }
  299.36 +        return o;
  299.37 +    }
  299.38  }
   300.1 --- a/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Tue Apr 29 15:25:58 2014 +0200
   300.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Wed Apr 30 15:04:10 2014 +0200
   300.3 @@ -18,6 +18,7 @@
   300.4  package org.apidesign.bck2brwsr.emul.reflect;
   300.5  
   300.6  import java.lang.reflect.Array;
   300.7 +import java.lang.reflect.Constructor;
   300.8  import java.lang.reflect.Method;
   300.9  import java.util.Enumeration;
  300.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
  300.11 @@ -37,15 +38,17 @@
  300.12      }
  300.13  
  300.14      protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
  300.15 +    protected abstract Constructor create(Class<?> declaringClass, Object data, String sig);
  300.16      
  300.17      
  300.18      //
  300.19      // bck2brwsr implementation
  300.20      //
  300.21  
  300.22 -    @JavaScriptBody(args = {"clazz", "prefix"},
  300.23 +    @JavaScriptBody(args = {"clazz", "prefix", "cnstr"},
  300.24          body = ""
  300.25 -        + "var c = clazz.cnstr.prototype;"
  300.26 +        + "var c = clazz.cnstr;\n"
  300.27 +        + "if (!cnstr) c = c.prototype;"
  300.28          + "var arr = new Array();\n"
  300.29          + "for (m in c) {\n"
  300.30          + "  if (m.indexOf(prefix) === 0) {\n"
  300.31 @@ -57,11 +60,55 @@
  300.32          + "}\n"
  300.33          + "return arr;")
  300.34      private static native Object[] findMethodData(
  300.35 -        Class<?> clazz, String prefix);
  300.36 +        Class<?> clazz, String prefix, boolean cnstr);
  300.37  
  300.38 +    public static Constructor findConstructor(
  300.39 +        Class<?> clazz, Class<?>... parameterTypes) {
  300.40 +        Object[] data = findMethodData(clazz, "cons__", true);
  300.41 +        BIG: for (int i = 0; i < data.length; i += 3) {
  300.42 +            String sig = ((String) data[i]).substring(6);
  300.43 +            Class<?> cls = (Class<?>) data[i + 2];
  300.44 +            Constructor tmp = INSTANCE.create(cls, data[i + 1], sig);
  300.45 +            Class<?>[] tmpParms = tmp.getParameterTypes();
  300.46 +            if (parameterTypes.length != tmpParms.length) {
  300.47 +                continue;
  300.48 +            }
  300.49 +            for (int j = 0; j < tmpParms.length; j++) {
  300.50 +                if (!parameterTypes[j].equals(tmpParms[j])) {
  300.51 +                    continue BIG;
  300.52 +                }
  300.53 +            }
  300.54 +            return tmp;
  300.55 +        }
  300.56 +        return null;
  300.57 +    }
  300.58 +
  300.59 +    public static Constructor[] findConstructors(Class<?> clazz, int mask) {
  300.60 +        Object[] namesAndData = findMethodData(clazz, "", true);
  300.61 +        int cnt = 0;
  300.62 +        for (int i = 0; i < namesAndData.length; i += 3) {
  300.63 +            String sig = (String) namesAndData[i];
  300.64 +            Object data = namesAndData[i + 1];
  300.65 +            if (!sig.startsWith("cons__")) {
  300.66 +                continue;
  300.67 +            }
  300.68 +            sig = sig.substring(6);
  300.69 +            Class<?> cls = (Class<?>) namesAndData[i + 2];
  300.70 +            final Constructor m = INSTANCE.create(cls, data, sig);
  300.71 +            if ((m.getModifiers() & mask) == 0) {
  300.72 +                continue;
  300.73 +            }
  300.74 +            namesAndData[cnt++] = m;
  300.75 +        }
  300.76 +        Constructor[] arr = new Constructor[cnt];
  300.77 +        for (int i = 0; i < cnt; i++) {
  300.78 +            arr[i] = (Constructor) namesAndData[i];
  300.79 +        }
  300.80 +        return arr;
  300.81 +    }
  300.82      public static Method findMethod(
  300.83          Class<?> clazz, String name, Class<?>... parameterTypes) {
  300.84 -        Object[] data = findMethodData(clazz, name + "__");
  300.85 +        Object[] data = findMethodData(clazz, name + "__", false);
  300.86          BIG: for (int i = 0; i < data.length; i += 3) {
  300.87              String sig = ((String) data[i]).substring(name.length() + 2);
  300.88              Class<?> cls = (Class<?>) data[i + 2];
  300.89 @@ -81,7 +128,7 @@
  300.90      }
  300.91  
  300.92      public static Method[] findMethods(Class<?> clazz, int mask) {
  300.93 -        Object[] namesAndData = findMethodData(clazz, "");
  300.94 +        Object[] namesAndData = findMethodData(clazz, "", false);
  300.95          int cnt = 0;
  300.96          for (int i = 0; i < namesAndData.length; i += 3) {
  300.97              String sig = (String) namesAndData[i];
   301.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   301.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/vm4brwsr/api/VM.java	Wed Apr 30 15:04:10 2014 +0200
   301.3 @@ -0,0 +1,47 @@
   301.4 +/**
   301.5 + * Back 2 Browser Bytecode Translator
   301.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   301.7 + *
   301.8 + * This program is free software: you can redistribute it and/or modify
   301.9 + * it under the terms of the GNU General Public License as published by
  301.10 + * the Free Software Foundation, version 2 of the License.
  301.11 + *
  301.12 + * This program is distributed in the hope that it will be useful,
  301.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  301.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  301.15 + * GNU General Public License for more details.
  301.16 + *
  301.17 + * You should have received a copy of the GNU General Public License
  301.18 + * along with this program. Look for COPYING file in the top folder.
  301.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  301.20 + */
  301.21 +package org.apidesign.vm4brwsr.api;
  301.22 +
  301.23 +import java.io.IOException;
  301.24 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  301.25 +
  301.26 +/** Utility methods to talk to the Bck2Brwsr virtual machine.
  301.27 + *
  301.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  301.29 + * @since 0.9
  301.30 + */
  301.31 +public final class VM {
  301.32 +    private VM() {
  301.33 +    }
  301.34 +
  301.35 +    /** Takes an existing class and replaces its existing byte code 
  301.36 +     * with new one.
  301.37 +     * 
  301.38 +     * @param clazz existing class to reload
  301.39 +     * @param byteCode new bytecode
  301.40 +     * @throws IOException an exception is something goes wrong
  301.41 +     */
  301.42 +    public static void reload(Class<?> clazz, byte[] byteCode) throws IOException {
  301.43 +        reloadImpl(clazz.getName(), byteCode);
  301.44 +    }
  301.45 +    
  301.46 +    @JavaScriptBody(args = { "name", "byteCode" }, body = "vm._reload(name, byteCode);")
  301.47 +    private static void reloadImpl(String name, byte[] byteCode) throws IOException {
  301.48 +        throw new IOException();
  301.49 +    }
  301.50 +}
   302.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Tue Apr 29 15:25:58 2014 +0200
   302.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Wed Apr 30 15:04:10 2014 +0200
   302.3 @@ -176,6 +176,8 @@
   302.4      };
   302.5  
   302.6      numberPrototype.shl64 = function(x) {
   302.7 +        x &= 0x3f;
   302.8 +        if (x == 0) return this;
   302.9          if (x >= 32) {
  302.10              var hi = this << (x - 32);
  302.11              return hi.next32(0);
  302.12 @@ -190,6 +192,8 @@
  302.13      };
  302.14  
  302.15      numberPrototype.shr64 = function(x) {
  302.16 +        x &= 0x3f;
  302.17 +        if (x == 0) return this;
  302.18          if (x >= 32) {
  302.19              var low = this.high32() >> (x - 32);
  302.20              low += (low < 0) ? (__m32 + 1) : 0;
  302.21 @@ -205,6 +209,8 @@
  302.22      };
  302.23  
  302.24      numberPrototype.ushr64 = function(x) {
  302.25 +        x &= 0x3f;
  302.26 +        if (x == 0) return this;
  302.27          if (x >= 32) {
  302.28              var low = this.high32() >>> (x - 32);
  302.29              low += (low < 0) ? (__m32 + 1) : 0;
  302.30 @@ -218,6 +224,14 @@
  302.31              return hi.next32(low);
  302.32          }
  302.33      };
  302.34 +    
  302.35 +    numberPrototype.compare = function(x) {
  302.36 +        if (this == x) {
  302.37 +            return 0;
  302.38 +        } else {
  302.39 +            return (this < x) ? -1 : 1;
  302.40 +        }
  302.41 +    };
  302.42  
  302.43      numberPrototype.compare64 = function(x) {
  302.44          if (this.high32() === x.high32()) {
   303.1 --- a/rt/emul/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   303.2 +++ b/rt/emul/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   303.3 @@ -4,16 +4,17 @@
   303.4    <parent>
   303.5      <groupId>org.apidesign.bck2brwsr</groupId>
   303.6      <artifactId>rt</artifactId>
   303.7 -    <version>0.8-SNAPSHOT</version>
   303.8 +    <version>0.9-SNAPSHOT</version>
   303.9    </parent>
  303.10    <groupId>org.apidesign.bck2brwsr</groupId>
  303.11    <artifactId>emul.pom</artifactId>
  303.12 -  <version>0.8-SNAPSHOT</version>
  303.13 +  <version>0.9-SNAPSHOT</version>
  303.14    <packaging>pom</packaging>
  303.15    <name>Emulation of Core Libraries</name>
  303.16    <modules>
  303.17      <module>mini</module>
  303.18      <module>compact</module>
  303.19      <module>brwsrtest</module>
  303.20 +    <module>fake</module>
  303.21    </modules>
  303.22  </project>
   304.1 --- a/rt/mojo/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   304.2 +++ b/rt/mojo/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   304.3 @@ -4,11 +4,11 @@
   304.4    <parent>
   304.5      <groupId>org.apidesign.bck2brwsr</groupId>
   304.6      <artifactId>rt</artifactId>
   304.7 -    <version>0.8-SNAPSHOT</version>
   304.8 +    <version>0.9-SNAPSHOT</version>
   304.9    </parent>
  304.10    <groupId>org.apidesign.bck2brwsr</groupId>
  304.11    <artifactId>bck2brwsr-maven-plugin</artifactId>
  304.12 -  <version>0.8-SNAPSHOT</version>
  304.13 +  <version>0.9-SNAPSHOT</version>
  304.14    <packaging>maven-plugin</packaging>
  304.15    <name>Bck2Brwsr Maven Plugin</name>
  304.16    <url>http://bck2brwsr.apidesign.org/</url>
   305.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java	Tue Apr 29 15:25:58 2014 +0200
   305.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java	Wed Apr 30 15:04:10 2014 +0200
   305.3 @@ -29,15 +29,21 @@
   305.4  import java.util.Collection;
   305.5  import java.util.List;
   305.6  import org.apache.maven.artifact.Artifact;
   305.7 +import org.apache.maven.model.Resource;
   305.8  import org.apache.maven.plugin.MojoExecutionException;
   305.9  import org.apache.maven.plugins.annotations.LifecyclePhase;
  305.10  import org.apache.maven.plugins.annotations.Mojo;
  305.11  import org.apache.maven.plugins.annotations.Parameter;
  305.12 +import org.apache.maven.plugins.annotations.ResolutionScope;
  305.13  import org.apache.maven.project.MavenProject;
  305.14  import org.apidesign.bck2brwsr.launcher.Launcher;
  305.15  
  305.16  /** Executes given HTML page in a browser. */
  305.17 -@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE)
  305.18 +@Mojo(
  305.19 +    name="brwsr",
  305.20 +    requiresDependencyResolution = ResolutionScope.RUNTIME,
  305.21 +    defaultPhase=LifecyclePhase.NONE
  305.22 +)
  305.23  public class BrwsrMojo extends AbstractMojo {
  305.24      public BrwsrMojo() {
  305.25      }
  305.26 @@ -64,20 +70,33 @@
  305.27      /** Root of all pages, and files, etc. */
  305.28      @Parameter
  305.29      private File directory;
  305.30 +    
  305.31 +    @Parameter(defaultValue="${project.build.directory}/bck2brwsr.js")
  305.32 +    private File javascript;
  305.33  
  305.34      @Override
  305.35      public void execute() throws MojoExecutionException {
  305.36          if (startpage == null) {
  305.37              throw new MojoExecutionException("You have to provide a start page");
  305.38          }
  305.39 -        
  305.40 +        if (javascript != null && javascript.isFile()) {
  305.41 +            System.setProperty("bck2brwsr.js", javascript.toURI().toString());
  305.42 +        }
  305.43          try {
  305.44              Closeable httpServer;
  305.45              if (directory != null) {
  305.46 -                httpServer = Launcher.showDir(directory, startpage);
  305.47 +                URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  305.48 +                httpServer = Launcher.showDir(launcher, directory, url, startpage);
  305.49              } else {
  305.50 -                URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
  305.51 +                URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  305.52                  try {
  305.53 +                    for (Resource r : prj.getResources()) {
  305.54 +                        File f = new File(r.getDirectory(), startpage().replace('/', File.separatorChar));
  305.55 +                        if (f.exists()) {
  305.56 +                            System.setProperty("startpage.file", f.getPath());
  305.57 +                        }
  305.58 +                    }
  305.59 +                    
  305.60                      httpServer = Launcher.showURL(launcher, url, startpage());
  305.61                  } catch (Exception ex) {
  305.62                      throw new MojoExecutionException("Can't open " + startpage(), ex);
   306.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java	Tue Apr 29 15:25:58 2014 +0200
   306.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java	Wed Apr 30 15:04:10 2014 +0200
   306.3 @@ -33,12 +33,16 @@
   306.4  import org.apache.maven.plugins.annotations.LifecyclePhase;
   306.5  import org.apache.maven.plugins.annotations.Mojo;
   306.6  import org.apache.maven.plugins.annotations.Parameter;
   306.7 +import org.apache.maven.plugins.annotations.ResolutionScope;
   306.8  import org.apache.maven.project.MavenProject;
   306.9  import org.apidesign.vm4brwsr.Bck2Brwsr;
  306.10  import org.apidesign.vm4brwsr.ObfuscationLevel;
  306.11  
  306.12  /** Compiles classes into JavaScript. */
  306.13 -@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
  306.14 +@Mojo(name="j2js", 
  306.15 +    requiresDependencyResolution = ResolutionScope.COMPILE,
  306.16 +    defaultPhase=LifecyclePhase.PROCESS_CLASSES
  306.17 +)
  306.18  public class Java2JavaScript extends AbstractMojo {
  306.19      public Java2JavaScript() {
  306.20      }
  306.21 @@ -46,7 +50,7 @@
  306.22      @Parameter(defaultValue="${project.build.directory}/classes")
  306.23      private File classes;
  306.24      /** JavaScript file to generate */
  306.25 -    @Parameter
  306.26 +    @Parameter(defaultValue="${project.build.directory}/bck2brwsr.js")
  306.27      private File javascript;
  306.28  
  306.29      /** Additional classes that should be pre-compiled into the javascript 
  306.30 @@ -66,6 +70,10 @@
  306.31       */
  306.32      @Parameter(defaultValue="NONE")
  306.33      private ObfuscationLevel obfuscation;
  306.34 +    
  306.35 +    /** Should classes from rt.jar be included? */
  306.36 +    @Parameter(defaultValue = "false")
  306.37 +    private boolean ignoreBootClassPath;
  306.38  
  306.39      /**
  306.40       * Indicates whether to create an extension library 
  306.41 @@ -81,6 +89,9 @@
  306.42          if (!classes.isDirectory()) {
  306.43              throw new MojoExecutionException("Can't find " + classes);
  306.44          }
  306.45 +        if (javascript == null) {
  306.46 +            throw new MojoExecutionException("Need to define 'javascript' attribute with a path to file to generate");
  306.47 +        }
  306.48  
  306.49          List<String> arr = new ArrayList<String>();
  306.50          long newest = collectAllClasses("", classes, arr);
  306.51 @@ -95,12 +106,12 @@
  306.52          }
  306.53  
  306.54          try {
  306.55 -            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
  306.56 +            URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  306.57              FileWriter w = new FileWriter(javascript);
  306.58              Bck2Brwsr.newCompiler().
  306.59                  obfuscation(obfuscation).
  306.60                  library(library).
  306.61 -                resources(url).
  306.62 +                resources(url, ignoreBootClassPath).
  306.63                  addRootClasses(arr.toArray(new String[0])).
  306.64                  generate(w);
  306.65              w.close();
   307.1 --- a/rt/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   307.2 +++ b/rt/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   307.3 @@ -3,18 +3,17 @@
   307.4    <modelVersion>4.0.0</modelVersion>
   307.5    <groupId>org.apidesign.bck2brwsr</groupId>
   307.6    <artifactId>rt</artifactId>
   307.7 -  <version>0.8-SNAPSHOT</version>
   307.8 +  <version>0.9-SNAPSHOT</version>
   307.9    <packaging>pom</packaging>
  307.10    <name>Bck2Brwsr Runtime</name>
  307.11    <parent>
  307.12      <groupId>org.apidesign</groupId>
  307.13      <artifactId>bck2brwsr</artifactId>
  307.14 -    <version>0.8-SNAPSHOT</version>
  307.15 +    <version>0.9-SNAPSHOT</version>
  307.16    </parent>  
  307.17    <modules>
  307.18      <module>core</module>
  307.19      <module>emul</module>
  307.20 -    <module>archetype</module>
  307.21      <module>mojo</module>
  307.22      <module>vm</module>
  307.23      <module>vmtest</module>
   308.1 --- a/rt/vm/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   308.2 +++ b/rt/vm/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   308.3 @@ -3,12 +3,12 @@
   308.4    <parent>
   308.5      <groupId>org.apidesign.bck2brwsr</groupId>
   308.6      <artifactId>rt</artifactId>
   308.7 -    <version>0.8-SNAPSHOT</version>
   308.8 +    <version>0.9-SNAPSHOT</version>
   308.9    </parent>
  308.10  
  308.11    <groupId>org.apidesign.bck2brwsr</groupId>
  308.12    <artifactId>vm4brwsr</artifactId>
  308.13 -  <version>0.8-SNAPSHOT</version>
  308.14 +  <version>0.9-SNAPSHOT</version>
  308.15    <packaging>jar</packaging>
  308.16  
  308.17    <name>Virtual Machine for Browser</name>
  308.18 @@ -18,6 +18,7 @@
  308.19      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  308.20      <author.name>Jaroslav Tulach</author.name>
  308.21      <author.email>jaroslav.tulach@apidesign.org</author.email>
  308.22 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
  308.23    </properties>
  308.24    
  308.25    <repositories>
  308.26 @@ -91,7 +92,7 @@
  308.27                              <classpath />
  308.28                              <argument>org.apidesign.vm4brwsr.Main</argument>
  308.29                              <argument>--obfuscatelevel</argument>
  308.30 -                            <argument>MINIMAL</argument>
  308.31 +                            <argument>${bck2brwsr.obfuscationlevel}</argument>
  308.32                              <argument>${project.build.directory}/bck2brwsr.js</argument>
  308.33                              <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
  308.34                          </arguments>
  308.35 @@ -151,6 +152,18 @@
  308.36        <artifactId>closure-compiler</artifactId>
  308.37        <version>r2388</version>
  308.38        <scope>compile</scope>
  308.39 -    </dependency>  
  308.40 +    </dependency>
  308.41 +    <dependency>
  308.42 +      <groupId>org.netbeans.html</groupId>
  308.43 +      <artifactId>net.java.html.boot</artifactId>
  308.44 +      <scope>test</scope>
  308.45 +      <version>${net.java.html.version}</version>
  308.46 +    </dependency>
  308.47 +    <dependency>
  308.48 +      <groupId>${project.groupId}</groupId>
  308.49 +      <artifactId>fake</artifactId>
  308.50 +      <version>${project.version}</version>
  308.51 +      <scope>test</scope>
  308.52 +    </dependency>
  308.53    </dependencies>
  308.54  </project>
   309.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Tue Apr 29 15:25:58 2014 +0200
   309.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Wed Apr 30 15:04:10 2014 +0200
   309.3 @@ -217,7 +217,21 @@
   309.4       * @since 0.5
   309.5       */
   309.6      public Bck2Brwsr resources(final ClassLoader loader) {
   309.7 -        return resources(new LdrRsrcs(loader));
   309.8 +        return resources(loader, false);
   309.9 +    }
  309.10 +
  309.11 +    /** A way to change the provider of additional resources (classes) for the 
  309.12 +     * compiler by specifying classloader to use for loading them.
  309.13 +     * 
  309.14 +     * @param loader class loader to load the resources from
  309.15 +     * @param ignoreBootClassPath <code>true</code> if classes loaded
  309.16 +     *    from <code>rt.jar</code> 
  309.17 +     * @return new instance of the compiler with all values being the same, just 
  309.18 +     *   different resources provider
  309.19 +     * @since 0.9
  309.20 +     */
  309.21 +    public Bck2Brwsr resources(final ClassLoader loader, boolean ignoreBootClassPath) {
  309.22 +        return resources(new LdrRsrcs(loader, ignoreBootClassPath));
  309.23      }
  309.24      
  309.25      /** Generates virtual machine based on previous configuration of the 
  309.26 @@ -247,7 +261,7 @@
  309.27      // 
  309.28      
  309.29      Resources getResources() {
  309.30 -        return res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader());
  309.31 +        return res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader(), false);
  309.32      }
  309.33      
  309.34      String[] allClasses() {
   310.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java	Tue Apr 29 15:25:58 2014 +0200
   310.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java	Wed Apr 30 15:04:10 2014 +0200
   310.3 @@ -39,37 +39,6 @@
   310.4  final class ByteCodeParser {
   310.5      private ByteCodeParser() {
   310.6      }
   310.7 -    /* Signature Characters */
   310.8 -    public static final char   SIGC_VOID                  = 'V';
   310.9 -    public static final String SIG_VOID                   = "V";
  310.10 -    public static final char   SIGC_BOOLEAN               = 'Z';
  310.11 -    public static final String SIG_BOOLEAN                = "Z";
  310.12 -    public static final char   SIGC_BYTE                  = 'B';
  310.13 -    public static final String SIG_BYTE                   = "B";
  310.14 -    public static final char   SIGC_CHAR                  = 'C';
  310.15 -    public static final String SIG_CHAR                   = "C";
  310.16 -    public static final char   SIGC_SHORT                 = 'S';
  310.17 -    public static final String SIG_SHORT                  = "S";
  310.18 -    public static final char   SIGC_INT                   = 'I';
  310.19 -    public static final String SIG_INT                    = "I";
  310.20 -    public static final char   SIGC_LONG                  = 'J';
  310.21 -    public static final String SIG_LONG                   = "J";
  310.22 -    public static final char   SIGC_FLOAT                 = 'F';
  310.23 -    public static final String SIG_FLOAT                  = "F";
  310.24 -    public static final char   SIGC_DOUBLE                = 'D';
  310.25 -    public static final String SIG_DOUBLE                 = "D";
  310.26 -    public static final char   SIGC_ARRAY                 = '[';
  310.27 -    public static final String SIG_ARRAY                  = "[";
  310.28 -    public static final char   SIGC_CLASS                 = 'L';
  310.29 -    public static final String SIG_CLASS                  = "L";
  310.30 -    public static final char   SIGC_METHOD                = '(';
  310.31 -    public static final String SIG_METHOD                 = "(";
  310.32 -    public static final char   SIGC_ENDCLASS              = ';';
  310.33 -    public static final String SIG_ENDCLASS               = ";";
  310.34 -    public static final char   SIGC_ENDMETHOD             = ')';
  310.35 -    public static final String SIG_ENDMETHOD              = ")";
  310.36 -    public static final char   SIGC_PACKAGE               = '/';
  310.37 -    public static final String SIG_PACKAGE                = "/";
  310.38  
  310.39      /* Class File Constants */
  310.40      public static final int JAVA_MAGIC                   = 0xcafebabe;
  310.41 @@ -107,17 +76,6 @@
  310.42      public static final int ACC_EXPLICIT                 = 0x00001000;
  310.43      public static final int ACC_SYNTHETIC                = 0x00010000; // actually, this is an attribute
  310.44  
  310.45 -    /* Type codes */
  310.46 -    public static final int T_CLASS                      = 0x00000002;
  310.47 -    public static final int T_BOOLEAN                    = 0x00000004;
  310.48 -    public static final int T_CHAR                       = 0x00000005;
  310.49 -    public static final int T_FLOAT                      = 0x00000006;
  310.50 -    public static final int T_DOUBLE                     = 0x00000007;
  310.51 -    public static final int T_BYTE                       = 0x00000008;
  310.52 -    public static final int T_SHORT                      = 0x00000009;
  310.53 -    public static final int T_INT                        = 0x0000000a;
  310.54 -    public static final int T_LONG                       = 0x0000000b;
  310.55 -
  310.56      /* Type codes for StackMap attribute */
  310.57      public static final int ITEM_Bogus      =0; // an unknown or uninitialized value
  310.58      public static final int ITEM_Integer    =1; // a 32-bit integer
  310.59 @@ -358,7 +316,7 @@
  310.60      public static final int opc_nonpriv                  = 254;
  310.61      public static final int opc_priv                     = 255;
  310.62  
  310.63 -        /* Wide instructions */
  310.64 +        /* Wide instructions *
  310.65      public static final int opc_iload_w         = (opc_wide<<8)|opc_iload;
  310.66      public static final int opc_lload_w         = (opc_wide<<8)|opc_lload;
  310.67      public static final int opc_fload_w         = (opc_wide<<8)|opc_fload;
  310.68 @@ -371,762 +329,7 @@
  310.69      public static final int opc_astore_w        = (opc_wide<<8)|opc_astore;
  310.70      public static final int opc_ret_w           = (opc_wide<<8)|opc_ret;
  310.71      public static final int opc_iinc_w          = (opc_wide<<8)|opc_iinc;
  310.72 -
  310.73 -    /* Opcode Names */
  310.74 -  public static final String opcNamesTab[] = {
  310.75 -        "nop",
  310.76 -        "aconst_null",
  310.77 -        "iconst_m1",
  310.78 -        "iconst_0",
  310.79 -        "iconst_1",
  310.80 -        "iconst_2",
  310.81 -        "iconst_3",
  310.82 -        "iconst_4",
  310.83 -        "iconst_5",
  310.84 -        "lconst_0",
  310.85 -        "lconst_1",
  310.86 -        "fconst_0",
  310.87 -        "fconst_1",
  310.88 -        "fconst_2",
  310.89 -        "dconst_0",
  310.90 -        "dconst_1",
  310.91 -        "bipush",
  310.92 -        "sipush",
  310.93 -        "ldc",
  310.94 -        "ldc_w",
  310.95 -        "ldc2_w",
  310.96 -        "iload",
  310.97 -        "lload",
  310.98 -        "fload",
  310.99 -        "dload",
 310.100 -        "aload",
 310.101 -        "iload_0",
 310.102 -        "iload_1",
 310.103 -        "iload_2",
 310.104 -        "iload_3",
 310.105 -        "lload_0",
 310.106 -        "lload_1",
 310.107 -        "lload_2",
 310.108 -        "lload_3",
 310.109 -        "fload_0",
 310.110 -        "fload_1",
 310.111 -        "fload_2",
 310.112 -        "fload_3",
 310.113 -        "dload_0",
 310.114 -        "dload_1",
 310.115 -        "dload_2",
 310.116 -        "dload_3",
 310.117 -        "aload_0",
 310.118 -        "aload_1",
 310.119 -        "aload_2",
 310.120 -        "aload_3",
 310.121 -        "iaload",
 310.122 -        "laload",
 310.123 -        "faload",
 310.124 -        "daload",
 310.125 -        "aaload",
 310.126 -        "baload",
 310.127 -        "caload",
 310.128 -        "saload",
 310.129 -        "istore",
 310.130 -        "lstore",
 310.131 -        "fstore",
 310.132 -        "dstore",
 310.133 -        "astore",
 310.134 -        "istore_0",
 310.135 -        "istore_1",
 310.136 -        "istore_2",
 310.137 -        "istore_3",
 310.138 -        "lstore_0",
 310.139 -        "lstore_1",
 310.140 -        "lstore_2",
 310.141 -        "lstore_3",
 310.142 -        "fstore_0",
 310.143 -        "fstore_1",
 310.144 -        "fstore_2",
 310.145 -        "fstore_3",
 310.146 -        "dstore_0",
 310.147 -        "dstore_1",
 310.148 -        "dstore_2",
 310.149 -        "dstore_3",
 310.150 -        "astore_0",
 310.151 -        "astore_1",
 310.152 -        "astore_2",
 310.153 -        "astore_3",
 310.154 -        "iastore",
 310.155 -        "lastore",
 310.156 -        "fastore",
 310.157 -        "dastore",
 310.158 -        "aastore",
 310.159 -        "bastore",
 310.160 -        "castore",
 310.161 -        "sastore",
 310.162 -        "pop",
 310.163 -        "pop2",
 310.164 -        "dup",
 310.165 -        "dup_x1",
 310.166 -        "dup_x2",
 310.167 -        "dup2",
 310.168 -        "dup2_x1",
 310.169 -        "dup2_x2",
 310.170 -        "swap",
 310.171 -        "iadd",
 310.172 -        "ladd",
 310.173 -        "fadd",
 310.174 -        "dadd",
 310.175 -        "isub",
 310.176 -        "lsub",
 310.177 -        "fsub",
 310.178 -        "dsub",
 310.179 -        "imul",
 310.180 -        "lmul",
 310.181 -        "fmul",
 310.182 -        "dmul",
 310.183 -        "idiv",
 310.184 -        "ldiv",
 310.185 -        "fdiv",
 310.186 -        "ddiv",
 310.187 -        "irem",
 310.188 -        "lrem",
 310.189 -        "frem",
 310.190 -        "drem",
 310.191 -        "ineg",
 310.192 -        "lneg",
 310.193 -        "fneg",
 310.194 -        "dneg",
 310.195 -        "ishl",
 310.196 -        "lshl",
 310.197 -        "ishr",
 310.198 -        "lshr",
 310.199 -        "iushr",
 310.200 -        "lushr",
 310.201 -        "iand",
 310.202 -        "land",
 310.203 -        "ior",
 310.204 -        "lor",
 310.205 -        "ixor",
 310.206 -        "lxor",
 310.207 -        "iinc",
 310.208 -        "i2l",
 310.209 -        "i2f",
 310.210 -        "i2d",
 310.211 -        "l2i",
 310.212 -        "l2f",
 310.213 -        "l2d",
 310.214 -        "f2i",
 310.215 -        "f2l",
 310.216 -        "f2d",
 310.217 -        "d2i",
 310.218 -        "d2l",
 310.219 -        "d2f",
 310.220 -        "i2b",
 310.221 -        "i2c",
 310.222 -        "i2s",
 310.223 -        "lcmp",
 310.224 -        "fcmpl",
 310.225 -        "fcmpg",
 310.226 -        "dcmpl",
 310.227 -        "dcmpg",
 310.228 -        "ifeq",
 310.229 -        "ifne",
 310.230 -        "iflt",
 310.231 -        "ifge",
 310.232 -        "ifgt",
 310.233 -        "ifle",
 310.234 -        "if_icmpeq",
 310.235 -        "if_icmpne",
 310.236 -        "if_icmplt",
 310.237 -        "if_icmpge",
 310.238 -        "if_icmpgt",
 310.239 -        "if_icmple",
 310.240 -        "if_acmpeq",
 310.241 -        "if_acmpne",
 310.242 -        "goto",
 310.243 -        "jsr",
 310.244 -        "ret",
 310.245 -        "tableswitch",
 310.246 -        "lookupswitch",
 310.247 -        "ireturn",
 310.248 -        "lreturn",
 310.249 -        "freturn",
 310.250 -        "dreturn",
 310.251 -        "areturn",
 310.252 -        "return",
 310.253 -        "getstatic",
 310.254 -        "putstatic",
 310.255 -        "getfield",
 310.256 -        "putfield",
 310.257 -        "invokevirtual",
 310.258 -        "invokespecial", //     was "invokenonvirtual",
 310.259 -        "invokestatic",
 310.260 -        "invokeinterface",
 310.261 -        "bytecode 186", //"xxxunusedxxx",
 310.262 -        "new",
 310.263 -        "newarray",
 310.264 -        "anewarray",
 310.265 -        "arraylength",
 310.266 -        "athrow",
 310.267 -        "checkcast",
 310.268 -        "instanceof",
 310.269 -        "monitorenter",
 310.270 -        "monitorexit",
 310.271 -         null, // "wide",
 310.272 -        "multianewarray",
 310.273 -        "ifnull",
 310.274 -        "ifnonnull",
 310.275 -        "goto_w",
 310.276 -        "jsr_w",
 310.277 -        "bytecode 202", // "breakpoint",
 310.278 -        "bytecode",
 310.279 -        "try",
 310.280 -        "endtry",
 310.281 -        "catch",
 310.282 -        "var",
 310.283 -        "endvar",
 310.284 -        "locals_map",
 310.285 -        "stack_map"
 310.286 -  };
 310.287 -
 310.288 -    /* Opcode Lengths */
 310.289 -  public static final int opcLengthsTab[] = {
 310.290 -        1,
 310.291 -        1,
 310.292 -        1,
 310.293 -        1,
 310.294 -        1,
 310.295 -        1,
 310.296 -        1,
 310.297 -        1,
 310.298 -        1,
 310.299 -        1,
 310.300 -        1,
 310.301 -        1,
 310.302 -        1,
 310.303 -        1,
 310.304 -        1,
 310.305 -        1,
 310.306 -        2,
 310.307 -        3,
 310.308 -        2,
 310.309 -        3,
 310.310 -        3,
 310.311 -        2,
 310.312 -        2,
 310.313 -        2,
 310.314 -        2,
 310.315 -        2,
 310.316 -        1,
 310.317 -        1,
 310.318 -        1,
 310.319 -        1,
 310.320 -        1,
 310.321 -        1,
 310.322 -        1,
 310.323 -        1,
 310.324 -        1,
 310.325 -        1,
 310.326 -        1,
 310.327 -        1,
 310.328 -        1,
 310.329 -        1,
 310.330 -        1,
 310.331 -        1,
 310.332 -        1,
 310.333 -        1,
 310.334 -        1,
 310.335 -        1,
 310.336 -        1,
 310.337 -        1,
 310.338 -        1,
 310.339 -        1,
 310.340 -        1,
 310.341 -        1,
 310.342 -        1,
 310.343 -        1,
 310.344 -        2,
 310.345 -        2,
 310.346 -        2,
 310.347 -        2,
 310.348 -        2,
 310.349 -        1,
 310.350 -        1,
 310.351 -        1,
 310.352 -        1,
 310.353 -        1,
 310.354 -        1,
 310.355 -        1,
 310.356 -        1,
 310.357 -        1,
 310.358 -        1,
 310.359 -        1,
 310.360 -        1,
 310.361 -        1,
 310.362 -        1,
 310.363 -        1,
 310.364 -        1,
 310.365 -        1,
 310.366 -        1,
 310.367 -        1,
 310.368 -        1,
 310.369 -        1,
 310.370 -        1,
 310.371 -        1,
 310.372 -        1,
 310.373 -        1,
 310.374 -        1,
 310.375 -        1,
 310.376 -        1,
 310.377 -        1,
 310.378 -        1,
 310.379 -        1,
 310.380 -        1,
 310.381 -        1,
 310.382 -        1,
 310.383 -        1,
 310.384 -        1,
 310.385 -        1,
 310.386 -        1,
 310.387 -        1,
 310.388 -        1,
 310.389 -        1,
 310.390 -        1,
 310.391 -        1,
 310.392 -        1,
 310.393 -        1,
 310.394 -        1,
 310.395 -        1,
 310.396 -        1,
 310.397 -        1,
 310.398 -        1,
 310.399 -        1,
 310.400 -        1,
 310.401 -        1,
 310.402 -        1,
 310.403 -        1,
 310.404 -        1,
 310.405 -        1,
 310.406 -        1,
 310.407 -        1,
 310.408 -        1,
 310.409 -        1,
 310.410 -        1,
 310.411 -        1,
 310.412 -        1,
 310.413 -        1,
 310.414 -        1,
 310.415 -        1,
 310.416 -        1,
 310.417 -        1,
 310.418 -        1,
 310.419 -        1,
 310.420 -        1,
 310.421 -        1,
 310.422 -        3,
 310.423 -        1,
 310.424 -        1,
 310.425 -        1,
 310.426 -        1,
 310.427 -        1,
 310.428 -        1,
 310.429 -        1,
 310.430 -        1,
 310.431 -        1,
 310.432 -        1,
 310.433 -        1,
 310.434 -        1,
 310.435 -        1,
 310.436 -        1,
 310.437 -        1,
 310.438 -        1,
 310.439 -        1,
 310.440 -        1,
 310.441 -        1,
 310.442 -        1,
 310.443 -        3,
 310.444 -        3,
 310.445 -        3,
 310.446 -        3,
 310.447 -        3,
 310.448 -        3,
 310.449 -        3,
 310.450 -        3,
 310.451 -        3,
 310.452 -        3,
 310.453 -        3,
 310.454 -        3,
 310.455 -        3,
 310.456 -        3,
 310.457 -        3,
 310.458 -        3,
 310.459 -        2,
 310.460 -        99,
 310.461 -        99,
 310.462 -        1,
 310.463 -        1,
 310.464 -        1,
 310.465 -        1,
 310.466 -        1,
 310.467 -        1,
 310.468 -        3,
 310.469 -        3,
 310.470 -        3,
 310.471 -        3,
 310.472 -        3,
 310.473 -        3,
 310.474 -        3,
 310.475 -        5,
 310.476 -        0,
 310.477 -        3,
 310.478 -        2,
 310.479 -        3,
 310.480 -        1,
 310.481 -        1,
 310.482 -        3,
 310.483 -        3,
 310.484 -        1,
 310.485 -        1,
 310.486 -        0, // wide
 310.487 -        4,
 310.488 -        3,
 310.489 -        3,
 310.490 -        5,
 310.491 -        5,
 310.492 -        1,
 310.493 -        1, 0, 0, 0, 0, 0 // pseudo
 310.494 -  };
 310.495 -
 310.496 -     /**
 310.497 -     * End of input
 310.498 -     */
 310.499 -    public static final int EOF = -1;
 310.500 -
 310.501 -   /*
 310.502 -     * Flags
 310.503 -     */
 310.504 -    public static final int F_VERBOSE           = 1 << 0;
 310.505 -    public static final int F_DUMP              = 1 << 1;
 310.506 -    public static final int F_WARNINGS          = 1 << 2;
 310.507 -    public static final int F_DEBUG             = 1 << 3;
 310.508 -    public static final int F_OPTIMIZE          = 1 << 4;
 310.509 -    public static final int F_DEPENDENCIES      = 1 << 5;
 310.510 -
 310.511 -    /*
 310.512 -     * Type codes
 310.513 -     */
 310.514 -    public static final int TC_BOOLEAN   = 0;
 310.515 -    public static final int TC_BYTE      = 1;
 310.516 -    public static final int TC_CHAR      = 2;
 310.517 -    public static final int TC_SHORT     = 3;
 310.518 -    public static final int TC_INT       = 4;
 310.519 -    public static final int TC_LONG      = 5;
 310.520 -    public static final int TC_FLOAT     = 6;
 310.521 -    public static final int TC_DOUBLE    = 7;
 310.522 -    public static final int TC_NULL      = 8;
 310.523 -    public static final int TC_ARRAY     = 9;
 310.524 -    public static final int TC_CLASS     = 10;
 310.525 -    public static final int TC_VOID      = 11;
 310.526 -    public static final int TC_METHOD    = 12;
 310.527 -    public static final int TC_ERROR     = 13;
 310.528 -
 310.529 -    /*
 310.530 -     * Type Masks
 310.531 -     */
 310.532 -    public static final int TM_NULL      = 1 << TC_NULL;
 310.533 -    public static final int TM_VOID      = 1 << TC_VOID;
 310.534 -    public static final int TM_BOOLEAN   = 1 << TC_BOOLEAN;
 310.535 -    public static final int TM_BYTE      = 1 << TC_BYTE;
 310.536 -    public static final int TM_CHAR      = 1 << TC_CHAR;
 310.537 -    public static final int TM_SHORT     = 1 << TC_SHORT;
 310.538 -    public static final int TM_INT       = 1 << TC_INT;
 310.539 -    public static final int TM_LONG      = 1 << TC_LONG;
 310.540 -    public static final int TM_FLOAT     = 1 << TC_FLOAT;
 310.541 -    public static final int TM_DOUBLE    = 1 << TC_DOUBLE;
 310.542 -    public static final int TM_ARRAY     = 1 << TC_ARRAY;
 310.543 -    public static final int TM_CLASS     = 1 << TC_CLASS;
 310.544 -    public static final int TM_METHOD    = 1 << TC_METHOD;
 310.545 -    public static final int TM_ERROR     = 1 << TC_ERROR;
 310.546 -
 310.547 -    public static final int TM_INT32     = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
 310.548 -    public static final int TM_NUM32     = TM_INT32 | TM_FLOAT;
 310.549 -    public static final int TM_NUM64     = TM_LONG | TM_DOUBLE;
 310.550 -    public static final int TM_INTEGER   = TM_INT32 | TM_LONG;
 310.551 -    public static final int TM_REAL      = TM_FLOAT | TM_DOUBLE;
 310.552 -    public static final int TM_NUMBER    = TM_INTEGER | TM_REAL;
 310.553 -    public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
 310.554 -
 310.555 -    /*
 310.556 -     * Class status
 310.557 -     */
 310.558 -    public static final int CS_UNDEFINED        = 0;
 310.559 -    public static final int CS_UNDECIDED        = 1;
 310.560 -    public static final int CS_BINARY           = 2;
 310.561 -    public static final int CS_SOURCE           = 3;
 310.562 -    public static final int CS_PARSED           = 4;
 310.563 -    public static final int CS_COMPILED         = 5;
 310.564 -    public static final int CS_NOTFOUND         = 6;
 310.565 -
 310.566 -    /*
 310.567 -     * Attributes
 310.568 -     */
 310.569 -    public static final int ATT_ALL             = -1;
 310.570 -    public static final int ATT_CODE            = 1;
 310.571 -
 310.572 -    /*
 310.573 -     * Number of bits used in file offsets
 310.574 -     */
 310.575 -    public static final int OFFSETBITS          = 19;
 310.576 -    public static final int MAXFILESIZE         = (1 << OFFSETBITS) - 1;
 310.577 -    public static final int MAXLINENUMBER       = (1 << (32 - OFFSETBITS)) - 1;
 310.578 -
 310.579 -    /*
 310.580 -     * Operators
 310.581 -     */
 310.582 -    public final int COMMA              = 0;
 310.583 -    public final int ASSIGN             = 1;
 310.584 -
 310.585 -    public final int ASGMUL             = 2;
 310.586 -    public final int ASGDIV             = 3;
 310.587 -    public final int ASGREM             = 4;
 310.588 -    public final int ASGADD             = 5;
 310.589 -    public final int ASGSUB             = 6;
 310.590 -    public final int ASGLSHIFT          = 7;
 310.591 -    public final int ASGRSHIFT          = 8;
 310.592 -    public final int ASGURSHIFT         = 9;
 310.593 -    public final int ASGBITAND          = 10;
 310.594 -    public final int ASGBITOR           = 11;
 310.595 -    public final int ASGBITXOR          = 12;
 310.596 -
 310.597 -    public final int COND               = 13;
 310.598 -    public final int OR                 = 14;
 310.599 -    public final int AND                = 15;
 310.600 -    public final int BITOR              = 16;
 310.601 -    public final int BITXOR             = 17;
 310.602 -    public final int BITAND             = 18;
 310.603 -    public final int NE                 = 19;
 310.604 -    public final int EQ                 = 20;
 310.605 -    public final int GE                 = 21;
 310.606 -    public final int GT                 = 22;
 310.607 -    public final int LE                 = 23;
 310.608 -    public final int LT                 = 24;
 310.609 -    public final int INSTANCEOF         = 25;
 310.610 -    public final int LSHIFT             = 26;
 310.611 -    public final int RSHIFT             = 27;
 310.612 -    public final int URSHIFT            = 28;
 310.613 -    public final int ADD                = 29;
 310.614 -    public final int SUB                = 30;
 310.615 -    public final int DIV                = 31;
 310.616 -    public final int REM                = 32;
 310.617 -    public final int MUL                = 33;
 310.618 -    public final int CAST               = 34;           // (x)y
 310.619 -    public final int POS                = 35;           // +x
 310.620 -    public final int NEG                = 36;           // -x
 310.621 -    public final int NOT                = 37;
 310.622 -    public final int BITNOT             = 38;
 310.623 -    public final int PREINC             = 39;           // ++x
 310.624 -    public final int PREDEC             = 40;           // --x
 310.625 -    public final int NEWARRAY           = 41;
 310.626 -    public final int NEWINSTANCE        = 42;
 310.627 -    public final int NEWFROMNAME        = 43;
 310.628 -    public final int POSTINC            = 44;           // x++
 310.629 -    public final int POSTDEC            = 45;           // x--
 310.630 -    public final int FIELD              = 46;
 310.631 -    public final int METHOD             = 47;           // x(y)
 310.632 -    public final int ARRAYACCESS        = 48;           // x[y]
 310.633 -    public final int NEW                = 49;
 310.634 -    public final int INC                = 50;
 310.635 -    public final int DEC                = 51;
 310.636 -
 310.637 -    public final int CONVERT            = 55;           // implicit conversion
 310.638 -    public final int EXPR               = 56;           // (x)
 310.639 -    public final int ARRAY              = 57;           // {x, y, ...}
 310.640 -    public final int GOTO               = 58;
 310.641 -
 310.642 -    /*
 310.643 -     * Value tokens
 310.644 -     */
 310.645 -    public final int IDENT              = 60;
 310.646 -    public final int BOOLEANVAL         = 61;
 310.647 -    public final int BYTEVAL            = 62;
 310.648 -    public final int CHARVAL            = 63;
 310.649 -    public final int SHORTVAL           = 64;
 310.650 -    public final int INTVAL                     = 65;
 310.651 -    public final int LONGVAL            = 66;
 310.652 -    public final int FLOATVAL           = 67;
 310.653 -    public final int DOUBLEVAL          = 68;
 310.654 -    public final int STRINGVAL          = 69;
 310.655 -
 310.656 -    /*
 310.657 -     * Type keywords
 310.658 -     */
 310.659 -    public final int BYTE               = 70;
 310.660 -    public final int CHAR               = 71;
 310.661 -    public final int SHORT              = 72;
 310.662 -    public final int INT                = 73;
 310.663 -    public final int LONG               = 74;
 310.664 -    public final int FLOAT              = 75;
 310.665 -    public final int DOUBLE             = 76;
 310.666 -    public final int VOID               = 77;
 310.667 -    public final int BOOLEAN            = 78;
 310.668 -
 310.669 -    /*
 310.670 -     * Expression keywords
 310.671 -     */
 310.672 -    public final int TRUE               = 80;
 310.673 -    public final int FALSE              = 81;
 310.674 -    public final int THIS               = 82;
 310.675 -    public final int SUPER              = 83;
 310.676 -    public final int NULL               = 84;
 310.677 -
 310.678 -    /*
 310.679 -     * Statement keywords
 310.680 -     */
 310.681 -    public final int IF                 = 90;
 310.682 -    public final int ELSE               = 91;
 310.683 -    public final int FOR                = 92;
 310.684 -    public final int WHILE              = 93;
 310.685 -    public final int DO                 = 94;
 310.686 -    public final int SWITCH             = 95;
 310.687 -    public final int CASE               = 96;
 310.688 -    public final int DEFAULT            = 97;
 310.689 -    public final int BREAK              = 98;
 310.690 -    public final int CONTINUE           = 99;
 310.691 -    public final int RETURN             = 100;
 310.692 -    public final int TRY                = 101;
 310.693 -    public final int CATCH              = 102;
 310.694 -    public final int FINALLY            = 103;
 310.695 -    public final int THROW              = 104;
 310.696 -    public final int STAT               = 105;
 310.697 -    public final int EXPRESSION         = 106;
 310.698 -    public final int DECLARATION        = 107;
 310.699 -    public final int VARDECLARATION     = 108;
 310.700 -
 310.701 -    /*
 310.702 -     * Declaration keywords
 310.703 -     */
 310.704 -    public final int IMPORT             = 110;
 310.705 -    public final int CLASS              = 111;
 310.706 -    public final int EXTENDS            = 112;
 310.707 -    public final int IMPLEMENTS         = 113;
 310.708 -    public final int INTERFACE          = 114;
 310.709 -    public final int PACKAGE            = 115;
 310.710 -
 310.711 -    /*
 310.712 -     * Modifier keywords
 310.713 -     */
 310.714 -    public final int PRIVATE    = 120;
 310.715 -    public final int PUBLIC             = 121;
 310.716 -    public final int PROTECTED  = 122;
 310.717 -    public final int CONST              = 123;
 310.718 -    public final int STATIC             = 124;
 310.719 -    public final int TRANSIENT          = 125;
 310.720 -    public final int SYNCHRONIZED       = 126;
 310.721 -    public final int NATIVE             = 127;
 310.722 -    public final int FINAL              = 128;
 310.723 -    public final int VOLATILE   = 129;
 310.724 -    public final int ABSTRACT   = 130;
 310.725 -    public final int STRICT             = 165;
 310.726 -
 310.727 -    /*
 310.728 -     * Punctuation
 310.729 -     */
 310.730 -    public final int SEMICOLON  = 135;
 310.731 -    public final int COLON              = 136;
 310.732 -    public final int QUESTIONMARK       = 137;
 310.733 -    public final int LBRACE             = 138;
 310.734 -    public final int RBRACE             = 139;
 310.735 -    public final int LPAREN             = 140;
 310.736 -    public final int RPAREN             = 141;
 310.737 -    public final int LSQBRACKET = 142;
 310.738 -    public final int RSQBRACKET = 143;
 310.739 -    public final int THROWS     = 144;
 310.740 -
 310.741 -    /*
 310.742 -     * Special tokens
 310.743 -     */
 310.744 -    public final int ERROR              = 145;          // an error
 310.745 -    public final int COMMENT    = 146;          // not used anymore.
 310.746 -    public final int TYPE               = 147;
 310.747 -    public final int LENGTH             = 148;
 310.748 -    public final int INLINERETURN       = 149;
 310.749 -    public final int INLINEMETHOD       = 150;
 310.750 -    public final int INLINENEWINSTANCE  = 151;
 310.751 -
 310.752 -    /*
 310.753 -     * Added for jasm
 310.754 -     */
 310.755 -        public final int METHODREF      = 152;
 310.756 -        public final int FIELDREF       = 153;
 310.757 -    public final int STACK              = 154;
 310.758 -    public final int LOCAL              = 155;
 310.759 -    public final int CPINDEX    = 156;
 310.760 -    public final int CPNAME             = 157;
 310.761 -    public final int SIGN               = 158;
 310.762 -    public final int BITS               = 159;
 310.763 -    public final int INF                = 160;
 310.764 -    public final int NAN                = 161;
 310.765 -    public final int INNERCLASS = 162;
 310.766 -    public final int OF         = 163;
 310.767 -    public final int SYNTHETIC          = 164;
 310.768 -// last used=165;
 310.769 -
 310.770 -   /*
 310.771 -     * Operator precedence
 310.772 -     */
 310.773 -    public static final int opPrecedence[] = {
 310.774 -        10,     11,     11,     11,     11,     11,     11,     11,     11,     11,
 310.775 -        11,     11,     11,     12,     13,     14,     15,     16,     17,     18,
 310.776 -        18,     19,     19,     19,     19,     19,     20,     20,     20,     21,
 310.777 -        21,     22,     22,     22,     23,     24,     24,     24,     24,     24,
 310.778 -        24,     25,     25,     26,     26,     26,     26,     26,     26
 310.779 -    };
 310.780 -
 310.781 -    /*
 310.782 -     * Operator names
 310.783 -     */
 310.784 -    public static final String opNames[] = {
 310.785 -        ",",            "=",            "*=",           "/=",           "%=",
 310.786 -        "+=",           "-=",           "<<=",          ">>=",          "<<<=",
 310.787 -        "&=",           "|=",           "^=",           "?:",           "||",
 310.788 -        "&&",           "|",            "^",            "&",            "!=",
 310.789 -        "==",           ">=",           ">",            "<=",           "<",
 310.790 -        "instanceof",   "<<",           ">>",           "<<<",          "+",
 310.791 -        "-",            "/",            "%",            "*",            "cast",
 310.792 -        "+",            "-",            "!",            "~",            "++",
 310.793 -        "--",           "new",          "new",          "new",          "++",
 310.794 -        "--",           "field",        "method",       "[]",           "new",
 310.795 -        "++",           "--",           null,           null,           null,
 310.796 -
 310.797 -        "convert",      "expr",         "array",        "goto",         null,
 310.798 -
 310.799 -        "Identifier",   "Boolean",      "Byte",         "Char",         "Short",
 310.800 -        "Integer",              "Long",         "Float",        "Double",       "String",
 310.801 -
 310.802 -        "byte",         "char",         "short",        "int",          "long",
 310.803 -        "float",        "double",       "void",         "boolean",      null,
 310.804 -
 310.805 -        "true",         "false",        "this",         "super",        "null",
 310.806 -        null,           null,           null,           null,           null,
 310.807 -
 310.808 -        "if",           "else",         "for",          "while",        "do",
 310.809 -        "switch",       "case",         "default",      "break",        "continue",
 310.810 -        "return",       "try",          "catch",        "finally",      "throw",
 310.811 -        "stat",         "expression",   "declaration",  "declaration",  null,
 310.812 -
 310.813 -        "import",       "class",        "extends",      "implements",   "interface",
 310.814 -        "package",      null,           null,           null,           null,
 310.815 -
 310.816 -        "private",      "public",       "protected",    "const",        "static",
 310.817 -        "transient",    "synchronized", "native",       "final",        "volatile",
 310.818 -        "abstract",     null,           null,           null,           null,
 310.819 -
 310.820 -        ";",            ":",            "?",            "{",            "}",
 310.821 -        "(",            ")",            "[",            "]",            "throws",
 310.822 -        "error",        "comment",      "type",         "length",       "inline-return",
 310.823 -        "inline-method", "inline-new",
 310.824 -        "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN",
 310.825 -        "bits", "INF", "NaN", "InnerClass", "of", "synthetic"
 310.826 -    };
 310.827 -    
 310.828 +*/
 310.829      static class AnnotationParser {
 310.830  
 310.831          private final boolean textual;
 310.832 @@ -1332,15 +535,11 @@
 310.833          private int super_class;
 310.834          private int interfaces_count;
 310.835          private int[] interfaces = new int[0];
 310.836 -        private int fields_count;
 310.837          private FieldData[] fields;
 310.838 -        private int methods_count;
 310.839          private MethodData[] methods;
 310.840          private InnerClassData[] innerClasses;
 310.841          private int attributes_count;
 310.842          private AttrData[] attrs;
 310.843 -        private String classname;
 310.844 -        private String superclassname;
 310.845          private int source_cpx = 0;
 310.846          private byte tags[];
 310.847          private Hashtable indexHashAscii = new Hashtable();
 310.848 @@ -1845,6 +1044,12 @@
 310.849                              case '\"':
 310.850                                  sb.append('\\').append('\"');
 310.851                                  break;
 310.852 +                            case '\u2028':
 310.853 +                                sb.append("\\u2028");
 310.854 +                                break;
 310.855 +                            case '\u2029':
 310.856 +                                sb.append("\\u2029");
 310.857 +                                break;
 310.858                              default:
 310.859                                  sb.append(c);
 310.860                          }
 310.861 @@ -2080,7 +1285,7 @@
 310.862          int name_index;
 310.863          int descriptor_index;
 310.864          int attributes_count;
 310.865 -        int value_cpx = 0;
 310.866 +        int value_cpx = -1;
 310.867          boolean isSynthetic = false;
 310.868          boolean isDeprecated = false;
 310.869          Vector attrs;
 310.870 @@ -2201,11 +1406,8 @@
 310.871              return isDeprecated;
 310.872          }
 310.873  
 310.874 -        /**
 310.875 -         * Returns index of constant value in cpool.
 310.876 -         */
 310.877 -        public int getConstantValueIndex() {
 310.878 -            return (value_cpx);
 310.879 +        public boolean hasConstantValue() {
 310.880 +            return value_cpx != -1;
 310.881          }
 310.882  
 310.883          /**
 310.884 @@ -2824,6 +2026,10 @@
 310.885              lastFrameByteCodeOffset = -1;
 310.886              advanceBy(0);
 310.887          }
 310.888 +        
 310.889 +        public boolean isEmpty() {
 310.890 +            return stackMapTable.length == 0;
 310.891 +        }
 310.892  
 310.893          public String getFrameAsString() {
 310.894              return (nextFrameIndex == 0)
   311.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Apr 29 15:25:58 2014 +0200
   311.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Apr 30 15:04:10 2014 +0200
   311.3 @@ -25,14 +25,36 @@
   311.4   *
   311.5   * @author Jaroslav Tulach <jtulach@netbeans.org>
   311.6   */
   311.7 -abstract class ByteCodeToJavaScript {
   311.8 +abstract class ByteCodeToJavaScript implements Appendable {
   311.9      private ClassData jc;
  311.10 -    final Appendable out;
  311.11 +    private final Appendable out;
  311.12 +    private boolean outChanged;
  311.13  
  311.14      protected ByteCodeToJavaScript(Appendable out) {
  311.15          this.out = out;
  311.16      }
  311.17      
  311.18 +    @Override
  311.19 +    public final Appendable append(CharSequence csq) throws IOException {
  311.20 +        out.append(csq);
  311.21 +        outChanged = true;
  311.22 +        return this;
  311.23 +    }
  311.24 +
  311.25 +    @Override
  311.26 +    public final Appendable append(CharSequence csq, int start, int end) throws IOException {
  311.27 +        out.append(csq, start, end);
  311.28 +        outChanged = true;
  311.29 +        return this;
  311.30 +    }
  311.31 +
  311.32 +    @Override
  311.33 +    public final Appendable append(char c) throws IOException {
  311.34 +        out.append(c);
  311.35 +        outChanged = true;
  311.36 +        return this;
  311.37 +    }
  311.38 +    
  311.39      /* Collects additional required resources.
  311.40       * 
  311.41       * @param internalClassName classes that were referenced and should be loaded in order the
  311.42 @@ -99,7 +121,7 @@
  311.43       * @throws IOException 
  311.44       */
  311.45      boolean debug(String msg) throws IOException {
  311.46 -        out.append(msg);
  311.47 +        append(msg);
  311.48          return true;
  311.49      }
  311.50  
  311.51 @@ -124,16 +146,34 @@
  311.52              );
  311.53          }
  311.54          byte[] arrData = jc.findAnnotationData(true);
  311.55 -        String[] arr = findAnnotation(arrData, jc, 
  311.56 -            "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
  311.57 -            "resource", "processByteCode"
  311.58 -        );
  311.59 -        if (arr != null) {
  311.60 -            if (!arr[0].isEmpty()) {
  311.61 -                requireScript(arr[0]);
  311.62 +        {
  311.63 +            String[] arr = findAnnotation(arrData, jc, 
  311.64 +                "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
  311.65 +                "resource", "processByteCode"
  311.66 +            );
  311.67 +            if (arr != null) {
  311.68 +                if (!arr[0].isEmpty()) {
  311.69 +                    requireScript(arr[0]);
  311.70 +                }
  311.71 +                if ("0".equals(arr[1])) {
  311.72 +                    return null;
  311.73 +                }
  311.74              }
  311.75 -            if ("0".equals(arr[1])) {
  311.76 -                return null;
  311.77 +        }
  311.78 +        {
  311.79 +            String[] arr = findAnnotation(arrData, jc, 
  311.80 +                "net.java.html.js.JavaScriptResource", 
  311.81 +                "value"
  311.82 +            );
  311.83 +            if (arr != null) {
  311.84 +                if (arr[0].startsWith("/")) {
  311.85 +                    requireScript(arr[0]);
  311.86 +                } else {
  311.87 +                    int last = jc.getClassName().lastIndexOf('/');
  311.88 +                    requireScript(
  311.89 +                        jc.getClassName().substring(0, last + 1).replace('.', '/') + arr[0]
  311.90 +                    );
  311.91 +                }
  311.92              }
  311.93          }
  311.94          String[] proto = findAnnotation(arrData, jc, 
  311.95 @@ -142,34 +182,39 @@
  311.96          );
  311.97          StringArray toInitilize = new StringArray();
  311.98          final String className = className(jc);
  311.99 -        out.append("\n\n").append(assignClass(className));
 311.100 -        out.append("function ").append(className).append("() {");
 311.101 -        out.append("\n  var CLS = ").append(className).append(';');
 311.102 -        out.append("\n  if (!CLS.$class) {");
 311.103 +        append("\n\n").append(assignClass(className));
 311.104 +        append("function ").append(className).append("() {");
 311.105 +        append("\n  var CLS = ").append(className).append(';');
 311.106 +        append("\n  if (!CLS.$class) {");
 311.107          if (proto == null) {
 311.108              String sc = jc.getSuperClassName(); // with _
 311.109 -            out.append("\n    var pp = ").
 311.110 -                append(accessClass(sc.replace('/', '_'))).append("(true);");
 311.111 -            out.append("\n    var p = CLS.prototype = pp;");
 311.112 -            out.append("\n    var c = p;");
 311.113 -            out.append("\n    var sprcls = pp.constructor.$class;");
 311.114 +            append("\n    var pp = ").
 311.115 +                append(accessClass(mangleClassName(sc))).append("(true);");
 311.116 +            append("\n    var p = CLS.prototype = pp;");
 311.117 +            append("\n    var c = p;");
 311.118 +            append("\n    var sprcls = pp.constructor.$class;");
 311.119          } else {
 311.120 -            out.append("\n    var p = CLS.prototype = ").append(proto[1]).append(";");
 311.121 +            append("\n    var p = CLS.prototype = ").append(proto[1]).append(";");
 311.122              if (proto[0] == null) {
 311.123                  proto[0] = "p";
 311.124              }
 311.125 -            out.append("\n    var c = ").append(proto[0]).append(";");
 311.126 -            out.append("\n    var sprcls = null;");
 311.127 +            append("\n    var c = ").append(proto[0]).append(";");
 311.128 +            append("\n    var sprcls = null;");
 311.129          }
 311.130          for (FieldData v : jc.getFields()) {
 311.131              if (v.isStatic()) {
 311.132 -                out.append("\n  CLS.").append(v.getName()).append(initField(v));
 311.133 -                out.append("\n  c._").append(v.getName()).append(" = function (v) {")
 311.134 -                   .append("  if (arguments.length == 1) CLS.").append(v.getName())
 311.135 -                   .append(" = v; return CLS.").
 311.136 +                if ((v.access & ACC_FINAL) != 0 && v.hasConstantValue()) {
 311.137 +                    if (v.getInternalSig().length() == 1 || v.getInternalSig().equals("Ljava/lang/String;")) {
 311.138 +                        continue;
 311.139 +                    }
 311.140 +                }
 311.141 +                append("\n  CLS.fld_").append(v.getName()).append(initField(v));
 311.142 +                append("\n  c._").append(v.getName()).append(" = function (v) {")
 311.143 +                   .append("  if (arguments.length == 1) CLS.fld_").append(v.getName())
 311.144 +                   .append(" = v; return CLS.fld_").
 311.145                      append(v.getName()).append("; };");
 311.146              } else {
 311.147 -                out.append("\n  c._").append(v.getName()).append(" = function (v) {")
 311.148 +                append("\n  c._").append(v.getName()).append(" = function (v) {")
 311.149                     .append("  if (arguments.length == 1) this.fld_").
 311.150                      append(className).append('_').append(v.getName())
 311.151                     .append(" = v; return this.fld_").
 311.152 @@ -187,14 +232,14 @@
 311.153              );
 311.154              if (only != null) {
 311.155                  if (only[0] != null && only[1] != null) {
 311.156 -                    out.append("\n    p.").append(only[0]).append(" = ")
 311.157 +                    append("\n    p.").append(only[0]).append(" = ")
 311.158                          .append(only[1]).append(";");
 311.159                  }
 311.160                  continue;
 311.161              }
 311.162              String destObject;
 311.163              String mn;
 311.164 -            out.append("\n    ");
 311.165 +            append("\n    ");
 311.166              if (m.isStatic()) {
 311.167                  destObject = "c";
 311.168                  mn = generateStaticMethod(destObject, m, toInitilize);
 311.169 @@ -210,39 +255,47 @@
 311.170              declaredMethod(m, destObject, mn);
 311.171              byte[] runAnno = m.findAnnotationData(false);
 311.172              if (runAnno != null) {
 311.173 -                out.append("\n    ").append(destObject).append(".").append(mn).append(".anno = {");
 311.174 -                generateAnno(jc, out, runAnno);
 311.175 -                out.append("\n    };");
 311.176 +                append("\n    ").append(destObject).append(".").append(mn).append(".anno = {");
 311.177 +                generateAnno(jc, runAnno);
 311.178 +                append("\n    };");
 311.179              }
 311.180 -            out.append("\n    ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
 311.181 -            out.append("\n    ").append(destObject).append(".").append(mn).append(".cls = CLS;");
 311.182 +            append("\n    ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
 311.183 +            append("\n    ").append(destObject).append(".").append(mn).append(".cls = CLS;");
 311.184          }
 311.185 -        out.append("\n    c.constructor = CLS;");
 311.186 -        out.append("\n    c['$instOf_").append(className).append("'] = true;");
 311.187 +        append("\n    c.constructor = CLS;");
 311.188 +        append("\n    function fillInstOf(x) {");
 311.189 +        String instOfName = "$instOf_" + className;
 311.190 +        append("\n        x['").append(instOfName).append("'] = true;");
 311.191          for (String superInterface : jc.getSuperInterfaces()) {
 311.192 -            out.append("\n    c['$instOf_").append(superInterface.replace('/', '_')).append("'] = true;");
 311.193 +            String intrfc = superInterface.replace('/', '_');
 311.194 +            append("\n      vm.").append(intrfc).append("(false)['fillInstOf'](x);");
 311.195 +            requireReference(superInterface);
 311.196          }
 311.197 -        out.append("\n    CLS.$class = 'temp';");
 311.198 -        out.append("\n    CLS.$class = ");
 311.199 -        out.append(accessClass("java_lang_Class(true);"));
 311.200 -        out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
 311.201 -        out.append("\n    CLS.$class.superclass = sprcls;");
 311.202 -        out.append("\n    CLS.$class.access = ").append(jc.getAccessFlags()+";");
 311.203 -        out.append("\n    CLS.$class.cnstr = CLS;");
 311.204 +        append("\n    }");
 311.205 +        append("\n    c['fillInstOf'] = fillInstOf;");
 311.206 +        append("\n    fillInstOf(c);");
 311.207 +//        obfuscationDelegate.exportJSProperty(this, "c", instOfName);
 311.208 +        append("\n    CLS.$class = 'temp';");
 311.209 +        append("\n    CLS.$class = ");
 311.210 +        append(accessClass("java_lang_Class(true);"));
 311.211 +        append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
 311.212 +        append("\n    CLS.$class.superclass = sprcls;");
 311.213 +        append("\n    CLS.$class.access = ").append(jc.getAccessFlags()+";");
 311.214 +        append("\n    CLS.$class.cnstr = CLS;");
 311.215          byte[] classAnno = jc.findAnnotationData(false);
 311.216          if (classAnno != null) {
 311.217 -            out.append("\n    CLS.$class.anno = {");
 311.218 -            generateAnno(jc, out, classAnno);
 311.219 -            out.append("\n    };");
 311.220 +            append("\n    CLS.$class.anno = {");
 311.221 +            generateAnno(jc, classAnno);
 311.222 +            append("\n    };");
 311.223          }
 311.224          for (String init : toInitilize.toArray()) {
 311.225 -            out.append("\n    ").append(init).append("();");
 311.226 +            append("\n    ").append(init).append("();");
 311.227          }
 311.228 -        out.append("\n  }");
 311.229 -        out.append("\n  if (arguments.length === 0) {");
 311.230 -        out.append("\n    if (!(this instanceof CLS)) {");
 311.231 -        out.append("\n      return new CLS();");
 311.232 -        out.append("\n    }");
 311.233 +        append("\n  }");
 311.234 +        append("\n  if (arguments.length === 0) {");
 311.235 +        append("\n    if (!(this instanceof CLS)) {");
 311.236 +        append("\n      return new CLS();");
 311.237 +        append("\n    }");
 311.238          for (FieldData v : jc.getFields()) {
 311.239              byte[] onlyArr = v.findAnnotationData(true);
 311.240              String[] only = findAnnotation(onlyArr, jc, 
 311.241 @@ -251,21 +304,21 @@
 311.242              );
 311.243              if (only != null) {
 311.244                  if (only[0] != null && only[1] != null) {
 311.245 -                    out.append("\n    p.").append(only[0]).append(" = ")
 311.246 +                    append("\n    p.").append(only[0]).append(" = ")
 311.247                          .append(only[1]).append(";");
 311.248                  }
 311.249                  continue;
 311.250              }
 311.251              if (!v.isStatic()) {
 311.252 -                out.append("\n    this.fld_").
 311.253 +                append("\n    this.fld_").
 311.254                      append(className).append('_').
 311.255                      append(v.getName()).append(initField(v));
 311.256              }
 311.257          }
 311.258 -        out.append("\n    return this;");
 311.259 -        out.append("\n  }");
 311.260 -        out.append("\n  return arguments[0] ? new CLS() : CLS.prototype;");
 311.261 -        out.append("\n};");
 311.262 +        append("\n    return this;");
 311.263 +        append("\n  }");
 311.264 +        append("\n  return arguments[0] ? new CLS() : CLS.prototype;");
 311.265 +        append("\n};");
 311.266  
 311.267          declaredClass(jc, className);
 311.268  
 311.269 @@ -305,34 +358,43 @@
 311.270          final LocalsMapper lmapper =
 311.271                  new LocalsMapper(stackMapIterator.getArguments());
 311.272  
 311.273 -        out.append(destObject).append(".").append(name).append(" = function(");
 311.274 -        lmapper.outputArguments(out, m.isStatic());
 311.275 -        out.append(") {").append("\n");
 311.276 +        append(destObject).append(".").append(name).append(" = function(");
 311.277 +        lmapper.outputArguments(this, m.isStatic());
 311.278 +        append(") {").append("\n");
 311.279  
 311.280          final byte[] byteCodes = m.getCode();
 311.281          if (byteCodes == null) {
 311.282 -            out.append("  throw 'no code found for ")
 311.283 +            append("  throw 'no code found for ")
 311.284                 .append(jc.getClassName()).append('.')
 311.285                 .append(m.getName()).append("';\n");
 311.286 -            out.append("};");
 311.287 +            append("};");
 311.288              return;
 311.289          }
 311.290  
 311.291          final StackMapper smapper = new StackMapper();
 311.292  
 311.293          if (!m.isStatic()) {
 311.294 -            out.append("  var ").append(" lcA0 = this;\n");
 311.295 +            append("  var ").append(" lcA0 = this;\n");
 311.296          }
 311.297  
 311.298 -        int lastStackFrame = -1;
 311.299 +        int lastStackFrame;
 311.300          TrapData[] previousTrap = null;
 311.301          boolean wide = false;
 311.302 +        boolean didBranches;
 311.303 +        if (stackMapIterator.isEmpty()) {
 311.304 +            didBranches = false;
 311.305 +            lastStackFrame = 0;
 311.306 +        } else {
 311.307 +            didBranches = true;
 311.308 +            lastStackFrame = -1;
 311.309 +            append("\n  var gt = 0;\n");
 311.310 +        }
 311.311          
 311.312 -        out.append("\n  var gt = 0;\n");
 311.313          int openBraces = 0;
 311.314          int topMostLabel = 0;
 311.315          for (int i = 0; i < byteCodes.length; i++) {
 311.316              int prev = i;
 311.317 +            outChanged = false;
 311.318              stackMapIterator.advanceTo(i);
 311.319              boolean changeInCatch = trap.advanceTo(i);
 311.320              if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
 311.321 @@ -342,12 +404,13 @@
 311.322                  }
 311.323              }
 311.324              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
 311.325 +                smapper.flush(this);
 311.326                  if (i != 0) {
 311.327 -                    out.append("    }\n");
 311.328 +                    append("    }\n");
 311.329                  }
 311.330                  if (openBraces > 64) {
 311.331                      for (int c = 0; c < 64; c++) {
 311.332 -                        out.append("break;}\n");
 311.333 +                        append("break;}\n");
 311.334                      }
 311.335                      openBraces = 1;
 311.336                      topMostLabel = i;
 311.337 @@ -356,85 +419,84 @@
 311.338                  lastStackFrame = stackMapIterator.getFrameIndex();
 311.339                  lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
 311.340                  smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
 311.341 -                out.append("    X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
 311.342 +                append("    X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
 311.343                  openBraces++;
 311.344                  changeInCatch = true;
 311.345              } else {
 311.346                  debug("    /* " + i + " */ ");
 311.347              }
 311.348              if (changeInCatch && trap.useTry()) {
 311.349 -                out.append("try {");
 311.350 +                append("try {");
 311.351                  previousTrap = trap.current();
 311.352              }
 311.353              final int c = readUByte(byteCodes, i);
 311.354              switch (c) {
 311.355                  case opc_aload_0:
 311.356 -                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0));
 311.357 +                    smapper.assign(this, VarType.REFERENCE, lmapper.getA(0));
 311.358                      break;
 311.359                  case opc_iload_0:
 311.360 -                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0));
 311.361 +                    smapper.assign(this, VarType.INTEGER, lmapper.getI(0));
 311.362                      break;
 311.363                  case opc_lload_0:
 311.364 -                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0));
 311.365 +                    smapper.assign(this, VarType.LONG, lmapper.getL(0));
 311.366                      break;
 311.367                  case opc_fload_0:
 311.368 -                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0));
 311.369 +                    smapper.assign(this, VarType.FLOAT, lmapper.getF(0));
 311.370                      break;
 311.371                  case opc_dload_0:
 311.372 -                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0));
 311.373 +                    smapper.assign(this, VarType.DOUBLE, lmapper.getD(0));
 311.374                      break;
 311.375                  case opc_aload_1:
 311.376 -                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1));
 311.377 +                    smapper.assign(this, VarType.REFERENCE, lmapper.getA(1));
 311.378                      break;
 311.379                  case opc_iload_1:
 311.380 -                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1));
 311.381 +                    smapper.assign(this, VarType.INTEGER, lmapper.getI(1));
 311.382                      break;
 311.383                  case opc_lload_1:
 311.384 -                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1));
 311.385 +                    smapper.assign(this, VarType.LONG, lmapper.getL(1));
 311.386                      break;
 311.387                  case opc_fload_1:
 311.388 -                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1));
 311.389 +                    smapper.assign(this, VarType.FLOAT, lmapper.getF(1));
 311.390                      break;
 311.391                  case opc_dload_1:
 311.392 -                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1));
 311.393 +                    smapper.assign(this, VarType.DOUBLE, lmapper.getD(1));
 311.394                      break;
 311.395                  case opc_aload_2:
 311.396 -                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2));
 311.397 +                    smapper.assign(this, VarType.REFERENCE, lmapper.getA(2));
 311.398                      break;
 311.399                  case opc_iload_2:
 311.400 -                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2));
 311.401 +                    smapper.assign(this, VarType.INTEGER, lmapper.getI(2));
 311.402                      break;
 311.403                  case opc_lload_2:
 311.404 -                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2));
 311.405 +                    smapper.assign(this, VarType.LONG, lmapper.getL(2));
 311.406                      break;
 311.407                  case opc_fload_2:
 311.408 -                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2));
 311.409 +                    smapper.assign(this, VarType.FLOAT, lmapper.getF(2));
 311.410                      break;
 311.411                  case opc_dload_2:
 311.412 -                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2));
 311.413 +                    smapper.assign(this, VarType.DOUBLE, lmapper.getD(2));
 311.414                      break;
 311.415                  case opc_aload_3:
 311.416 -                    emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3));
 311.417 +                    smapper.assign(this, VarType.REFERENCE, lmapper.getA(3));
 311.418                      break;
 311.419                  case opc_iload_3:
 311.420 -                    emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3));
 311.421 +                    smapper.assign(this, VarType.INTEGER, lmapper.getI(3));
 311.422                      break;
 311.423                  case opc_lload_3:
 311.424 -                    emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3));
 311.425 +                    smapper.assign(this, VarType.LONG, lmapper.getL(3));
 311.426                      break;
 311.427                  case opc_fload_3:
 311.428 -                    emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3));
 311.429 +                    smapper.assign(this, VarType.FLOAT, lmapper.getF(3));
 311.430                      break;
 311.431                  case opc_dload_3:
 311.432 -                    emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3));
 311.433 +                    smapper.assign(this, VarType.DOUBLE, lmapper.getD(3));
 311.434                      break;
 311.435                  case opc_iload: {
 311.436                      ++i;
 311.437                      final int indx = wide ? readUShort(byteCodes, i++)
 311.438                                            : readUByte(byteCodes, i);
 311.439                      wide = false;
 311.440 -                    emit(out, "var @1 = @2;",
 311.441 -                         smapper.pushI(), lmapper.getI(indx));
 311.442 +                    smapper.assign(this, VarType.INTEGER, lmapper.getI(indx));
 311.443                      break;
 311.444                  }
 311.445                  case opc_lload: {
 311.446 @@ -442,8 +504,7 @@
 311.447                      final int indx = wide ? readUShort(byteCodes, i++)
 311.448                                            : readUByte(byteCodes, i);
 311.449                      wide = false;
 311.450 -                    emit(out, "var @1 = @2;",
 311.451 -                         smapper.pushL(), lmapper.getL(indx));
 311.452 +                    smapper.assign(this, VarType.LONG, lmapper.getL(indx));
 311.453                      break;
 311.454                  }
 311.455                  case opc_fload: {
 311.456 @@ -451,8 +512,7 @@
 311.457                      final int indx = wide ? readUShort(byteCodes, i++)
 311.458                                            : readUByte(byteCodes, i);
 311.459                      wide = false;
 311.460 -                    emit(out, "var @1 = @2;",
 311.461 -                         smapper.pushF(), lmapper.getF(indx));
 311.462 +                    smapper.assign(this, VarType.FLOAT, lmapper.getF(indx));
 311.463                      break;
 311.464                  }
 311.465                  case opc_dload: {
 311.466 @@ -460,8 +520,7 @@
 311.467                      final int indx = wide ? readUShort(byteCodes, i++)
 311.468                                            : readUByte(byteCodes, i);
 311.469                      wide = false;
 311.470 -                    emit(out, "var @1 = @2;",
 311.471 -                         smapper.pushD(), lmapper.getD(indx));
 311.472 +                    smapper.assign(this, VarType.DOUBLE, lmapper.getD(indx));
 311.473                      break;
 311.474                  }
 311.475                  case opc_aload: {
 311.476 @@ -469,8 +528,7 @@
 311.477                      final int indx = wide ? readUShort(byteCodes, i++)
 311.478                                            : readUByte(byteCodes, i);
 311.479                      wide = false;
 311.480 -                    emit(out, "var @1 = @2;",
 311.481 -                         smapper.pushA(), lmapper.getA(indx));
 311.482 +                    smapper.assign(this, VarType.REFERENCE, lmapper.getA(indx));
 311.483                      break;
 311.484                  }
 311.485                  case opc_istore: {
 311.486 @@ -478,7 +536,7 @@
 311.487                      final int indx = wide ? readUShort(byteCodes, i++)
 311.488                                            : readUByte(byteCodes, i);
 311.489                      wide = false;
 311.490 -                    emit(out, "var @1 = @2;",
 311.491 +                    emit(smapper, this, "var @1 = @2;",
 311.492                           lmapper.setI(indx), smapper.popI());
 311.493                      break;
 311.494                  }
 311.495 @@ -487,7 +545,7 @@
 311.496                      final int indx = wide ? readUShort(byteCodes, i++)
 311.497                                            : readUByte(byteCodes, i);
 311.498                      wide = false;
 311.499 -                    emit(out, "var @1 = @2;",
 311.500 +                    emit(smapper, this, "var @1 = @2;",
 311.501                           lmapper.setL(indx), smapper.popL());
 311.502                      break;
 311.503                  }
 311.504 @@ -496,7 +554,7 @@
 311.505                      final int indx = wide ? readUShort(byteCodes, i++)
 311.506                                            : readUByte(byteCodes, i);
 311.507                      wide = false;
 311.508 -                    emit(out, "var @1 = @2;",
 311.509 +                    emit(smapper, this, "var @1 = @2;",
 311.510                           lmapper.setF(indx), smapper.popF());
 311.511                      break;
 311.512                  }
 311.513 @@ -505,7 +563,7 @@
 311.514                      final int indx = wide ? readUShort(byteCodes, i++)
 311.515                                            : readUByte(byteCodes, i);
 311.516                      wide = false;
 311.517 -                    emit(out, "var @1 = @2;",
 311.518 +                    emit(smapper, this, "var @1 = @2;",
 311.519                           lmapper.setD(indx), smapper.popD());
 311.520                      break;
 311.521                  }
 311.522 @@ -514,181 +572,181 @@
 311.523                      final int indx = wide ? readUShort(byteCodes, i++)
 311.524                                            : readUByte(byteCodes, i);
 311.525                      wide = false;
 311.526 -                    emit(out, "var @1 = @2;",
 311.527 +                    emit(smapper, this, "var @1 = @2;",
 311.528                           lmapper.setA(indx), smapper.popA());
 311.529                      break;
 311.530                  }
 311.531                  case opc_astore_0:
 311.532 -                    emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA());
 311.533 +                    emit(smapper, this, "var @1 = @2;", lmapper.setA(0), smapper.popA());
 311.534                      break;
 311.535                  case opc_istore_0:
 311.536 -                    emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI());
 311.537 +                    emit(smapper, this, "var @1 = @2;", lmapper.setI(0), smapper.popI());
 311.538                      break;
 311.539                  case opc_lstore_0:
 311.540 -                    emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL());
 311.541 +                    emit(smapper, this, "var @1 = @2;", lmapper.setL(0), smapper.popL());
 311.542                      break;
 311.543                  case opc_fstore_0:
 311.544 -                    emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF());
 311.545 +                    emit(smapper, this, "var @1 = @2;", lmapper.setF(0), smapper.popF());
 311.546                      break;
 311.547                  case opc_dstore_0:
 311.548 -                    emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD());
 311.549 +                    emit(smapper, this, "var @1 = @2;", lmapper.setD(0), smapper.popD());
 311.550                      break;
 311.551                  case opc_astore_1:
 311.552 -                    emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA());
 311.553 +                    emit(smapper, this, "var @1 = @2;", lmapper.setA(1), smapper.popA());
 311.554                      break;
 311.555                  case opc_istore_1:
 311.556 -                    emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI());
 311.557 +                    emit(smapper, this, "var @1 = @2;", lmapper.setI(1), smapper.popI());
 311.558                      break;
 311.559                  case opc_lstore_1:
 311.560 -                    emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL());
 311.561 +                    emit(smapper, this, "var @1 = @2;", lmapper.setL(1), smapper.popL());
 311.562                      break;
 311.563                  case opc_fstore_1:
 311.564 -                    emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF());
 311.565 +                    emit(smapper, this, "var @1 = @2;", lmapper.setF(1), smapper.popF());
 311.566                      break;
 311.567                  case opc_dstore_1:
 311.568 -                    emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD());
 311.569 +                    emit(smapper, this, "var @1 = @2;", lmapper.setD(1), smapper.popD());
 311.570                      break;
 311.571                  case opc_astore_2:
 311.572 -                    emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA());
 311.573 +                    emit(smapper, this, "var @1 = @2;", lmapper.setA(2), smapper.popA());
 311.574                      break;
 311.575                  case opc_istore_2:
 311.576 -                    emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI());
 311.577 +                    emit(smapper, this, "var @1 = @2;", lmapper.setI(2), smapper.popI());
 311.578                      break;
 311.579                  case opc_lstore_2:
 311.580 -                    emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL());
 311.581 +                    emit(smapper, this, "var @1 = @2;", lmapper.setL(2), smapper.popL());
 311.582                      break;
 311.583                  case opc_fstore_2:
 311.584 -                    emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF());
 311.585 +                    emit(smapper, this, "var @1 = @2;", lmapper.setF(2), smapper.popF());
 311.586                      break;
 311.587                  case opc_dstore_2:
 311.588 -                    emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD());
 311.589 +                    emit(smapper, this, "var @1 = @2;", lmapper.setD(2), smapper.popD());
 311.590                      break;
 311.591                  case opc_astore_3:
 311.592 -                    emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA());
 311.593 +                    emit(smapper, this, "var @1 = @2;", lmapper.setA(3), smapper.popA());
 311.594                      break;
 311.595                  case opc_istore_3:
 311.596 -                    emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI());
 311.597 +                    emit(smapper, this, "var @1 = @2;", lmapper.setI(3), smapper.popI());
 311.598                      break;
 311.599                  case opc_lstore_3:
 311.600 -                    emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL());
 311.601 +                    emit(smapper, this, "var @1 = @2;", lmapper.setL(3), smapper.popL());
 311.602                      break;
 311.603                  case opc_fstore_3:
 311.604 -                    emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF());
 311.605 +                    emit(smapper, this, "var @1 = @2;", lmapper.setF(3), smapper.popF());
 311.606                      break;
 311.607                  case opc_dstore_3:
 311.608 -                    emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD());
 311.609 +                    emit(smapper, this, "var @1 = @2;", lmapper.setD(3), smapper.popD());
 311.610                      break;
 311.611                  case opc_iadd:
 311.612 -                    emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
 311.613 +                    smapper.replace(this, VarType.INTEGER, "(@1).add32(@2)", smapper.getI(1), smapper.popI());
 311.614                      break;
 311.615                  case opc_ladd:
 311.616 -                    emit(out, "@1 = @1.add64(@2);", smapper.getL(1), smapper.popL());
 311.617 +                    smapper.replace(this, VarType.LONG, "(@1).add64(@2)", smapper.getL(1), smapper.popL());
 311.618                      break;
 311.619                  case opc_fadd:
 311.620 -                    emit(out, "@1 += @2;", smapper.getF(1), smapper.popF());
 311.621 +                    smapper.replace(this, VarType.FLOAT, "(@1 + @2)", smapper.getF(1), smapper.popF());
 311.622                      break;
 311.623                  case opc_dadd:
 311.624 -                    emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
 311.625 +                    smapper.replace(this, VarType.DOUBLE, "(@1 + @2)", smapper.getD(1), smapper.popD());
 311.626                      break;
 311.627                  case opc_isub:
 311.628 -                    emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
 311.629 +                    smapper.replace(this, VarType.INTEGER, "(@1).sub32(@2)", smapper.getI(1), smapper.popI());
 311.630                      break;
 311.631                  case opc_lsub:
 311.632 -                    emit(out, "@1 = @1.sub64(@2);", smapper.getL(1), smapper.popL());
 311.633 +                    smapper.replace(this, VarType.LONG, "(@1).sub64(@2)", smapper.getL(1), smapper.popL());
 311.634                      break;
 311.635                  case opc_fsub:
 311.636 -                    emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF());
 311.637 +                    smapper.replace(this, VarType.FLOAT, "(@1 - @2)", smapper.getF(1), smapper.popF());
 311.638                      break;
 311.639                  case opc_dsub:
 311.640 -                    emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
 311.641 +                    smapper.replace(this, VarType.DOUBLE, "(@1 - @2)", smapper.getD(1), smapper.popD());
 311.642                      break;
 311.643                  case opc_imul:
 311.644 -                    emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
 311.645 +                    smapper.replace(this, VarType.INTEGER, "(@1).mul32(@2)", smapper.getI(1), smapper.popI());
 311.646                      break;
 311.647                  case opc_lmul:
 311.648 -                    emit(out, "@1 = @1.mul64(@2);", smapper.getL(1), smapper.popL());
 311.649 +                    smapper.replace(this, VarType.LONG, "(@1).mul64(@2)", smapper.getL(1), smapper.popL());
 311.650                      break;
 311.651                  case opc_fmul:
 311.652 -                    emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF());
 311.653 +                    smapper.replace(this, VarType.FLOAT, "(@1 * @2)", smapper.getF(1), smapper.popF());
 311.654                      break;
 311.655                  case opc_dmul:
 311.656 -                    emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD());
 311.657 +                    smapper.replace(this, VarType.DOUBLE, "(@1 * @2)", smapper.getD(1), smapper.popD());
 311.658                      break;
 311.659                  case opc_idiv:
 311.660 -                    emit(out, "@1 = @1.div32(@2);",
 311.661 +                    smapper.replace(this, VarType.INTEGER, "(@1).div32(@2)",
 311.662                           smapper.getI(1), smapper.popI());
 311.663                      break;
 311.664                  case opc_ldiv:
 311.665 -                    emit(out, "@1 = @1.div64(@2);",
 311.666 +                    smapper.replace(this, VarType.LONG, "(@1).div64(@2)",
 311.667                           smapper.getL(1), smapper.popL());
 311.668                      break;
 311.669                  case opc_fdiv:
 311.670 -                    emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF());
 311.671 +                    smapper.replace(this, VarType.FLOAT, "(@1 / @2)", smapper.getF(1), smapper.popF());
 311.672                      break;
 311.673                  case opc_ddiv:
 311.674 -                    emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD());
 311.675 +                    smapper.replace(this, VarType.DOUBLE, "(@1 / @2)", smapper.getD(1), smapper.popD());
 311.676                      break;
 311.677                  case opc_irem:
 311.678 -                    emit(out, "@1 = @1.mod32(@2);",
 311.679 +                    smapper.replace(this, VarType.INTEGER, "(@1).mod32(@2)",
 311.680                           smapper.getI(1), smapper.popI());
 311.681                      break;
 311.682                  case opc_lrem:
 311.683 -                    emit(out, "@1 = @1.mod64(@2);",
 311.684 +                    smapper.replace(this, VarType.LONG, "(@1).mod64(@2)",
 311.685                           smapper.getL(1), smapper.popL());
 311.686                      break;
 311.687                  case opc_frem:
 311.688 -                    emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF());
 311.689 +                    smapper.replace(this, VarType.FLOAT, "(@1 % @2)", smapper.getF(1), smapper.popF());
 311.690                      break;
 311.691                  case opc_drem:
 311.692 -                    emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD());
 311.693 +                    smapper.replace(this, VarType.DOUBLE, "(@1 % @2)", smapper.getD(1), smapper.popD());
 311.694                      break;
 311.695                  case opc_iand:
 311.696 -                    emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI());
 311.697 +                    smapper.replace(this, VarType.INTEGER, "(@1 & @2)", smapper.getI(1), smapper.popI());
 311.698                      break;
 311.699                  case opc_land:
 311.700 -                    emit(out, "@1 = @1.and64(@2);", smapper.getL(1), smapper.popL());
 311.701 +                    smapper.replace(this, VarType.LONG, "(@1).and64(@2)", smapper.getL(1), smapper.popL());
 311.702                      break;
 311.703                  case opc_ior:
 311.704 -                    emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI());
 311.705 +                    smapper.replace(this, VarType.INTEGER, "(@1 | @2)", smapper.getI(1), smapper.popI());
 311.706                      break;
 311.707                  case opc_lor:
 311.708 -                    emit(out, "@1 = @1.or64(@2);", smapper.getL(1), smapper.popL());
 311.709 +                    smapper.replace(this, VarType.LONG, "(@1).or64(@2)", smapper.getL(1), smapper.popL());
 311.710                      break;
 311.711                  case opc_ixor:
 311.712 -                    emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI());
 311.713 +                    smapper.replace(this, VarType.INTEGER, "(@1 ^ @2)", smapper.getI(1), smapper.popI());
 311.714                      break;
 311.715                  case opc_lxor:
 311.716 -                    emit(out, "@1 = @1.xor64(@2);", smapper.getL(1), smapper.popL());
 311.717 +                    smapper.replace(this, VarType.LONG, "(@1).xor64(@2)", smapper.getL(1), smapper.popL());
 311.718                      break;
 311.719                  case opc_ineg:
 311.720 -                    emit(out, "@1 = @1.neg32();", smapper.getI(0));
 311.721 +                    smapper.replace(this, VarType.INTEGER, "(@1).neg32()", smapper.getI(0));
 311.722                      break;
 311.723                  case opc_lneg:
 311.724 -                    emit(out, "@1 = @1.neg64();", smapper.getL(0));
 311.725 +                    smapper.replace(this, VarType.LONG, "(@1).neg64()", smapper.getL(0));
 311.726                      break;
 311.727                  case opc_fneg:
 311.728 -                    emit(out, "@1 = -@1;", smapper.getF(0));
 311.729 +                    smapper.replace(this, VarType.FLOAT, "(-@1)", smapper.getF(0));
 311.730                      break;
 311.731                  case opc_dneg:
 311.732 -                    emit(out, "@1 = -@1;", smapper.getD(0));
 311.733 +                    smapper.replace(this, VarType.DOUBLE, "(-@1)", smapper.getD(0));
 311.734                      break;
 311.735                  case opc_ishl:
 311.736 -                    emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI());
 311.737 +                    smapper.replace(this, VarType.INTEGER, "(@1 << @2)", smapper.getI(1), smapper.popI());
 311.738                      break;
 311.739                  case opc_lshl:
 311.740 -                    emit(out, "@1 = @1.shl64(@2);", smapper.getL(1), smapper.popI());
 311.741 +                    smapper.replace(this, VarType.LONG, "(@1).shl64(@2)", smapper.getL(1), smapper.popI());
 311.742                      break;
 311.743                  case opc_ishr:
 311.744 -                    emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI());
 311.745 +                    smapper.replace(this, VarType.INTEGER, "(@1 >> @2)", smapper.getI(1), smapper.popI());
 311.746                      break;
 311.747                  case opc_lshr:
 311.748 -                    emit(out, "@1 = @1.shr64(@2);", smapper.getL(1), smapper.popI());
 311.749 +                    smapper.replace(this, VarType.LONG, "(@1).shr64(@2)", smapper.getL(1), smapper.popI());
 311.750                      break;
 311.751                  case opc_iushr:
 311.752 -                    emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI());
 311.753 +                    smapper.replace(this, VarType.INTEGER, "(@1 >>> @2)", smapper.getI(1), smapper.popI());
 311.754                      break;
 311.755                  case opc_lushr:
 311.756 -                    emit(out, "@1 = @1.ushr64(@2);", smapper.getL(1), smapper.popI());
 311.757 +                    smapper.replace(this, VarType.LONG, "(@1).ushr64(@2)", smapper.getL(1), smapper.popI());
 311.758                      break;
 311.759                  case opc_iinc: {
 311.760                      ++i;
 311.761 @@ -699,132 +757,132 @@
 311.762                                              : byteCodes[i];
 311.763                      wide = false;
 311.764                      if (incrBy == 1) {
 311.765 -                        emit(out, "@1++;", lmapper.getI(varIndx));
 311.766 +                        emit(smapper, this, "@1++;", lmapper.getI(varIndx));
 311.767                      } else {
 311.768 -                        emit(out, "@1 += @2;",
 311.769 +                        emit(smapper, this, "@1 += @2;",
 311.770                               lmapper.getI(varIndx),
 311.771                               Integer.toString(incrBy));
 311.772                      }
 311.773                      break;
 311.774                  }
 311.775                  case opc_return:
 311.776 -                    emit(out, "return;");
 311.777 +                    emit(smapper, this, "return;");
 311.778                      break;
 311.779                  case opc_ireturn:
 311.780 -                    emit(out, "return @1;", smapper.popI());
 311.781 +                    emit(smapper, this, "return @1;", smapper.popI());
 311.782                      break;
 311.783                  case opc_lreturn:
 311.784 -                    emit(out, "return @1;", smapper.popL());
 311.785 +                    emit(smapper, this, "return @1;", smapper.popL());
 311.786                      break;
 311.787                  case opc_freturn:
 311.788 -                    emit(out, "return @1;", smapper.popF());
 311.789 +                    emit(smapper, this, "return @1;", smapper.popF());
 311.790                      break;
 311.791                  case opc_dreturn:
 311.792 -                    emit(out, "return @1;", smapper.popD());
 311.793 +                    emit(smapper, this, "return @1;", smapper.popD());
 311.794                      break;
 311.795                  case opc_areturn:
 311.796 -                    emit(out, "return @1;", smapper.popA());
 311.797 +                    emit(smapper, this, "return @1;", smapper.popA());
 311.798                      break;
 311.799                  case opc_i2l:
 311.800 -                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL());
 311.801 +                    smapper.replace(this, VarType.LONG, "@1", smapper.getI(0));
 311.802                      break;
 311.803                  case opc_i2f:
 311.804 -                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF());
 311.805 +                    smapper.replace(this, VarType.FLOAT, "@1", smapper.getI(0));
 311.806                      break;
 311.807                  case opc_i2d:
 311.808 -                    emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD());
 311.809 +                    smapper.replace(this, VarType.DOUBLE, "@1", smapper.getI(0));
 311.810                      break;
 311.811                  case opc_l2i:
 311.812 -                    emit(out, "var @2 = @1.toInt32();", smapper.popL(), smapper.pushI());
 311.813 +                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()", smapper.getL(0));
 311.814                      break;
 311.815                      // max int check?
 311.816                  case opc_l2f:
 311.817 -                    emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushF());
 311.818 +                    smapper.replace(this, VarType.FLOAT, "(@1).toFP()", smapper.getL(0));
 311.819                      break;
 311.820                  case opc_l2d:
 311.821 -                    emit(out, "var @2 = @1.toFP();", smapper.popL(), smapper.pushD());
 311.822 +                    smapper.replace(this, VarType.DOUBLE, "(@1).toFP()", smapper.getL(0));
 311.823                      break;
 311.824                  case opc_f2d:
 311.825 -                    emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD());
 311.826 +                    smapper.replace(this, VarType.DOUBLE, "@1",
 311.827 +                         smapper.getF(0));
 311.828                      break;
 311.829                  case opc_d2f:
 311.830 -                    emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF());
 311.831 +                    smapper.replace(this, VarType.FLOAT, "@1",
 311.832 +                         smapper.getD(0));
 311.833                      break;
 311.834                  case opc_f2i:
 311.835 -                    emit(out, "var @2 = @1.toInt32();",
 311.836 -                         smapper.popF(), smapper.pushI());
 311.837 +                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
 311.838 +                         smapper.getF(0));
 311.839                      break;
 311.840                  case opc_f2l:
 311.841 -                    emit(out, "var @2 = @1.toLong();",
 311.842 -                         smapper.popF(), smapper.pushL());
 311.843 +                    smapper.replace(this, VarType.LONG, "(@1).toLong()",
 311.844 +                         smapper.getF(0));
 311.845                      break;
 311.846                  case opc_d2i:
 311.847 -                    emit(out, "var @2 = @1.toInt32();",
 311.848 -                         smapper.popD(), smapper.pushI());
 311.849 +                    smapper.replace(this, VarType.INTEGER, "(@1).toInt32()",
 311.850 +                         smapper.getD(0));
 311.851                      break;
 311.852                  case opc_d2l:
 311.853 -                    emit(out, "var @2 = @1.toLong();",
 311.854 -                         smapper.popD(), smapper.pushL());
 311.855 +                    smapper.replace(this, VarType.LONG, "(@1).toLong()", smapper.getD(0));
 311.856                      break;
 311.857                  case opc_i2b:
 311.858 -                    emit(out, "var @1 = @1.toInt8();", smapper.getI(0));
 311.859 +                    smapper.replace(this, VarType.INTEGER, "(@1).toInt8()", smapper.getI(0));
 311.860                      break;
 311.861                  case opc_i2c:
 311.862 -                    out.append("{ /* number conversion */ }");
 311.863                      break;
 311.864                  case opc_i2s:
 311.865 -                    emit(out, "var @1 = @1.toInt16();", smapper.getI(0));
 311.866 +                    smapper.replace(this, VarType.INTEGER, "(@1).toInt16()", smapper.getI(0));
 311.867                      break;
 311.868                  case opc_aconst_null:
 311.869 -                    emit(out, "var @1 = null;", smapper.pushA());
 311.870 +                    smapper.assign(this, VarType.REFERENCE, "null");
 311.871                      break;
 311.872                  case opc_iconst_m1:
 311.873 -                    emit(out, "var @1 = -1;", smapper.pushI());
 311.874 +                    smapper.assign(this, VarType.INTEGER, "-1");
 311.875                      break;
 311.876                  case opc_iconst_0:
 311.877 -                    emit(out, "var @1 = 0;", smapper.pushI());
 311.878 +                    smapper.assign(this, VarType.INTEGER, "0");
 311.879                      break;
 311.880                  case opc_dconst_0:
 311.881 -                    emit(out, "var @1 = 0;", smapper.pushD());
 311.882 +                    smapper.assign(this, VarType.DOUBLE, "0");
 311.883                      break;
 311.884                  case opc_lconst_0:
 311.885 -                    emit(out, "var @1 = 0;", smapper.pushL());
 311.886 +                    smapper.assign(this, VarType.LONG, "0");
 311.887                      break;
 311.888                  case opc_fconst_0:
 311.889 -                    emit(out, "var @1 = 0;", smapper.pushF());
 311.890 +                    smapper.assign(this, VarType.FLOAT, "0");
 311.891                      break;
 311.892                  case opc_iconst_1:
 311.893 -                    emit(out, "var @1 = 1;", smapper.pushI());
 311.894 +                    smapper.assign(this, VarType.INTEGER, "1");
 311.895                      break;
 311.896                  case opc_lconst_1:
 311.897 -                    emit(out, "var @1 = 1;", smapper.pushL());
 311.898 +                    smapper.assign(this, VarType.LONG, "1");
 311.899                      break;
 311.900                  case opc_fconst_1:
 311.901 -                    emit(out, "var @1 = 1;", smapper.pushF());
 311.902 +                    smapper.assign(this, VarType.FLOAT, "1");
 311.903                      break;
 311.904                  case opc_dconst_1:
 311.905 -                    emit(out, "var @1 = 1;", smapper.pushD());
 311.906 +                    smapper.assign(this, VarType.DOUBLE, "1");
 311.907                      break;
 311.908                  case opc_iconst_2:
 311.909 -                    emit(out, "var @1 = 2;", smapper.pushI());
 311.910 +                    smapper.assign(this, VarType.INTEGER, "2");
 311.911                      break;
 311.912                  case opc_fconst_2:
 311.913 -                    emit(out, "var @1 = 2;", smapper.pushF());
 311.914 +                    smapper.assign(this, VarType.FLOAT, "2");
 311.915                      break;
 311.916                  case opc_iconst_3:
 311.917 -                    emit(out, "var @1 = 3;", smapper.pushI());
 311.918 +                    smapper.assign(this, VarType.INTEGER, "3");
 311.919                      break;
 311.920                  case opc_iconst_4:
 311.921 -                    emit(out, "var @1 = 4;", smapper.pushI());
 311.922 +                    smapper.assign(this, VarType.INTEGER, "4");
 311.923                      break;
 311.924                  case opc_iconst_5:
 311.925 -                    emit(out, "var @1 = 5;", smapper.pushI());
 311.926 +                    smapper.assign(this, VarType.INTEGER, "5");
 311.927                      break;
 311.928                  case opc_ldc: {
 311.929                      int indx = readUByte(byteCodes, ++i);
 311.930                      String v = encodeConstant(indx);
 311.931                      int type = VarType.fromConstantType(jc.getTag(indx));
 311.932 -                    emit(out, "var @1 = @2;", smapper.pushT(type), v);
 311.933 +                    smapper.assign(this, type, v);
 311.934                      break;
 311.935                  }
 311.936                  case opc_ldc_w:
 311.937 @@ -837,118 +895,122 @@
 311.938                          final Long lv = new Long(v);
 311.939                          final int low = (int)(lv.longValue() & 0xFFFFFFFF);
 311.940                          final int hi = (int)(lv.longValue() >> 32);
 311.941 -                        emit(out, "var @1 = 0x@3.next32(0x@2);", smapper.pushL(), 
 311.942 -                                Integer.toHexString(low), Integer.toHexString(hi));
 311.943 +                        if (hi == 0) {
 311.944 +                            smapper.assign(this, VarType.LONG, "0x" + Integer.toHexString(low));
 311.945 +                        } else {
 311.946 +                            smapper.assign(this, VarType.LONG,
 311.947 +                                "0x" + Integer.toHexString(hi) + ".next32(0x" + 
 311.948 +                                    Integer.toHexString(low) + ")"
 311.949 +                            );
 311.950 +                        }
 311.951                      } else {
 311.952 -                        emit(out, "var @1 = @2;", smapper.pushT(type), v);
 311.953 +                        smapper.assign(this, type, v);
 311.954                      }
 311.955                      break;
 311.956                  }
 311.957                  case opc_lcmp:
 311.958 -                    emit(out, "var @3 = @2.compare64(@1);",
 311.959 -                         smapper.popL(), smapper.popL(), smapper.pushI());
 311.960 +                    smapper.replace(this, VarType.INTEGER, "(@2).compare64(@1)", smapper.popL(), smapper.getL(0));
 311.961                      break;
 311.962                  case opc_fcmpl:
 311.963                  case opc_fcmpg:
 311.964 -                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
 311.965 -                         smapper.popF(), smapper.popF(), smapper.pushI());
 311.966 +                    smapper.replace(this, VarType.INTEGER, "(@2).compare(@1)", smapper.popF(), smapper.getF(0));
 311.967                      break;
 311.968                  case opc_dcmpl:
 311.969                  case opc_dcmpg:
 311.970 -                    emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);",
 311.971 -                         smapper.popD(), smapper.popD(), smapper.pushI());
 311.972 +                    smapper.replace(this, VarType.INTEGER, "(@2).compare(@1)", smapper.popD(), smapper.getD(0));
 311.973                      break;
 311.974                  case opc_if_acmpeq:
 311.975 -                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
 311.976 +                    i = generateIf(smapper, byteCodes, i, smapper.popA(), smapper.popA(),
 311.977                                     "===", topMostLabel);
 311.978                      break;
 311.979                  case opc_if_acmpne:
 311.980 -                    i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
 311.981 +                    i = generateIf(smapper, byteCodes, i, smapper.popA(), smapper.popA(),
 311.982                                     "!==", topMostLabel);
 311.983                      break;
 311.984                  case opc_if_icmpeq:
 311.985 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 311.986 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
 311.987                                     "==", topMostLabel);
 311.988                      break;
 311.989                  case opc_ifeq: {
 311.990                      int indx = i + readShortArg(byteCodes, i);
 311.991 -                    emitIf(out, "if (@1 == 0) ",
 311.992 +                    emitIf(smapper, this, "if ((@1) == 0) ",
 311.993                           smapper.popI(), i, indx, topMostLabel);
 311.994                      i += 2;
 311.995                      break;
 311.996                  }
 311.997                  case opc_ifne: {
 311.998                      int indx = i + readShortArg(byteCodes, i);
 311.999 -                    emitIf(out, "if (@1 != 0) ",
311.1000 +                    emitIf(smapper, this, "if ((@1) != 0) ",
311.1001                           smapper.popI(), i, indx, topMostLabel);
311.1002                      i += 2;
311.1003                      break;
311.1004                  }
311.1005                  case opc_iflt: {
311.1006                      int indx = i + readShortArg(byteCodes, i);
311.1007 -                    emitIf(out, "if (@1 < 0) ",
311.1008 +                    emitIf(smapper, this, "if ((@1) < 0) ",
311.1009                           smapper.popI(), i, indx, topMostLabel);
311.1010                      i += 2;
311.1011                      break;
311.1012                  }
311.1013                  case opc_ifle: {
311.1014                      int indx = i + readShortArg(byteCodes, i);
311.1015 -                    emitIf(out, "if (@1 <= 0) ",
311.1016 +                    emitIf(smapper, this, "if ((@1) <= 0) ",
311.1017                           smapper.popI(), i, indx, topMostLabel);
311.1018                      i += 2;
311.1019                      break;
311.1020                  }
311.1021                  case opc_ifgt: {
311.1022                      int indx = i + readShortArg(byteCodes, i);
311.1023 -                    emitIf(out, "if (@1 > 0) ",
311.1024 +                    emitIf(smapper, this, "if ((@1) > 0) ",
311.1025                           smapper.popI(), i, indx, topMostLabel);
311.1026                      i += 2;
311.1027                      break;
311.1028                  }
311.1029                  case opc_ifge: {
311.1030                      int indx = i + readShortArg(byteCodes, i);
311.1031 -                    emitIf(out, "if (@1 >= 0) ",
311.1032 +                    emitIf(smapper, this, "if ((@1) >= 0) ",
311.1033                           smapper.popI(), i, indx, topMostLabel);
311.1034                      i += 2;
311.1035                      break;
311.1036                  }
311.1037                  case opc_ifnonnull: {
311.1038                      int indx = i + readShortArg(byteCodes, i);
311.1039 -                    emitIf(out, "if (@1 !== null) ",
311.1040 +                    emitIf(smapper, this, "if ((@1) !== null) ",
311.1041                           smapper.popA(), i, indx, topMostLabel);
311.1042                      i += 2;
311.1043                      break;
311.1044                  }
311.1045                  case opc_ifnull: {
311.1046                      int indx = i + readShortArg(byteCodes, i);
311.1047 -                    emitIf(out, "if (@1 === null) ",
311.1048 +                    emitIf(smapper, this, "if ((@1) === null) ",
311.1049                           smapper.popA(), i, indx, topMostLabel);
311.1050                      i += 2;
311.1051                      break;
311.1052                  }
311.1053                  case opc_if_icmpne:
311.1054 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
311.1055 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
311.1056                                     "!=", topMostLabel);
311.1057                      break;
311.1058                  case opc_if_icmplt:
311.1059 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
311.1060 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
311.1061                                     "<", topMostLabel);
311.1062                      break;
311.1063                  case opc_if_icmple:
311.1064 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
311.1065 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
311.1066                                     "<=", topMostLabel);
311.1067                      break;
311.1068                  case opc_if_icmpgt:
311.1069 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
311.1070 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
311.1071                                     ">", topMostLabel);
311.1072                      break;
311.1073                  case opc_if_icmpge:
311.1074 -                    i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
311.1075 +                    i = generateIf(smapper, byteCodes, i, smapper.popI(), smapper.popI(),
311.1076                                     ">=", topMostLabel);
311.1077                      break;
311.1078                  case opc_goto: {
311.1079 +                    smapper.flush(this);
311.1080                      int indx = i + readShortArg(byteCodes, i);
311.1081 -                    goTo(out, i, indx, topMostLabel);
311.1082 +                    goTo(this, i, indx, topMostLabel);
311.1083                      i += 2;
311.1084                      break;
311.1085                  }
311.1086 @@ -976,8 +1038,8 @@
311.1087                  case opc_new: {
311.1088                      int indx = readUShortArg(byteCodes, i);
311.1089                      String ci = jc.getClassName(indx);
311.1090 -                    emit(out, "var @1 = new @2;",
311.1091 -                         smapper.pushA(), accessClass(ci.replace('/', '_')));
311.1092 +                    emit(smapper, this, "var @1 = new @2;",
311.1093 +                         smapper.pushA(), accessClass(mangleClassName(ci)));
311.1094                      addReference(ci);
311.1095                      i += 2;
311.1096                      break;
311.1097 @@ -999,54 +1061,53 @@
311.1098                      break;
311.1099                  }
311.1100                  case opc_arraylength:
311.1101 -                    emit(out, "var @2 = @1.length;",
311.1102 -                         smapper.popA(), smapper.pushI());
311.1103 +                    smapper.replace(this, VarType.INTEGER, "(@1).length", smapper.getA(0));
311.1104                      break;
311.1105                  case opc_lastore:
311.1106 -                    emit(out, "Array.at(@3, @2, @1);",
311.1107 +                    emit(smapper, this, "Array.at(@3, @2, @1);",
311.1108                           smapper.popL(), smapper.popI(), smapper.popA());
311.1109                      break;
311.1110                  case opc_fastore:
311.1111 -                    emit(out, "Array.at(@3, @2, @1);",
311.1112 +                    emit(smapper, this, "Array.at(@3, @2, @1);",
311.1113                           smapper.popF(), smapper.popI(), smapper.popA());
311.1114                      break;
311.1115                  case opc_dastore:
311.1116 -                    emit(out, "Array.at(@3, @2, @1);",
311.1117 +                    emit(smapper, this, "Array.at(@3, @2, @1);",
311.1118                           smapper.popD(), smapper.popI(), smapper.popA());
311.1119                      break;
311.1120                  case opc_aastore:
311.1121 -                    emit(out, "Array.at(@3, @2, @1);",
311.1122 +                    emit(smapper, this, "Array.at(@3, @2, @1);",
311.1123                           smapper.popA(), smapper.popI(), smapper.popA());
311.1124                      break;
311.1125                  case opc_iastore:
311.1126                  case opc_bastore:
311.1127                  case opc_castore:
311.1128                  case opc_sastore:
311.1129 -                    emit(out, "Array.at(@3, @2, @1);",
311.1130 +                    emit(smapper, this, "Array.at(@3, @2, @1);",
311.1131                           smapper.popI(), smapper.popI(), smapper.popA());
311.1132                      break;
311.1133                  case opc_laload:
311.1134 -                    emit(out, "var @3 = Array.at(@2, @1);",
311.1135 -                         smapper.popI(), smapper.popA(), smapper.pushL());
311.1136 +                    smapper.replace(this, VarType.LONG, "Array.at(@2, @1)",
311.1137 +                         smapper.popI(), smapper.getA(0));
311.1138                      break;
311.1139                  case opc_faload:
311.1140 -                    emit(out, "var @3 = Array.at(@2, @1);",
311.1141 -                         smapper.popI(), smapper.popA(), smapper.pushF());
311.1142 +                    smapper.replace(this, VarType.FLOAT, "Array.at(@2, @1)",
311.1143 +                         smapper.popI(), smapper.getA(0));
311.1144                      break;
311.1145                  case opc_daload:
311.1146 -                    emit(out, "var @3 = Array.at(@2, @1);",
311.1147 -                         smapper.popI(), smapper.popA(), smapper.pushD());
311.1148 +                    smapper.replace(this, VarType.DOUBLE, "Array.at(@2, @1)",
311.1149 +                         smapper.popI(), smapper.getA(0));
311.1150                      break;
311.1151                  case opc_aaload:
311.1152 -                    emit(out, "var @3 = Array.at(@2, @1);",
311.1153 -                         smapper.popI(), smapper.popA(), smapper.pushA());
311.1154 +                    smapper.replace(this, VarType.REFERENCE, "Array.at(@2, @1)",
311.1155 +                         smapper.popI(), smapper.getA(0));
311.1156                      break;
311.1157                  case opc_iaload:
311.1158                  case opc_baload:
311.1159                  case opc_caload:
311.1160                  case opc_saload:
311.1161 -                    emit(out, "var @3 = Array.at(@2, @1);",
311.1162 -                         smapper.popI(), smapper.popA(), smapper.pushI());
311.1163 +                    smapper.replace(this, VarType.INTEGER, "Array.at(@2, @1)",
311.1164 +                         smapper.popI(), smapper.getA(0));
311.1165                      break;
311.1166                  case opc_pop:
311.1167                  case opc_pop2:
311.1168 @@ -1055,86 +1116,86 @@
311.1169                      break;
311.1170                  case opc_dup: {
311.1171                      final Variable v = smapper.get(0);
311.1172 -                    emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v);
311.1173 +                    emit(smapper, this, "var @1 = @2;", smapper.pushT(v.getType()), v);
311.1174                      break;
311.1175                  }
311.1176                  case opc_dup2: {
311.1177                      final Variable vi1 = smapper.get(0);
311.1178  
311.1179                      if (vi1.isCategory2()) {
311.1180 -                        emit(out, "var @1 = @2;",
311.1181 +                        emit(smapper, this, "var @1 = @2;",
311.1182                               smapper.pushT(vi1.getType()), vi1);
311.1183                      } else {
311.1184                          final Variable vi2 = smapper.get(1);
311.1185 -                        emit(out, "var @1 = @2, @3 = @4;",
311.1186 +                        emit(smapper, this, "var @1 = @2, @3 = @4;",
311.1187                               smapper.pushT(vi2.getType()), vi2,
311.1188                               smapper.pushT(vi1.getType()), vi1);
311.1189                      }
311.1190                      break;
311.1191                  }
311.1192                  case opc_dup_x1: {
311.1193 -                    final Variable vi1 = smapper.pop();
311.1194 -                    final Variable vi2 = smapper.pop();
311.1195 +                    final Variable vi1 = smapper.pop(this);
311.1196 +                    final Variable vi2 = smapper.pop(this);
311.1197                      final Variable vo3 = smapper.pushT(vi1.getType());
311.1198                      final Variable vo2 = smapper.pushT(vi2.getType());
311.1199                      final Variable vo1 = smapper.pushT(vi1.getType());
311.1200  
311.1201 -                    emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
311.1202 +                    emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
311.1203                           vo1, vi1, vo2, vi2, vo3, vo1);
311.1204                      break;
311.1205                  }
311.1206                  case opc_dup2_x1: {
311.1207 -                    final Variable vi1 = smapper.pop();
311.1208 -                    final Variable vi2 = smapper.pop();
311.1209 +                    final Variable vi1 = smapper.pop(this);
311.1210 +                    final Variable vi2 = smapper.pop(this);
311.1211  
311.1212                      if (vi1.isCategory2()) {
311.1213                          final Variable vo3 = smapper.pushT(vi1.getType());
311.1214                          final Variable vo2 = smapper.pushT(vi2.getType());
311.1215                          final Variable vo1 = smapper.pushT(vi1.getType());
311.1216  
311.1217 -                        emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
311.1218 +                        emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
311.1219                               vo1, vi1, vo2, vi2, vo3, vo1);
311.1220                      } else {
311.1221 -                        final Variable vi3 = smapper.pop();
311.1222 +                        final Variable vi3 = smapper.pop(this);
311.1223                          final Variable vo5 = smapper.pushT(vi2.getType());
311.1224                          final Variable vo4 = smapper.pushT(vi1.getType());
311.1225                          final Variable vo3 = smapper.pushT(vi3.getType());
311.1226                          final Variable vo2 = smapper.pushT(vi2.getType());
311.1227                          final Variable vo1 = smapper.pushT(vi1.getType());
311.1228  
311.1229 -                        emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
311.1230 +                        emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6,",
311.1231                               vo1, vi1, vo2, vi2, vo3, vi3);
311.1232 -                        emit(out, " @1 = @2, @3 = @4;",
311.1233 +                        emit(smapper, this, " @1 = @2, @3 = @4;",
311.1234                               vo4, vo1, vo5, vo2);
311.1235                      }
311.1236                      break;
311.1237                  }
311.1238                  case opc_dup_x2: {
311.1239 -                    final Variable vi1 = smapper.pop();
311.1240 -                    final Variable vi2 = smapper.pop();
311.1241 +                    final Variable vi1 = smapper.pop(this);
311.1242 +                    final Variable vi2 = smapper.pop(this);
311.1243  
311.1244                      if (vi2.isCategory2()) {
311.1245                          final Variable vo3 = smapper.pushT(vi1.getType());
311.1246                          final Variable vo2 = smapper.pushT(vi2.getType());
311.1247                          final Variable vo1 = smapper.pushT(vi1.getType());
311.1248  
311.1249 -                        emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
311.1250 +                        emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
311.1251                               vo1, vi1, vo2, vi2, vo3, vo1);
311.1252                      } else {
311.1253 -                        final Variable vi3 = smapper.pop();
311.1254 +                        final Variable vi3 = smapper.pop(this);
311.1255                          final Variable vo4 = smapper.pushT(vi1.getType());
311.1256                          final Variable vo3 = smapper.pushT(vi3.getType());
311.1257                          final Variable vo2 = smapper.pushT(vi2.getType());
311.1258                          final Variable vo1 = smapper.pushT(vi1.getType());
311.1259  
311.1260 -                        emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
311.1261 +                        emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
311.1262                               vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
311.1263                      }
311.1264                      break;
311.1265                  }
311.1266                  case opc_dup2_x2: {
311.1267 -                    final Variable vi1 = smapper.pop();
311.1268 -                    final Variable vi2 = smapper.pop();
311.1269 +                    final Variable vi1 = smapper.pop(this);
311.1270 +                    final Variable vi2 = smapper.pop(this);
311.1271  
311.1272                      if (vi1.isCategory2()) {
311.1273                          if (vi2.isCategory2()) {
311.1274 @@ -1142,20 +1203,20 @@
311.1275                              final Variable vo2 = smapper.pushT(vi2.getType());
311.1276                              final Variable vo1 = smapper.pushT(vi1.getType());
311.1277  
311.1278 -                            emit(out, "var @1 = @2, @3 = @4, @5 = @6;",
311.1279 +                            emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6;",
311.1280                                   vo1, vi1, vo2, vi2, vo3, vo1);
311.1281                          } else {
311.1282 -                            final Variable vi3 = smapper.pop();
311.1283 +                            final Variable vi3 = smapper.pop(this);
311.1284                              final Variable vo4 = smapper.pushT(vi1.getType());
311.1285                              final Variable vo3 = smapper.pushT(vi3.getType());
311.1286                              final Variable vo2 = smapper.pushT(vi2.getType());
311.1287                              final Variable vo1 = smapper.pushT(vi1.getType());
311.1288  
311.1289 -                            emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
311.1290 +                            emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;",
311.1291                                   vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1);
311.1292                          }
311.1293                      } else {
311.1294 -                        final Variable vi3 = smapper.pop();
311.1295 +                        final Variable vi3 = smapper.pop(this);
311.1296  
311.1297                          if (vi3.isCategory2()) {
311.1298                              final Variable vo5 = smapper.pushT(vi2.getType());
311.1299 @@ -1164,12 +1225,12 @@
311.1300                              final Variable vo2 = smapper.pushT(vi2.getType());
311.1301                              final Variable vo1 = smapper.pushT(vi1.getType());
311.1302  
311.1303 -                            emit(out, "var @1 = @2, @3 = @4, @5 = @6,",
311.1304 +                            emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6,",
311.1305                                   vo1, vi1, vo2, vi2, vo3, vi3);
311.1306 -                            emit(out, " @1 = @2, @3 = @4;",
311.1307 +                            emit(smapper, this, " @1 = @2, @3 = @4;",
311.1308                                   vo4, vo1, vo5, vo2);
311.1309                          } else {
311.1310 -                            final Variable vi4 = smapper.pop();
311.1311 +                            final Variable vi4 = smapper.pop(this);
311.1312                              final Variable vo6 = smapper.pushT(vi2.getType());
311.1313                              final Variable vo5 = smapper.pushT(vi1.getType());
311.1314                              final Variable vo4 = smapper.pushT(vi4.getType());
311.1315 @@ -1177,9 +1238,9 @@
311.1316                              final Variable vo2 = smapper.pushT(vi2.getType());
311.1317                              final Variable vo1 = smapper.pushT(vi1.getType());
311.1318                              
311.1319 -                            emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
311.1320 +                            emit(smapper, this, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8,",
311.1321                                   vo1, vi1, vo2, vi2, vo3, vi3, vo4, vi4);
311.1322 -                            emit(out, " @1 = @2, @3 = @4;",
311.1323 +                            emit(smapper, this, " @1 = @2, @3 = @4;",
311.1324                                   vo5, vo1, vo6, vo2);
311.1325                          }
311.1326                      }
311.1327 @@ -1192,7 +1253,7 @@
311.1328                      if (vi1.getType() == vi2.getType()) {
311.1329                          final Variable tmp = smapper.pushT(vi1.getType());
311.1330  
311.1331 -                        emit(out, "var @1 = @2, @2 = @3, @3 = @1;",
311.1332 +                        emit(smapper, this, "var @1 = @2, @2 = @3, @3 = @1;",
311.1333                               tmp, vi1, vi2);
311.1334                          smapper.pop(1);
311.1335                      } else {
311.1336 @@ -1203,26 +1264,26 @@
311.1337                      break;
311.1338                  }
311.1339                  case opc_bipush:
311.1340 -                    emit(out, "var @1 = @2;",
311.1341 -                         smapper.pushI(), Integer.toString(byteCodes[++i]));
311.1342 +                    smapper.assign(this, VarType.INTEGER, 
311.1343 +                        "(" + Integer.toString(byteCodes[++i]) + ")");
311.1344                      break;
311.1345                  case opc_sipush:
311.1346 -                    emit(out, "var @1 = @2;",
311.1347 -                         smapper.pushI(),
311.1348 -                         Integer.toString(readShortArg(byteCodes, i)));
311.1349 +                    smapper.assign(this, VarType.INTEGER, 
311.1350 +                        "(" + Integer.toString(readShortArg(byteCodes, i)) + ")"
311.1351 +                    );
311.1352                      i += 2;
311.1353                      break;
311.1354                  case opc_getfield: {
311.1355                      int indx = readUShortArg(byteCodes, i);
311.1356                      String[] fi = jc.getFieldInfoName(indx);
311.1357                      final int type = VarType.fromFieldType(fi[2].charAt(0));
311.1358 -                    final String mangleClass = mangleSig(fi[0]);
311.1359 +                    final String mangleClass = mangleClassName(fi[0]);
311.1360                      final String mangleClassAccess = accessClass(mangleClass);
311.1361 -                    emit(out, "var @2 = @3.call(@1);",
311.1362 -                         smapper.popA(),
311.1363 -                         smapper.pushT(type),
311.1364 +                    smapper.replace(this, type, "@2.call(@1)",
311.1365 +                         smapper.getA(0),
311.1366                           accessField(mangleClassAccess + "(false)",
311.1367 -                                     "_" + fi[1], fi));
311.1368 +                                     "_" + fi[1], fi)
311.1369 +                    );
311.1370                      i += 2;
311.1371                      break;
311.1372                  }
311.1373 @@ -1230,9 +1291,9 @@
311.1374                      int indx = readUShortArg(byteCodes, i);
311.1375                      String[] fi = jc.getFieldInfoName(indx);
311.1376                      final int type = VarType.fromFieldType(fi[2].charAt(0));
311.1377 -                    final String mangleClass = mangleSig(fi[0]);
311.1378 +                    final String mangleClass = mangleClassName(fi[0]);
311.1379                      final String mangleClassAccess = accessClass(mangleClass);
311.1380 -                    emit(out, "@3.call(@2, @1);",
311.1381 +                    emit(smapper, this, "@3.call(@2, @1);",
311.1382                           smapper.popT(type),
311.1383                           smapper.popA(),
311.1384                           accessField(mangleClassAccess + "(false)",
311.1385 @@ -1244,11 +1305,8 @@
311.1386                      int indx = readUShortArg(byteCodes, i);
311.1387                      String[] fi = jc.getFieldInfoName(indx);
311.1388                      final int type = VarType.fromFieldType(fi[2].charAt(0));
311.1389 -                    emit(out, "var @1 = @2();",
311.1390 -                         smapper.pushT(type),
311.1391 -                         accessField(accessClass(fi[0].replace('/', '_'))
311.1392 -                                         + "(false)",
311.1393 -                                     "_" + fi[1], fi));
311.1394 +                    String ac = accessClass(mangleClassName(fi[0]));
311.1395 +                    smapper.assign(this, type, ac + "(false)._" + fi[1] + "()");
311.1396                      i += 2;
311.1397                      addReference(fi[0]);
311.1398                      break;
311.1399 @@ -1257,10 +1315,8 @@
311.1400                      int indx = readUShortArg(byteCodes, i);
311.1401                      String[] fi = jc.getFieldInfoName(indx);
311.1402                      final int type = VarType.fromFieldType(fi[2].charAt(0));
311.1403 -                    emit(out, "@1(@2);",
311.1404 -                         accessField(accessClass(fi[0].replace('/', '_'))
311.1405 -                                         + "(false)",
311.1406 -                                     "_" + fi[1], fi),
311.1407 +                    emit(smapper, this, "@1(false)._@2(@3);",
311.1408 +                         accessClass(mangleClassName(fi[0])), fi[1],
311.1409                           smapper.popT(type));
311.1410                      i += 2;
311.1411                      addReference(fi[0]);
311.1412 @@ -1279,22 +1335,22 @@
311.1413                      break;
311.1414                  }
311.1415                  case opc_athrow: {
311.1416 -                    final Variable v = smapper.popA();
311.1417 +                    final CharSequence v = smapper.popA();
311.1418                      smapper.clear();
311.1419  
311.1420 -                    emit(out, "{ var @1 = @2; throw @2; }",
311.1421 +                    emit(smapper, this, "{ var @1 = @2; throw @2; }",
311.1422                           smapper.pushA(), v);
311.1423                      break;
311.1424                  }
311.1425  
311.1426                  case opc_monitorenter: {
311.1427 -                    out.append("/* monitor enter */");
311.1428 +                    debug("/* monitor enter */");
311.1429                      smapper.popA();
311.1430                      break;
311.1431                  }
311.1432  
311.1433                  case opc_monitorexit: {
311.1434 -                    out.append("/* monitor exit */");
311.1435 +                    debug("/* monitor exit */");
311.1436                      smapper.popA();
311.1437                      break;
311.1438                  }
311.1439 @@ -1305,31 +1361,39 @@
311.1440  
311.1441                  default: {
311.1442                      wide = false;
311.1443 -                    emit(out, "throw 'unknown bytecode @1';",
311.1444 +                    emit(smapper, this, "throw 'unknown bytecode @1';",
311.1445                           Integer.toString(c));
311.1446                  }
311.1447              }
311.1448              if (debug(" //")) {
311.1449                  generateByteCodeComment(prev, i, byteCodes);
311.1450              }
311.1451 -            out.append("\n");            
311.1452 +            if (outChanged) {
311.1453 +                append("\n");
311.1454 +            }
311.1455          }
311.1456          if (previousTrap != null) {
311.1457              generateCatch(previousTrap, byteCodes.length, topMostLabel);
311.1458          }
311.1459 -        out.append("\n    }\n");
311.1460 +        if (didBranches) {
311.1461 +            append("\n    }\n");
311.1462 +        }
311.1463          while (openBraces-- > 0) {
311.1464 -            out.append('}');
311.1465 +            append('}');
311.1466          }
311.1467 -        out.append("\n};");
311.1468 +        append("\n};");
311.1469      }
311.1470  
311.1471 -    private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
311.1472 +    private int generateIf(StackMapper mapper, byte[] byteCodes, 
311.1473 +        int i, final CharSequence v2, final CharSequence v1, 
311.1474 +        final String test, int topMostLabel
311.1475 +    ) throws IOException {
311.1476 +        mapper.flush(this);
311.1477          int indx = i + readShortArg(byteCodes, i);
311.1478 -        out.append("if (").append(v1)
311.1479 -           .append(' ').append(test).append(' ')
311.1480 -           .append(v2).append(") ");
311.1481 -        goTo(out, i, indx, topMostLabel);
311.1482 +        append("if ((").append(v1)
311.1483 +           .append(") ").append(test).append(" (")
311.1484 +           .append(v2).append(")) ");
311.1485 +        goTo(this, i, indx, topMostLabel);
311.1486          return i + 2;
311.1487      }
311.1488      
311.1489 @@ -1442,8 +1506,20 @@
311.1490          return mangleSig(sig, 0, sig.length());
311.1491      }
311.1492      
311.1493 +    private static String mangleMethodName(String name) {
311.1494 +        StringBuilder sb = new StringBuilder(name.length() * 2);
311.1495 +        int last = name.length();
311.1496 +        for (int i = 0; i < last; i++) {
311.1497 +            final char ch = name.charAt(i);
311.1498 +            switch (ch) {
311.1499 +                case '_': sb.append("_1"); break;
311.1500 +                default: sb.append(ch); break;
311.1501 +            }
311.1502 +        }
311.1503 +        return sb.toString();
311.1504 +    }
311.1505      private static String mangleSig(String txt, int first, int last) {
311.1506 -        StringBuilder sb = new StringBuilder();
311.1507 +        StringBuilder sb = new StringBuilder((last - first) * 2);
311.1508          for (int i = first; i < last; i++) {
311.1509              final char ch = txt.charAt(i);
311.1510              switch (ch) {
311.1511 @@ -1456,6 +1532,10 @@
311.1512          }
311.1513          return sb.toString();
311.1514      }
311.1515 +    
311.1516 +    private static String mangleClassName(String name) {
311.1517 +        return mangleSig(name);
311.1518 +    }
311.1519  
311.1520      private static String findMethodName(MethodData m, StringBuilder cnt) {
311.1521          StringBuilder name = new StringBuilder();
311.1522 @@ -1464,7 +1544,7 @@
311.1523          } else if ("<clinit>".equals(m.getName())) { // NOI18N
311.1524              name.append("class"); // NOI18N
311.1525          } else {
311.1526 -            name.append(m.getName());
311.1527 +            name.append(mangleMethodName(m.getName()));
311.1528          } 
311.1529          
311.1530          countArgs(m.getInternalSig(), new char[1], name, cnt);
311.1531 @@ -1478,7 +1558,7 @@
311.1532          if ("<init>".equals(nm)) { // NOI18N
311.1533              name.append("cons"); // NOI18N
311.1534          } else {
311.1535 -            name.append(nm);
311.1536 +            name.append(mangleMethodName(nm));
311.1537          }
311.1538          countArgs(descr, returnType, name, cnt);
311.1539          return name.toString();
311.1540 @@ -1493,14 +1573,14 @@
311.1541          String mn = findMethodName(mi, cnt, returnType);
311.1542  
311.1543          final int numArguments = isStatic ? cnt.length() : cnt.length() + 1;
311.1544 -        final Variable[] vars = new Variable[numArguments];
311.1545 +        final CharSequence[] vars = new CharSequence[numArguments];
311.1546  
311.1547          for (int j = numArguments - 1; j >= 0; --j) {
311.1548 -            vars[j] = mapper.pop();
311.1549 +            vars[j] = mapper.popValue();
311.1550          }
311.1551  
311.1552          if (returnType[0] != 'V') {
311.1553 -            out.append("var ")
311.1554 +            append("var ")
311.1555                 .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
311.1556                 .append(" = ");
311.1557          }
311.1558 @@ -1510,20 +1590,20 @@
311.1559          if (mn.startsWith("cons_")) {
311.1560              object += ".constructor";
311.1561          }
311.1562 -        out.append(accessStaticMethod(object, mn, mi));
311.1563 +        append(accessStaticMethod(object, mn, mi));
311.1564          if (isStatic) {
311.1565 -            out.append('(');
311.1566 +            append('(');
311.1567          } else {
311.1568 -            out.append(".call(");
311.1569 +            append(".call(");
311.1570          }
311.1571          if (numArguments > 0) {
311.1572 -            out.append(vars[0]);
311.1573 +            append(vars[0]);
311.1574              for (int j = 1; j < numArguments; ++j) {
311.1575 -                out.append(", ");
311.1576 -                out.append(vars[j]);
311.1577 +                append(", ");
311.1578 +                append(vars[j]);
311.1579              }
311.1580          }
311.1581 -        out.append(");");
311.1582 +        append(");");
311.1583          i += 2;
311.1584          addReference(in);
311.1585          return i;
311.1586 @@ -1537,27 +1617,27 @@
311.1587          String mn = findMethodName(mi, cnt, returnType);
311.1588  
311.1589          final int numArguments = cnt.length() + 1;
311.1590 -        final Variable[] vars = new Variable[numArguments];
311.1591 +        final CharSequence[] vars = new CharSequence[numArguments];
311.1592  
311.1593          for (int j = numArguments - 1; j >= 0; --j) {
311.1594 -            vars[j] = mapper.pop();
311.1595 +            vars[j] = mapper.popValue();
311.1596          }
311.1597  
311.1598          if (returnType[0] != 'V') {
311.1599 -            out.append("var ")
311.1600 +            append("var ")
311.1601                 .append(mapper.pushT(VarType.fromFieldType(returnType[0])))
311.1602                 .append(" = ");
311.1603          }
311.1604  
311.1605 -        out.append(accessVirtualMethod(vars[0].toString(), mn, mi));
311.1606 -        out.append('(');
311.1607 +        append(accessVirtualMethod(vars[0].toString(), mn, mi));
311.1608 +        append('(');
311.1609          String sep = "";
311.1610          for (int j = 1; j < numArguments; ++j) {
311.1611 -            out.append(sep);
311.1612 -            out.append(vars[j]);
311.1613 +            append(sep);
311.1614 +            append(vars[j]);
311.1615              sep = ", ";
311.1616          }
311.1617 -        out.append(");");
311.1618 +        append(");");
311.1619          i += 2;
311.1620          return i;
311.1621      }
311.1622 @@ -1587,10 +1667,10 @@
311.1623          String s = jc.stringValue(entryIndex, classRef);
311.1624          if (classRef[0] != null) {
311.1625              if (classRef[0].startsWith("[")) {
311.1626 -                s = accessClass("java_lang_Class") + "(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('" + classRef[0] + "');";
311.1627 +                s = accessClass("java_lang_Class") + "(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('" + classRef[0] + "')";
311.1628              } else {
311.1629                  addReference(classRef[0]);
311.1630 -                s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
311.1631 +                s = accessClass(mangleClassName(s)) + "(false).constructor.$class";
311.1632              }
311.1633          }
311.1634          return s;
311.1635 @@ -1602,6 +1682,7 @@
311.1636              return null;
311.1637          }
311.1638          final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
311.1639 +        final String htmlType = "Lnet/java/html/js/JavaScriptBody;";
311.1640          class P extends AnnotationParser {
311.1641              public P() {
311.1642                  super(false, true);
311.1643 @@ -1610,6 +1691,8 @@
311.1644              int cnt;
311.1645              String[] args = new String[30];
311.1646              String body;
311.1647 +            boolean javacall;
311.1648 +            boolean html4j;
311.1649              
311.1650              @Override
311.1651              protected void visitAttr(String type, String attr, String at, String value) {
311.1652 @@ -1622,6 +1705,18 @@
311.1653                          throw new IllegalArgumentException(attr);
311.1654                      }
311.1655                  }
311.1656 +                if (type.equals(htmlType)) {
311.1657 +                    html4j = true;
311.1658 +                    if ("body".equals(attr)) {
311.1659 +                        body = value;
311.1660 +                    } else if ("args".equals(attr)) {
311.1661 +                        args[cnt++] = value;
311.1662 +                    } else if ("javacall".equals(attr)) {
311.1663 +                        javacall = "1".equals(value);
311.1664 +                    } else {
311.1665 +                        throw new IllegalArgumentException(attr);
311.1666 +                    }
311.1667 +                }
311.1668              }
311.1669          }
311.1670          P p = new P();
311.1671 @@ -1631,23 +1726,153 @@
311.1672          }
311.1673          StringBuilder cnt = new StringBuilder();
311.1674          final String mn = findMethodName(m, cnt);
311.1675 -        out.append(destObject).append(".").append(mn);
311.1676 -        out.append(" = function(");
311.1677 +        append(destObject).append(".").append(mn);
311.1678 +        append(" = function(");
311.1679          String space = "";
311.1680          int index = 0;
311.1681 +        StringBuilder toValue = new StringBuilder();
311.1682          for (int i = 0; i < cnt.length(); i++) {
311.1683 -            out.append(space);
311.1684 -            space = outputArg(out, p.args, index);
311.1685 +            append(space);
311.1686 +            space = outputArg(this, p.args, index);
311.1687 +            if (p.html4j && space.length() > 0) {
311.1688 +                toValue.append("\n  ").append(p.args[index]).append(" = vm.org_apidesign_bck2brwsr_emul_lang_System(false).toJS(").
311.1689 +                    append(p.args[index]).append(");");
311.1690 +            }
311.1691              index++;
311.1692          }
311.1693 -        out.append(") {").append("\n");
311.1694 -        out.append(p.body);
311.1695 -        out.append("\n}\n");
311.1696 +        append(") {").append("\n");
311.1697 +        append(toValue.toString());
311.1698 +        if (p.javacall) {
311.1699 +            int lastSlash = jc.getClassName().lastIndexOf('/');
311.1700 +            final String pkg = jc.getClassName().substring(0, lastSlash);
311.1701 +            append(mangleCallbacks(pkg, p.body));
311.1702 +            requireReference(pkg + "/$JsCallbacks$");
311.1703 +        } else {
311.1704 +            append(p.body);
311.1705 +        }
311.1706 +        append("\n}\n");
311.1707          return mn;
311.1708      }
311.1709 +    
311.1710 +    private static CharSequence mangleCallbacks(String pkgName, String body) {
311.1711 +        StringBuilder sb = new StringBuilder();
311.1712 +        int pos = 0;
311.1713 +        for (;;) {
311.1714 +            int next = body.indexOf(".@", pos);
311.1715 +            if (next == -1) {
311.1716 +                sb.append(body.substring(pos));
311.1717 +                body = sb.toString();
311.1718 +                break;
311.1719 +            }
311.1720 +            int ident = next;
311.1721 +            while (ident > 0) {
311.1722 +                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
311.1723 +                    ident++;
311.1724 +                    break;
311.1725 +                }
311.1726 +            }
311.1727 +            String refId = body.substring(ident, next);
311.1728 +
311.1729 +            sb.append(body.substring(pos, ident));
311.1730 +
311.1731 +            int sigBeg = body.indexOf('(', next);
311.1732 +            int sigEnd = body.indexOf(')', sigBeg);
311.1733 +            int colon4 = body.indexOf("::", next);
311.1734 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
311.1735 +                throw new IllegalStateException("Malformed body " + body);
311.1736 +            }
311.1737 +            String fqn = body.substring(next + 2, colon4);
311.1738 +            String method = body.substring(colon4 + 2, sigBeg);
311.1739 +            String params = body.substring(sigBeg, sigEnd + 1);
311.1740 +
311.1741 +            int paramBeg = body.indexOf('(', sigEnd + 1);
311.1742 +            
311.1743 +            sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
311.1744 +            sb.append(mangleJsCallbacks(fqn, method, params, false));
311.1745 +            sb.append("(").append(refId);
311.1746 +            if (body.charAt(paramBeg + 1) != ')') {
311.1747 +                sb.append(",");
311.1748 +            }
311.1749 +            pos = paramBeg + 1;
311.1750 +        }
311.1751 +        sb = null;
311.1752 +        pos = 0;
311.1753 +        for (;;) {
311.1754 +            int next = body.indexOf("@", pos);
311.1755 +            if (next == -1) {
311.1756 +                if (sb == null) {
311.1757 +                    return body;
311.1758 +                }
311.1759 +                sb.append(body.substring(pos));
311.1760 +                return sb;
311.1761 +            }
311.1762 +            if (sb == null) {
311.1763 +                sb = new StringBuilder();
311.1764 +            }
311.1765 +
311.1766 +            sb.append(body.substring(pos, next));
311.1767 +
311.1768 +            int sigBeg = body.indexOf('(', next);
311.1769 +            int sigEnd = body.indexOf(')', sigBeg);
311.1770 +            int colon4 = body.indexOf("::", next);
311.1771 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
311.1772 +                throw new IllegalStateException("Malformed body " + body);
311.1773 +            }
311.1774 +            String fqn = body.substring(next + 1, colon4);
311.1775 +            String method = body.substring(colon4 + 2, sigBeg);
311.1776 +            String params = body.substring(sigBeg, sigEnd + 1);
311.1777 +
311.1778 +            int paramBeg = body.indexOf('(', sigEnd + 1);
311.1779 +            
311.1780 +            sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
311.1781 +            sb.append(mangleJsCallbacks(fqn, method, params, true));
311.1782 +            sb.append("(");
311.1783 +            pos = paramBeg + 1;
311.1784 +        }
311.1785 +    }
311.1786 +
311.1787 +    static String mangleJsCallbacks(String fqn, String method, String params, boolean isStatic) {
311.1788 +        if (params.startsWith("(")) {
311.1789 +            params = params.substring(1);
311.1790 +        }
311.1791 +        if (params.endsWith(")")) {
311.1792 +            params = params.substring(0, params.length() - 1);
311.1793 +        }
311.1794 +        StringBuilder sb = new StringBuilder();
311.1795 +        final String fqnu = fqn.replace('.', '_');
311.1796 +        final String rfqn = mangleClassName(fqnu);
311.1797 +        final String rm = mangleMethodName(method);
311.1798 +        final String srp;
311.1799 +        {
311.1800 +            StringBuilder pb = new StringBuilder();
311.1801 +            int len = params.length();
311.1802 +            int indx = 0;
311.1803 +            while (indx < len) {
311.1804 +                char ch = params.charAt(indx);
311.1805 +                if (ch == '[' || ch == 'L') {
311.1806 +                    pb.append("Ljava/lang/Object;");
311.1807 +                    indx = params.indexOf(';', indx) + 1;
311.1808 +                } else {
311.1809 +                    pb.append(ch);
311.1810 +                    indx++;
311.1811 +                }
311.1812 +            }
311.1813 +            srp = mangleSig(pb.toString());
311.1814 +        }
311.1815 +        final String rp = mangleSig(params);
311.1816 +        final String mrp = mangleMethodName(rp);
311.1817 +        sb.append(rfqn).append("$").append(rm).
311.1818 +            append('$').append(mrp).append("__Ljava_lang_Object_2");
311.1819 +        if (!isStatic) {
311.1820 +            sb.append('L').append(fqnu).append("_2");
311.1821 +        }
311.1822 +        sb.append(srp);
311.1823 +        return sb.toString();
311.1824 +    }
311.1825 +
311.1826      private static String className(ClassData jc) {
311.1827          //return jc.getName().getInternalName().replace('/', '_');
311.1828 -        return jc.getClassName().replace('/', '_');
311.1829 +        return mangleClassName(jc.getClassName());
311.1830      }
311.1831      
311.1832      private static String[] findAnnotation(
311.1833 @@ -1697,7 +1922,7 @@
311.1834          return " = null;";
311.1835      }
311.1836  
311.1837 -    private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
311.1838 +    private void generateAnno(ClassData cd, byte[] data) throws IOException {
311.1839          AnnotationParser ap = new AnnotationParser(true, false) {
311.1840              int[] cnt = new int[32];
311.1841              int depth;
311.1842 @@ -1708,39 +1933,39 @@
311.1843                  requireReference(slashType);
311.1844                  
311.1845                  if (cnt[depth]++ > 0) {
311.1846 -                    out.append(",");
311.1847 +                    append(",");
311.1848                  }
311.1849                  if (top) {
311.1850 -                    out.append('"').append(attrType).append("\" : ");
311.1851 +                    append('"').append(attrType).append("\" : ");
311.1852                  }
311.1853 -                out.append("{\n");
311.1854 +                append("{\n");
311.1855                  cnt[++depth] = 0;
311.1856              }
311.1857  
311.1858              @Override
311.1859              protected void visitAnnotationEnd(String type, boolean top) throws IOException {
311.1860 -                out.append("\n}\n");
311.1861 +                append("\n}\n");
311.1862                  depth--;
311.1863              }
311.1864  
311.1865              @Override
311.1866              protected void visitValueStart(String attrName, char type) throws IOException {
311.1867                  if (cnt[depth]++ > 0) {
311.1868 -                    out.append(",\n");
311.1869 +                    append(",\n");
311.1870                  }
311.1871                  cnt[++depth] = 0;
311.1872                  if (attrName != null) {
311.1873 -                    out.append(attrName).append(" : ");
311.1874 +                    append(attrName).append(" : ");
311.1875                  }
311.1876                  if (type == '[') {
311.1877 -                    out.append("[");
311.1878 +                    append("[");
311.1879                  }
311.1880              }
311.1881  
311.1882              @Override
311.1883              protected void visitValueEnd(String attrName, char type) throws IOException {
311.1884                  if (type == '[') {
311.1885 -                    out.append("]");
311.1886 +                    append("]");
311.1887                  }
311.1888                  depth--;
311.1889              }
311.1890 @@ -1751,7 +1976,7 @@
311.1891                  if (attr == null && value == null) {
311.1892                      return;
311.1893                  }
311.1894 -                out.append(value);
311.1895 +                append(value);
311.1896              }
311.1897  
311.1898              @Override
311.1899 @@ -1760,8 +1985,8 @@
311.1900                  final String slashType = attrType.substring(1, attrType.length() - 1);
311.1901                  requireReference(slashType);
311.1902                  
311.1903 -                out.append(accessClass(slashType.replace('/', '_')))
311.1904 -                   .append("(false).constructor.").append(value);
311.1905 +                append(accessClass(mangleClassName(slashType)))
311.1906 +                   .append("(false).constructor.fld_").append(value);
311.1907              }
311.1908          };
311.1909          ap.parse(data, cd);
311.1910 @@ -1779,7 +2004,21 @@
311.1911          return ",";
311.1912      }
311.1913  
311.1914 -    private static void emit(final Appendable out,
311.1915 +    final void emitNoFlush(
311.1916 +        StackMapper sm, 
311.1917 +        final String format, final CharSequence... params
311.1918 +    ) throws IOException {
311.1919 +        emitImpl(this, format, params);
311.1920 +    }
311.1921 +    static final void emit(
311.1922 +        StackMapper sm, 
311.1923 +        final Appendable out, 
311.1924 +        final String format, final CharSequence... params
311.1925 +    ) throws IOException {
311.1926 +        sm.flush(out);
311.1927 +        emitImpl(out, format, params);
311.1928 +    }
311.1929 +    static void emitImpl(final Appendable out,
311.1930                               final String format,
311.1931                               final CharSequence... params) throws IOException {
311.1932          final int length = format.length();
311.1933 @@ -1805,7 +2044,7 @@
311.1934      }
311.1935  
311.1936      private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException {
311.1937 -        out.append("} catch (e) {\n");
311.1938 +        append("} catch (e) {\n");
311.1939          int finallyPC = -1;
311.1940          for (TrapData e : traps) {
311.1941              if (e == null) {
311.1942 @@ -1814,22 +2053,22 @@
311.1943              if (e.catch_cpx != 0) { //not finally
311.1944                  final String classInternalName = jc.getClassName(e.catch_cpx);
311.1945                  addReference(classInternalName);
311.1946 -                out.append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
311.1947 -                out.append("if (e['$instOf_" + classInternalName.replace('/', '_') + "']) {");
311.1948 -                out.append("var stA0 = e;");
311.1949 -                goTo(out, current, e.handler_pc, topMostLabel);
311.1950 -                out.append("}\n");
311.1951 +                append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
311.1952 +                append("if (e['$instOf_" + classInternalName.replace('/', '_') + "']) {");
311.1953 +                append("var stA0 = e;");
311.1954 +                goTo(this, current, e.handler_pc, topMostLabel);
311.1955 +                append("}\n");
311.1956              } else {
311.1957                  finallyPC = e.handler_pc;
311.1958              }
311.1959          }
311.1960          if (finallyPC == -1) {
311.1961 -            out.append("throw e;");
311.1962 +            append("throw e;");
311.1963          } else {
311.1964 -            out.append("var stA0 = e;");
311.1965 -            goTo(out, current, finallyPC, topMostLabel);
311.1966 +            append("var stA0 = e;");
311.1967 +            goTo(this, current, finallyPC, topMostLabel);
311.1968          }
311.1969 -        out.append("\n}");
311.1970 +        append("\n}");
311.1971      }
311.1972  
311.1973      private static void goTo(Appendable out, int current, int to, int canBack) throws IOException {
311.1974 @@ -1845,10 +2084,13 @@
311.1975      }
311.1976  
311.1977      private static void emitIf(
311.1978 -        Appendable out, String pattern, Variable param, 
311.1979 +        StackMapper sm, 
311.1980 +        Appendable out, String pattern, 
311.1981 +        CharSequence param, 
311.1982          int current, int to, int canBack
311.1983      ) throws IOException {
311.1984 -        emit(out, pattern, param);
311.1985 +        sm.flush(out);
311.1986 +        emitImpl(out, pattern, param);
311.1987          goTo(out, current, to, canBack);
311.1988      }
311.1989  
311.1990 @@ -1865,7 +2107,8 @@
311.1991              case 11: jvmType = "[J"; break;
311.1992              default: throw new IllegalStateException("Array type: " + atype);
311.1993          }
311.1994 -        emit(out, "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);",
311.1995 +        emit(smapper, this, 
311.1996 +            "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](true, '@3', @1);",
311.1997               smapper.popI(), smapper.pushA(), jvmType);
311.1998      }
311.1999  
311.2000 @@ -1876,7 +2119,8 @@
311.2001          } else {
311.2002              typeName = "[L" + typeName + ";";
311.2003          }
311.2004 -        emit(out, "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);",
311.2005 +        emit(smapper, this,
311.2006 +            "var @2 = Array.prototype['newArray__Ljava_lang_Object_2ZLjava_lang_String_2I'](false, '@3', @1);",
311.2007               smapper.popI(), smapper.pushA(), typeName);
311.2008      }
311.2009  
311.2010 @@ -1892,7 +2136,8 @@
311.2011              dims.insert(1, smapper.popI());
311.2012          }
311.2013          dims.append(']');
311.2014 -        emit(out, "var @2 = Array.prototype['multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II']('@3', @1, 0);",
311.2015 +        emit(smapper, this, 
311.2016 +            "var @2 = Array.prototype['multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II']('@3', @1, 0);",
311.2017               dims.toString(), smapper.pushA(), typeName);
311.2018          return i;
311.2019      }
311.2020 @@ -1905,16 +2150,18 @@
311.2021          table += 4;
311.2022          int high = readInt4(byteCodes, table);
311.2023          table += 4;
311.2024 -        out.append("switch (").append(smapper.popI()).append(") {\n");
311.2025 +        final CharSequence swVar = smapper.popValue();
311.2026 +        smapper.flush(this);
311.2027 +        append("switch (").append(swVar).append(") {\n");
311.2028          while (low <= high) {
311.2029              int offset = i + readInt4(byteCodes, table);
311.2030              table += 4;
311.2031 -            out.append("  case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n');
311.2032 +            append("  case " + low).append(":"); goTo(this, i, offset, topMostLabel); append('\n');
311.2033              low++;
311.2034          }
311.2035 -        out.append("  default: ");
311.2036 -        goTo(out, i, dflt, topMostLabel);
311.2037 -        out.append("\n}");
311.2038 +        append("  default: ");
311.2039 +        goTo(this, i, dflt, topMostLabel);
311.2040 +        append("\n}");
311.2041          i = table - 1;
311.2042          return i;
311.2043      }
311.2044 @@ -1925,17 +2172,19 @@
311.2045          table += 4;
311.2046          int n = readInt4(byteCodes, table);
311.2047          table += 4;
311.2048 -        out.append("switch (").append(smapper.popI()).append(") {\n");
311.2049 +        final CharSequence swVar = smapper.popValue();
311.2050 +        smapper.flush(this);
311.2051 +        append("switch (").append(swVar).append(") {\n");
311.2052          while (n-- > 0) {
311.2053              int cnstnt = readInt4(byteCodes, table);
311.2054              table += 4;
311.2055              int offset = i + readInt4(byteCodes, table);
311.2056              table += 4;
311.2057 -            out.append("  case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n');
311.2058 +            append("  case " + cnstnt).append(": "); goTo(this, i, offset, topMostLabel); append('\n');
311.2059          }
311.2060 -        out.append("  default: ");
311.2061 -        goTo(out, i, dflt, topMostLabel);
311.2062 -        out.append("\n}");
311.2063 +        append("  default: ");
311.2064 +        goTo(this, i, dflt, topMostLabel);
311.2065 +        append("\n}");
311.2066          i = table - 1;
311.2067          return i;
311.2068      }
311.2069 @@ -1943,11 +2192,13 @@
311.2070      private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
311.2071          final String type = jc.getClassName(indx);
311.2072          if (!type.startsWith("[")) {
311.2073 -            emit(out, "var @2 = @1 != null && @1['$instOf_@3'] ? 1 : 0;",
311.2074 +            emit(smapper, this, 
311.2075 +                    "var @2 = @1 != null && @1['$instOf_@3'] ? 1 : 0;",
311.2076                   smapper.popA(), smapper.pushI(),
311.2077                   type.replace('/', '_'));
311.2078          } else {
311.2079 -            emit(out, "var @2 = vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@3')['isInstance__ZLjava_lang_Object_2'](@1);",
311.2080 +            emit(smapper, this, 
311.2081 +                "var @2 = vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@3')['isInstance__ZLjava_lang_Object_2'](@1);",
311.2082                  smapper.popA(), smapper.pushI(),
311.2083                  type
311.2084              );
311.2085 @@ -1957,21 +2208,22 @@
311.2086      private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
311.2087          final String type = jc.getClassName(indx);
311.2088          if (!type.startsWith("[")) {
311.2089 -            emit(out,
311.2090 +            emitNoFlush(smapper, 
311.2091                   "if (@1 !== null && !@1['$instOf_@2']) throw vm.java_lang_ClassCastException(true);",
311.2092 -                 smapper.getA(0), type.replace('/', '_'));
311.2093 +                 smapper.getT(0, VarType.REFERENCE, false), type.replace('/', '_'));
311.2094          } else {
311.2095 -            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);",
311.2096 -                 smapper.getA(0), type
311.2097 +            emitNoFlush(smapper, 
311.2098 +                "vm.java_lang_Class(false)['forName__Ljava_lang_Class_2Ljava_lang_String_2']('@2')['cast__Ljava_lang_Object_2Ljava_lang_Object_2'](@1);",
311.2099 +                 smapper.getT(0, VarType.REFERENCE, false), type
311.2100              );
311.2101          }
311.2102      }
311.2103  
311.2104      private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
311.2105          for (int j = prev; j <= i; j++) {
311.2106 -            out.append(" ");
311.2107 +            append(" ");
311.2108              final int cc = readUByte(byteCodes, j);
311.2109 -            out.append(Integer.toString(cc));
311.2110 +            append(Integer.toString(cc));
311.2111          }
311.2112      }
311.2113  }
   312.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java	Tue Apr 29 15:25:58 2014 +0200
   312.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java	Wed Apr 30 15:04:10 2014 +0200
   312.3 @@ -28,9 +28,11 @@
   312.4   */
   312.5  final class LdrRsrcs implements Bck2Brwsr.Resources {
   312.6      private final ClassLoader loader;
   312.7 +    private final boolean skipRtJar;
   312.8  
   312.9 -    LdrRsrcs(ClassLoader loader) {
  312.10 +    LdrRsrcs(ClassLoader loader, boolean skipRtJar) {
  312.11          this.loader = loader;
  312.12 +        this.skipRtJar = skipRtJar;
  312.13      }
  312.14  
  312.15      @Override
  312.16 @@ -40,6 +42,12 @@
  312.17          while (en.hasMoreElements()) {
  312.18              u = en.nextElement();
  312.19          }
  312.20 -        return (u != null) ? u.openStream() : null;
  312.21 +        if (u == null) {
  312.22 +            throw new IOException("Can't find " + name);
  312.23 +        }
  312.24 +        if (skipRtJar && u.toExternalForm().contains("lib/rt.jar!")) {
  312.25 +            return null;
  312.26 +        }
  312.27 +        return u.openStream();
  312.28      }
  312.29  }
   313.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Tue Apr 29 15:25:58 2014 +0200
   313.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Wed Apr 30 15:04:10 2014 +0200
   313.3 @@ -108,7 +108,7 @@
   313.4              Bck2Brwsr.newCompiler().library(createExtension).
   313.5                  obfuscation(obfLevel).
   313.6                  addRootClasses(classes.toArray()).
   313.7 -                resources(new LdrRsrcs(mainClassLoader)).
   313.8 +                resources(new LdrRsrcs(Main.class.getClassLoader(), true)).
   313.9                  generate(w);
  313.10          }
  313.11      }
   314.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java	Tue Apr 29 15:25:58 2014 +0200
   314.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java	Wed Apr 30 15:04:10 2014 +0200
   314.3 @@ -17,24 +17,21 @@
   314.4   */
   314.5  package org.apidesign.vm4brwsr;
   314.6  
   314.7 +import java.io.IOException;
   314.8  import org.apidesign.vm4brwsr.ByteCodeParser.TypeArray;
   314.9  
  314.10  final class StackMapper {
  314.11      private final TypeArray stackTypeIndexPairs;
  314.12 -    private int[] typeCounters;
  314.13 -    private int[] typeMaxCounters;
  314.14 +    private final StringArray stackValues;
  314.15  
  314.16      public StackMapper() {
  314.17          stackTypeIndexPairs = new TypeArray();
  314.18 -        typeCounters = new int[VarType.LAST + 1];
  314.19 -        typeMaxCounters = new int[VarType.LAST + 1];
  314.20 +        stackValues = new StringArray();
  314.21      }
  314.22  
  314.23      public void clear() {
  314.24 -        for (int type = 0; type <= VarType.LAST; ++type) {
  314.25 -            typeCounters[type] = 0;
  314.26 -        }
  314.27          stackTypeIndexPairs.clear();
  314.28 +        stackValues.clear();
  314.29      }
  314.30  
  314.31      public void syncWithFrameStack(final TypeArray frameStack) {
  314.32 @@ -70,33 +67,66 @@
  314.33          return getVariable(pushTypeImpl(type));
  314.34      }
  314.35  
  314.36 -    public Variable popI() {
  314.37 +    void assign(Appendable out, int varType, CharSequence s) throws IOException {
  314.38 +        pushTypeAndValue(varType, s);
  314.39 +    }
  314.40 +
  314.41 +    void replace(Appendable out, int varType, String format, CharSequence... arr) 
  314.42 +    throws IOException {
  314.43 +        StringBuilder sb = new StringBuilder();
  314.44 +        ByteCodeToJavaScript.emitImpl(sb, format, arr);
  314.45 +        String[] values = stackValues.toArray();
  314.46 +        final int last = stackTypeIndexPairs.getSize() - 1;
  314.47 +        values[last] = sb.toString();
  314.48 +        final int value = (last << 8) | (varType & 0xff);
  314.49 +        stackTypeIndexPairs.set(last, value);
  314.50 +    }
  314.51 +    
  314.52 +    void flush(Appendable out) throws IOException {
  314.53 +        int count = stackTypeIndexPairs.getSize();
  314.54 +        for (int i = 0; i < count; i++) {
  314.55 +            String val = stackValues.getAndClear(i, true);
  314.56 +            if (val == null) {
  314.57 +                continue;
  314.58 +            }
  314.59 +            CharSequence var = getVariable(stackTypeIndexPairs.get(i));
  314.60 +            ByteCodeToJavaScript.emitImpl(out, "var @1 = @2;", var, val);
  314.61 +        }
  314.62 +    }
  314.63 +    
  314.64 +    public CharSequence popI() {
  314.65          return popT(VarType.INTEGER);
  314.66      }
  314.67  
  314.68 -    public Variable popL() {
  314.69 +    public CharSequence popL() {
  314.70          return popT(VarType.LONG);
  314.71      }
  314.72  
  314.73 -    public Variable popF() {
  314.74 +    public CharSequence popF() {
  314.75          return popT(VarType.FLOAT);
  314.76      }
  314.77  
  314.78 -    public Variable popD() {
  314.79 +    public CharSequence popD() {
  314.80          return popT(VarType.DOUBLE);
  314.81      }
  314.82  
  314.83 -    public Variable popA() {
  314.84 +    public CharSequence popA() {
  314.85          return popT(VarType.REFERENCE);
  314.86      }
  314.87  
  314.88 -    public Variable popT(final int type) {
  314.89 -        final Variable variable = getT(0, type);
  314.90 +    public CharSequence popT(final int type) {
  314.91 +        final CharSequence variable = getT(0, type);
  314.92          popImpl(1);
  314.93          return variable;
  314.94      }
  314.95  
  314.96 -    public Variable pop() {
  314.97 +    public CharSequence popValue() {
  314.98 +        final CharSequence variable = getT(0, -1);
  314.99 +        popImpl(1);
 314.100 +        return variable;
 314.101 +    }
 314.102 +    public Variable pop(Appendable out) throws IOException {
 314.103 +        flush(out);
 314.104          final Variable variable = get(0);
 314.105          popImpl(1);
 314.106          return variable;
 314.107 @@ -110,37 +140,44 @@
 314.108          popImpl(count);
 314.109      }
 314.110  
 314.111 -    public Variable getI(final int indexFromTop) {
 314.112 +    public CharSequence getI(final int indexFromTop) {
 314.113          return getT(indexFromTop, VarType.INTEGER);
 314.114      }
 314.115  
 314.116 -    public Variable getL(final int indexFromTop) {
 314.117 +    public CharSequence getL(final int indexFromTop) {
 314.118          return getT(indexFromTop, VarType.LONG);
 314.119      }
 314.120  
 314.121 -    public Variable getF(final int indexFromTop) {
 314.122 +    public CharSequence getF(final int indexFromTop) {
 314.123          return getT(indexFromTop, VarType.FLOAT);
 314.124      }
 314.125  
 314.126 -    public Variable getD(final int indexFromTop) {
 314.127 +    public CharSequence getD(final int indexFromTop) {
 314.128          return getT(indexFromTop, VarType.DOUBLE);
 314.129      }
 314.130  
 314.131 -    public Variable getA(final int indexFromTop) {
 314.132 +    public CharSequence getA(final int indexFromTop) {
 314.133          return getT(indexFromTop, VarType.REFERENCE);
 314.134      }
 314.135  
 314.136 -    public Variable getT(final int indexFromTop, final int type) {
 314.137 +    public CharSequence getT(final int indexFromTop, final int type) {
 314.138 +        return getT(indexFromTop, type, true);
 314.139 +    }
 314.140 +    public CharSequence getT(final int indexFromTop, final int type, boolean clear) {
 314.141          final int stackSize = stackTypeIndexPairs.getSize();
 314.142          if (indexFromTop >= stackSize) {
 314.143              throw new IllegalStateException("Stack underflow");
 314.144          }
 314.145          final int stackValue =
 314.146                  stackTypeIndexPairs.get(stackSize - indexFromTop - 1);
 314.147 -        if ((stackValue & 0xff) != type) {
 314.148 +        if (type != -1 && (stackValue & 0xff) != type) {
 314.149              throw new IllegalStateException("Type mismatch");
 314.150          }
 314.151 -
 314.152 +        String value =
 314.153 +            stackValues.getAndClear(stackSize - indexFromTop - 1, clear);
 314.154 +        if (value != null) {
 314.155 +            return value;
 314.156 +        }
 314.157          return getVariable(stackValue);
 314.158      }
 314.159  
 314.160 @@ -156,35 +193,36 @@
 314.161      }
 314.162  
 314.163      private int pushTypeImpl(final int type) {
 314.164 -        final int count = typeCounters[type];
 314.165 +        final int count = stackTypeIndexPairs.getSize();
 314.166          final int value = (count << 8) | (type & 0xff);
 314.167 -        incCounter(type);
 314.168          stackTypeIndexPairs.add(value);
 314.169 +        
 314.170 +        addStackValue(count, null);
 314.171 +        return value;
 314.172 +    }
 314.173  
 314.174 -        return value;
 314.175 +    private void pushTypeAndValue(final int type, CharSequence v) {
 314.176 +        final int count = stackTypeIndexPairs.getSize();
 314.177 +        final int value = (count << 8) | (type & 0xff);
 314.178 +        stackTypeIndexPairs.add(value);
 314.179 +        final String val = v.toString();
 314.180 +        addStackValue(count, val);
 314.181 +    }
 314.182 +
 314.183 +    private void addStackValue(int at, final String val) {
 314.184 +        final String[] arr = stackValues.toArray();
 314.185 +        if (arr.length > at) {
 314.186 +            arr[at] = val;
 314.187 +        } else {
 314.188 +            stackValues.add(val);
 314.189 +        }
 314.190      }
 314.191  
 314.192      private void popImpl(final int count) {
 314.193          final int stackSize = stackTypeIndexPairs.getSize();
 314.194 -        for (int i = stackSize - count; i < stackSize; ++i) {
 314.195 -            final int value = stackTypeIndexPairs.get(i);
 314.196 -            decCounter(value & 0xff);
 314.197 -        }
 314.198 -
 314.199          stackTypeIndexPairs.setSize(stackSize - count);
 314.200      }
 314.201  
 314.202 -    private void incCounter(final int type) {
 314.203 -        final int newValue = ++typeCounters[type];
 314.204 -        if (typeMaxCounters[type] < newValue) {
 314.205 -            typeMaxCounters[type] = newValue;
 314.206 -        }
 314.207 -    }
 314.208 -
 314.209 -    private void decCounter(final int type) {
 314.210 -        --typeCounters[type];
 314.211 -    }
 314.212 -
 314.213      public Variable getVariable(final int typeAndIndex) {
 314.214          final int type = typeAndIndex & 0xff;
 314.215          final int index = typeAndIndex >> 8;
   315.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java	Tue Apr 29 15:25:58 2014 +0200
   315.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java	Wed Apr 30 15:04:10 2014 +0200
   315.3 @@ -105,11 +105,23 @@
   315.4      }
   315.5  
   315.6      int indexOf(String ic) {
   315.7 -        for (int i = 0; i < arr.length; i++) {
   315.8 +        if (arr != null) for (int i = 0; i < arr.length; i++) {
   315.9              if (ic.equals(arr[i])) {
  315.10                  return i;
  315.11              }
  315.12          }
  315.13          return -1;
  315.14      }
  315.15 +
  315.16 +    String getAndClear(int count, boolean clear) {
  315.17 +        String s = arr[count];
  315.18 +        if (clear) {
  315.19 +            arr[count] = null;
  315.20 +        }
  315.21 +        return s;
  315.22 +    }
  315.23 +
  315.24 +    void clear() {
  315.25 +        arr = null;
  315.26 +    }
  315.27  }
   316.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Tue Apr 29 15:25:58 2014 +0200
   316.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed Apr 30 15:04:10 2014 +0200
   316.3 @@ -85,11 +85,11 @@
   316.4  
   316.5      private void doCompile(StringArray names, StringArray asBinary) throws IOException {
   316.6          generatePrologue();
   316.7 -        out.append(
   316.8 +        append(
   316.9                  "\n  var invoker = {};");
  316.10          generateBody(names);
  316.11          for (String invokerMethod: invokerMethods.toArray()) {
  316.12 -            out.append("\n  invoker." + invokerMethod + " = function(target) {"
  316.13 +            append("\n  invoker." + invokerMethod + " = function(target) {"
  316.14                  + "\n    return function() {"
  316.15                  + "\n      return target['" + invokerMethod + "'].apply(target, arguments);"
  316.16                  + "\n    };"
  316.17 @@ -98,19 +98,19 @@
  316.18          }
  316.19          
  316.20          for (String r : asBinary.toArray()) {
  316.21 -            out.append("\n  ").append(getExportsObject()).append(".registerResource('");
  316.22 -            out.append(r).append("', '");
  316.23 +            append("\n  ").append(getExportsObject()).append(".registerResource('");
  316.24 +            append(r).append("', '");
  316.25              InputStream is = this.resources.get(r);
  316.26              byte[] arr = new byte[is.available()];
  316.27              int len = is.read(arr);
  316.28              if (len != arr.length) {
  316.29                  throw new IOException("Not read as much as expected for " + r + " expected: " + arr.length + " was: " + len);
  316.30              }
  316.31 -            out.append(btoa(arr));
  316.32 -            out.append("');");
  316.33 +            append(btoa(arr));
  316.34 +            append("');");
  316.35          }
  316.36          
  316.37 -        out.append("\n");
  316.38 +        append("\n");
  316.39          generateEpilogue();
  316.40      }
  316.41  
  316.42 @@ -131,7 +131,7 @@
  316.43      protected final void declaredClass(ClassData classData, String mangledName)
  316.44              throws IOException {
  316.45          if (exportedSymbols.isExported(classData)) {
  316.46 -            out.append("\n").append(getExportsObject()).append("['")
  316.47 +            append("\n").append(getExportsObject()).append("['")
  316.48                                                 .append(mangledName)
  316.49                                                 .append("'] = ")
  316.50                              .append(accessClass(mangledName))
  316.51 @@ -167,7 +167,7 @@
  316.52  
  316.53      private void exportMember(String destObject, String memberName)
  316.54              throws IOException {
  316.55 -        out.append("\n").append(destObject).append("['")
  316.56 +        append("\n").append(destObject).append("['")
  316.57                                             .append(memberName)
  316.58                                             .append("'] = ")
  316.59                          .append(destObject).append(".").append(memberName)
  316.60 @@ -177,11 +177,15 @@
  316.61      private void generateBody(StringArray names) throws IOException {
  316.62          StringArray processed = new StringArray();
  316.63          StringArray initCode = new StringArray();
  316.64 +        StringArray skipClass = new StringArray();
  316.65          for (String baseClass : names.toArray()) {
  316.66              references.add(baseClass);
  316.67              for (;;) {
  316.68                  String name = null;
  316.69                  for (String n : references.toArray()) {
  316.70 +                    if (skipClass.contains(n)) {
  316.71 +                        continue;
  316.72 +                    }
  316.73                      if (processed.contains(n)) {
  316.74                          continue;
  316.75                      }
  316.76 @@ -190,28 +194,18 @@
  316.77                  if (name == null) {
  316.78                      break;
  316.79                  }
  316.80 -
  316.81 +                InputStream is = resources.get(name + ".class");
  316.82 +                if (is == null) {
  316.83 +                    lazyReference(this, name);
  316.84 +                    skipClass.add(name);
  316.85 +                    continue;
  316.86 +                }
  316.87                  try {
  316.88                      String ic = generateClass(name);
  316.89                      processed.add(name);
  316.90                      initCode.add(ic == null ? "" : ic);
  316.91                  } catch (RuntimeException ex) {
  316.92 -                    if (out instanceof CharSequence) {
  316.93 -                        CharSequence seq = (CharSequence)out;
  316.94 -                        int lastBlock = seq.length();
  316.95 -                        while (lastBlock-- > 0) {
  316.96 -                            if (seq.charAt(lastBlock) == '{') {
  316.97 -                                break;
  316.98 -                            }
  316.99 -                        }
 316.100 -                        throw new IOException("Error while compiling " + name + "\n"
 316.101 -                            + seq.subSequence(lastBlock + 1, seq.length()), ex
 316.102 -                        );
 316.103 -                    } else {
 316.104 -                        throw new IOException("Error while compiling " + name + "\n"
 316.105 -                            + out, ex
 316.106 -                        );
 316.107 -                    }
 316.108 +                    throw new IOException("Error while compiling " + name + "\n", ex);
 316.109                  }
 316.110              }
 316.111  
 316.112 @@ -223,7 +217,7 @@
 316.113                  if (emul == null) {
 316.114                      throw new IOException("Can't find " + resource);
 316.115                  }
 316.116 -                readResource(emul, out);
 316.117 +                readResource(emul, this);
 316.118              }
 316.119              scripts = new StringArray();
 316.120  
 316.121 @@ -235,12 +229,53 @@
 316.122                  if (indx >= 0) {
 316.123                      final String theCode = initCode.toArray()[indx];
 316.124                      if (!theCode.isEmpty()) {
 316.125 -                        out.append(theCode).append("\n");
 316.126 +                        append(theCode).append("\n");
 316.127                      }
 316.128                      initCode.toArray()[indx] = "";
 316.129                  }
 316.130              }
 316.131          }
 316.132 +/*
 316.133 +        append(
 316.134 +              "  return vm;\n"
 316.135 +            + "  };\n"
 316.136 +            + "  function mangleClass(name) {\n"
 316.137 +            + "    return name.replace__Ljava_lang_String_2Ljava_lang_CharSequence_2Ljava_lang_CharSequence_2(\n"
 316.138 +            + "      '_', '_1').replace__Ljava_lang_String_2CC('.','_');\n"
 316.139 +            + "  };\n"
 316.140 +            + "  global.bck2brwsr = function() {\n"
 316.141 +            + "    var args = Array.prototype.slice.apply(arguments);\n"
 316.142 +            + "    var vm = fillInVMSkeleton({});\n"
 316.143 +            + "    var loader = {};\n"
 316.144 +            + "    loader.vm = vm;\n"
 316.145 +            + "    loader.loadClass = function(name) {\n"
 316.146 +            + "      var attr = mangleClass(name);\n"
 316.147 +            + "      var fn = vm[attr];\n"
 316.148 +            + "      if (fn) return fn(false);\n"
 316.149 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.150 +            + "        load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
 316.151 +            + "    }\n"
 316.152 +            + "    if (vm.loadClass) {\n"
 316.153 +            + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
 316.154 +            + "    }\n"
 316.155 +            + "    vm.loadClass = loader.loadClass;\n"
 316.156 +            + "    vm._reload = function(name, byteCode) {;\n"
 316.157 +            + "      var attr = mangleClass(name);\n"
 316.158 +            + "      delete vm[attr];\n"
 316.159 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.160 +            + "        reload__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2_3B(loader, name, args, byteCode);\n"
 316.161 +            + "    };\n"
 316.162 +            + "    vm.loadBytes = function(name, skip) {\n"
 316.163 +            + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.164 +            + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, name, args, typeof skip == 'number' ? skip : 0);\n"
 316.165 +            + "    }\n"
 316.166 +            + "    vm.java_lang_reflect_Array(false);\n"
 316.167 +            + "    vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.168 +            + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, null, args, 0);\n"
 316.169 +            + "    return loader;\n"
 316.170 +            + "  };\n");
 316.171 +        append("}(this));");
 316.172 +*/
 316.173      }
 316.174  
 316.175      private static void readResource(InputStream emul, Appendable out) throws IOException {
 316.176 @@ -442,12 +477,12 @@
 316.177  
 316.178          @Override
 316.179          protected void generatePrologue() throws IOException {
 316.180 -            out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
 316.181 +            append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
 316.182          }
 316.183  
 316.184          @Override
 316.185          protected void generateEpilogue() throws IOException {
 316.186 -            out.append(
 316.187 +            append(
 316.188                    "  return vm;\n"
 316.189                  + "  };\n"
 316.190                  + "  var extensions = [];\n"
 316.191 @@ -495,22 +530,22 @@
 316.192                  + "      throw 'Cannot initialize the bck2brwsr VM twice!';\n"
 316.193                  + "    }\n"
 316.194                  + "    vm.loadClass = loader.loadClass;\n"
 316.195 -                + "    vm.loadBytes = function(name) {\n"
 316.196 +                + "    vm.loadBytes = function(name, skip) {\n"
 316.197                  + "      if (resources[name]) return resources[name][0];\n"
 316.198                  + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.199 -                + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
 316.200 +                + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, name, args, typeof skip == 'number' ? skip : 0);\n"
 316.201                  + "    }\n"
 316.202                  + "    vm.java_lang_reflect_Array(false);\n"
 316.203                  + "    vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
 316.204 -                + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, null, args);\n"
 316.205 +                + "      loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2I(loader, null, args, 0);\n"
 316.206                  + "    return loader;\n"
 316.207                  + "  };\n");
 316.208 -            out.append(
 316.209 +            append(
 316.210                    "  global.bck2brwsr.registerExtension = function(extension) {\n"
 316.211                  + "    extensions.push(extension);\n"
 316.212                  + "    return null;\n"
 316.213                  + "  };\n");
 316.214 -            out.append("}(this));");
 316.215 +            append("}(this));");
 316.216          }
 316.217  
 316.218          @Override
 316.219 @@ -535,9 +570,9 @@
 316.220  
 316.221          @Override
 316.222          protected void generatePrologue() throws IOException {
 316.223 -            out.append("bck2brwsr.registerExtension(function(exports) {\n"
 316.224 +            append("bck2brwsr.registerExtension(function(exports) {\n"
 316.225                             + "  var vm = {};\n");
 316.226 -            out.append("  function link(n, inst) {\n"
 316.227 +            append("  function link(n, inst) {\n"
 316.228                             + "    var cls = n['replace__Ljava_lang_String_2CC']"
 316.229                                                    + "('/', '_').toString();\n"
 316.230                             + "    var dot = n['replace__Ljava_lang_String_2CC']"
 316.231 @@ -550,13 +585,13 @@
 316.232  
 316.233          @Override
 316.234          protected void generateEpilogue() throws IOException {
 316.235 -            out.append("});");
 316.236 +            append("});");
 316.237          }
 316.238  
 316.239          @Override
 316.240          protected String generateClass(String className) throws IOException {
 316.241              if (isExternalClass(className)) {
 316.242 -                out.append("\n").append(assignClass(
 316.243 +                append("\n").append(assignClass(
 316.244                                              className.replace('/', '_')))
 316.245                     .append("function() {\n  return link('")
 316.246                     .append(className)
 316.247 @@ -579,4 +614,16 @@
 316.248              return !extensionClasses.contains(className);
 316.249          }
 316.250      }
 316.251 +    
 316.252 +    private static void lazyReference(Appendable out, String n) throws IOException {
 316.253 +        String cls = n.replace('/', '_');
 316.254 +        String dot = n.replace('/', '.');
 316.255 +        
 316.256 +        out.append("\nvm.").append(cls).append(" = function() {");
 316.257 +        out.append("\n  var instance = arguments.length == 0 || arguments[0] === true;");
 316.258 +        out.append("\n  delete vm.").append(cls).append(";");
 316.259 +        out.append("\n  var c = vm.loadClass('").append(dot).append("');");
 316.260 +        out.append("\n  return vm.").append(cls).append("(instance);");
 316.261 +        out.append("\n}");
 316.262 +    }
 316.263  }
   317.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Tue Apr 29 15:25:58 2014 +0200
   317.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Wed Apr 30 15:04:10 2014 +0200
   317.3 @@ -20,7 +20,6 @@
   317.4  import java.io.ByteArrayInputStream;
   317.5  import java.io.IOException;
   317.6  import java.io.InputStream;
   317.7 -import java.lang.reflect.Array;
   317.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   317.9  
  317.10  /**
  317.11 @@ -43,27 +42,34 @@
  317.12      throws IOException, ClassNotFoundException {
  317.13          return new VMLazy(loader, arguments).load(name, false);
  317.14      }
  317.15 +
  317.16 +    static Object reload(Object loader, String name, Object[] arguments, byte[] arr) 
  317.17 +    throws IOException, ClassNotFoundException {
  317.18 +        return new VMLazy(loader, arguments).defineClass(arr, name, false);
  317.19 +    }
  317.20      
  317.21 -    static byte[] loadBytes(Object loader, String name, Object[] arguments) throws Exception {
  317.22 -        return Zips.loadFromCp(arguments, name);
  317.23 +    static byte[] loadBytes(Object loader, String name, Object[] arguments, int skip) throws Exception {
  317.24 +        return Zips.loadFromCp(arguments, name, skip);
  317.25      }
  317.26      
  317.27      private Object load(String name, boolean instance)
  317.28      throws IOException, ClassNotFoundException {
  317.29          String res = name.replace('.', '/') + ".class";
  317.30 -        byte[] arr = Zips.loadFromCp(args, res);
  317.31 +        byte[] arr = Zips.loadFromCp(args, res, 0);
  317.32          if (arr == null) {
  317.33              throw new ClassNotFoundException(name);
  317.34          }
  317.35 -//        beingDefined(loader, name);
  317.36 +        
  317.37 +        return defineClass(arr, name, instance);
  317.38 +    }
  317.39 +
  317.40 +    private Object defineClass(byte[] arr, String name, boolean instance) throws IOException {
  317.41          StringBuilder out = new StringBuilder(65535);
  317.42          out.append("var loader = arguments[0];\n");
  317.43          out.append("var vm = loader.vm;\n");
  317.44          int prelude = out.length();
  317.45          String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr));
  317.46          String code = out.toString().toString();
  317.47 -//        dump("Loading " + name);
  317.48 -        dump(code);
  317.49          String under = name.replace('.', '_');
  317.50          Object fn = applyCode(loader, under, code, instance);
  317.51          
  317.52 @@ -71,26 +77,12 @@
  317.53              out.setLength(prelude);
  317.54              out.append(initCode);
  317.55              code = out.toString().toString();
  317.56 -            dump(code);
  317.57              applyCode(loader, null, code, false);
  317.58          }            
  317.59          
  317.60          return fn;
  317.61      }
  317.62  
  317.63 -//    @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());")
  317.64 -    static void dump(String s) {
  317.65 -    }
  317.66 -
  317.67 -/* possibly not needed:
  317.68 -    @JavaScriptBody(args = {"loader", "n" }, body =
  317.69 -        "var cls = n.replace__Ljava_lang_String_2CC(n, '.','_').toString();" +
  317.70 -        "loader.vm[cls] = true;\n"
  317.71 -    )
  317.72 -    private static native void beingDefined(Object loader, String name);
  317.73 -*/
  317.74 -    
  317.75 -
  317.76      @JavaScriptBody(args = {"loader", "name", "script", "instance" }, body =
  317.77          "try {\n" +
  317.78          "  new Function(script)(loader, name);\n" +
  317.79 @@ -130,6 +122,14 @@
  317.80  
  317.81          @Override
  317.82          protected void requireScript(String resourcePath) throws IOException {
  317.83 +            if (!resourcePath.startsWith("/")) {
  317.84 +                resourcePath = "/" + resourcePath;
  317.85 +            }
  317.86 +            String code = readCode(resourcePath);
  317.87 +            applyCode(lazy.loader, null, code, false);
  317.88 +        }
  317.89 +
  317.90 +        private String readCode(String resourcePath) throws IOException {
  317.91              InputStream is = getClass().getResourceAsStream(resourcePath);
  317.92              StringBuilder sb = new StringBuilder();
  317.93              for (;;) {
  317.94 @@ -139,7 +139,7 @@
  317.95                  }
  317.96                  sb.append((char)ch);
  317.97              }
  317.98 -            applyCode(lazy.loader, null, sb.toString(), false);
  317.99 +            return sb.toString();
 317.100          }
 317.101  
 317.102          @Override
   318.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Tue Apr 29 15:25:58 2014 +0200
   318.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Zips.java	Wed Apr 30 15:04:10 2014 +0200
   318.3 @@ -49,7 +49,7 @@
   318.4      @JavaScriptBody(args = { "arr", "index", "value" }, body = "arr[index] = value; return value;")
   318.5      private static native Object set(Object arr, int index, Object value);
   318.6      
   318.7 -    public static byte[] loadFromCp(Object classpath, String res) 
   318.8 +    public static byte[] loadFromCp(Object classpath, String res, int skip) 
   318.9      throws IOException, ClassNotFoundException {
  318.10          for (int i = 0; i < length(classpath); i++) {
  318.11              Object c = at(classpath, i);
  318.12 @@ -74,24 +74,27 @@
  318.13                  byte[] checkRes;
  318.14                  if (c instanceof Zips) {
  318.15                      checkRes = ((Zips)c).findRes(res);
  318.16 +                    if (checkRes != null && --skip < 0) {
  318.17 +                        return checkRes;
  318.18 +                    }
  318.19                  } else {
  318.20 -                    checkRes = callFunction(c, res);
  318.21 -                }
  318.22 -                if (checkRes != null) {
  318.23 -                    return checkRes;
  318.24 +                    checkRes = callFunction(c, res, skip);
  318.25 +                    if (checkRes != null) {
  318.26 +                        return checkRes;
  318.27 +                    }
  318.28                  }
  318.29              }
  318.30          }
  318.31          return null;
  318.32      }
  318.33      
  318.34 -    @JavaScriptBody(args = { "fn", "res" }, body = 
  318.35 -        "if (typeof fn === 'function') return fn(res);\n"
  318.36 +    @JavaScriptBody(args = { "fn", "res", "skip" }, body = 
  318.37 +        "if (typeof fn === 'function') return fn(res, skip);\n"
  318.38        + "return null;"
  318.39      )
  318.40 -    private static native byte[] callFunction(Object fn, String res);
  318.41 +    private static native byte[] callFunction(Object fn, String res, int skip);
  318.42      
  318.43 -    @JavaScriptBody(args = { "msg" }, body = "console.log(msg.toString());")
  318.44 +    @JavaScriptBody(args = { "msg" }, body = "if (typeof console !== 'undefined') console.log(msg.toString());")
  318.45      private static native void log(String msg);
  318.46  
  318.47      private byte[] findRes(String res) throws IOException {
   319.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java	Tue Apr 29 15:25:58 2014 +0200
   319.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java	Wed Apr 30 15:04:10 2014 +0200
   319.3 @@ -52,4 +52,15 @@
   319.4          assertTrue(returnType[0] != 'V', "Returns string");
   319.5          assertEquals(ret, "toJavaScript__Ljava_lang_String_2_3B");
   319.6      }
   319.7 +    
   319.8 +    @Test public void mangleJsCallbackToAType() throws Exception {
   319.9 +        String res = ByteCodeToJavaScript.mangleJsCallbacks(
  319.10 +            "org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations",
  319.11 +            "onError", "Ljava/lang/Object;", false
  319.12 +        );
  319.13 +        assertEquals(res, 
  319.14 +            "org_1apidesign_1bck2brwsr_1vmtest_1impl_1HtmlAnnotations$onError$Ljava_1lang_1Object_12__Ljava_lang_Object_2Lorg_apidesign_bck2brwsr_vmtest_impl_HtmlAnnotations_2Ljava_lang_Object_2",
  319.15 +            "Pretty long method name"
  319.16 +        );
  319.17 +    }
  319.18  }
   320.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Tue Apr 29 15:25:58 2014 +0200
   320.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Wed Apr 30 15:04:10 2014 +0200
   320.3 @@ -21,20 +21,19 @@
   320.4  import java.io.InputStream;
   320.5  import java.net.URL;
   320.6  import java.util.Enumeration;
   320.7 -import java.util.Set;
   320.8 -import java.util.TreeSet;
   320.9  
  320.10  /**
  320.11   *
  320.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
  320.13   */
  320.14  public final class BytesLoader {
  320.15 -    private static Set<String> requested = new TreeSet<String>();
  320.16 +    private static final StringArray requested = new StringArray();
  320.17  
  320.18      public byte[] get(String name) throws IOException {
  320.19 -        if (!requested.add(name)) {
  320.20 +        if (requested.contains(name)) {
  320.21              throw new IllegalStateException("Requested for second time: " + name);
  320.22          }
  320.23 +        requested.add(name);
  320.24          byte[] arr = readClass(name);
  320.25          /*
  320.26          System.err.print("loader['" + name + "'] = [");
   321.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Tue Apr 29 15:25:58 2014 +0200
   321.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Wed Apr 30 15:04:10 2014 +0200
   321.3 @@ -215,4 +215,17 @@
   321.4          );
   321.5      }
   321.6  
   321.7 +    @Test public void typeOfFn() throws Exception {
   321.8 +        assertExec("Type of function is Object", Classes.class,
   321.9 +            "typeOfFn__Ljava_lang_String_2",
  321.10 +            "java.lang.Object"
  321.11 +        );
  321.12 +    }
  321.13 +    
  321.14 +    @Test public void instanceOfSuperInterface() throws Exception {
  321.15 +        assertExec("Is iof super interface", Classes.class,
  321.16 +            "instanceOfSuperInterface__Z",
  321.17 +            1.0
  321.18 +        );
  321.19 +    }
  321.20  }
   322.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Tue Apr 29 15:25:58 2014 +0200
   322.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Wed Apr 30 15:04:10 2014 +0200
   322.3 @@ -18,6 +18,7 @@
   322.4  package org.apidesign.vm4brwsr;
   322.5  
   322.6  import java.io.IOException;
   322.7 +import java.io.Serializable;
   322.8  import java.lang.annotation.Annotation;
   322.9  import java.lang.annotation.Retention;
  322.10  import java.lang.annotation.RetentionPolicy;
  322.11 @@ -233,4 +234,20 @@
  322.12      public static String valueEnum(String v) {
  322.13          return ClassesMarker.E.valueOf(v).toString();
  322.14      }
  322.15 +    
  322.16 +    public static String typeOfFn() {
  322.17 +        return fn().getClass().getName();
  322.18 +    }
  322.19 +    
  322.20 +    @JavaScriptBody(args = {  }, body = "return function() { alert('x'); };")
  322.21 +    private native static Object fn();
  322.22 +    
  322.23 +    public static boolean instanceOfSuperInterface() {
  322.24 +        Object obj = new SuperSerial() {
  322.25 +        };
  322.26 +        return obj instanceof Serializable;
  322.27 +    }
  322.28 +    
  322.29 +    private static interface SuperSerial extends Serializable {
  322.30 +    }
  322.31  }
   323.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   323.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/DelayedLoading.java	Wed Apr 30 15:04:10 2014 +0200
   323.3 @@ -0,0 +1,31 @@
   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.vm4brwsr;
  323.22 +
  323.23 +import java.net.URL;
  323.24 +
  323.25 +/**
  323.26 + *
  323.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  323.28 + */
  323.29 +public class DelayedLoading {
  323.30 +    public static String toStrViaURI(String url) throws Exception {
  323.31 +        URL u = new URL(url);
  323.32 +        return u.toURI().toString();
  323.33 +    }
  323.34 +}
   324.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   324.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/DelayedLoadingTest.java	Wed Apr 30 15:04:10 2014 +0200
   324.3 @@ -0,0 +1,55 @@
   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.vm4brwsr;
  324.22 +
  324.23 +import java.net.URL;
  324.24 +import org.testng.annotations.BeforeClass;
  324.25 +import org.testng.annotations.AfterClass;
  324.26 +import org.testng.annotations.Test;
  324.27 +
  324.28 +/**
  324.29 + *
  324.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  324.31 + */
  324.32 +public class DelayedLoadingTest {
  324.33 +    private static TestVM code;
  324.34 +    
  324.35 +    @Test public void verifyUsageOf() throws Exception {
  324.36 +        code.register(new BytesLoader());
  324.37 +        
  324.38 +        URL u = new URL("http://apidesign.org");
  324.39 +        
  324.40 +        Object str = code.execCode("Access URI", 
  324.41 +            DelayedLoading.class, "toStrViaURI__Ljava_lang_String_2Ljava_lang_String_2",
  324.42 +            u.toExternalForm(), u.toExternalForm()
  324.43 +        );
  324.44 +    }
  324.45 +    
  324.46 +    
  324.47 +    @BeforeClass 
  324.48 +    public static void compileTheCode() throws Exception {
  324.49 +        code = TestVM.compileClass(
  324.50 +            "org/apidesign/vm4brwsr/DelayedLoading");
  324.51 +    }
  324.52 +    @AfterClass
  324.53 +    public static void releaseTheCode() {
  324.54 +        code = null;
  324.55 +    }
  324.56 +    
  324.57 +}
  324.58 +
   325.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   325.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Hello.java	Wed Apr 30 15:04:10 2014 +0200
   325.3 @@ -0,0 +1,35 @@
   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.vm4brwsr;
  325.22 +
  325.23 +import java.io.IOException;
  325.24 +
  325.25 +/**
  325.26 + *
  325.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  325.28 + */
  325.29 +public class Hello {
  325.30 +    public static String hello() {
  325.31 +        return "Hello World!";
  325.32 +    }
  325.33 +    
  325.34 +    public static Object reloadYourSelf(byte[] arr) throws IOException {
  325.35 +        org.apidesign.vm4brwsr.api.VM.reload(Hello.class, arr);
  325.36 +        return null;
  325.37 +    }
  325.38 +}
   326.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Tue Apr 29 15:25:58 2014 +0200
   326.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Wed Apr 30 15:04:10 2014 +0200
   326.3 @@ -137,4 +137,8 @@
   326.4      
   326.5      @JavaScriptBody(args = { "instance" }, body = "return instance.getByte__B();")
   326.6      private static native int jsgetbytes(Instance instance);
   326.7 +
   326.8 +    int sum(int i, int i0) {
   326.9 +        return i + i0;
  326.10 +    }
  326.11  }
   327.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSub.java	Tue Apr 29 15:25:58 2014 +0200
   327.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSub.java	Wed Apr 30 15:04:10 2014 +0200
   327.3 @@ -31,7 +31,7 @@
   327.4      
   327.5      @Override
   327.6      public void setByte(byte b) {
   327.7 -        super.setByte((byte) (b + 1));
   327.8 +        super.setByte((byte) (b + StaticMethod.MISSING_CONSTANT));
   327.9      }
  327.10      
  327.11      public static double recallDbl() {
   328.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   328.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/NoStringCnstntsTest.java	Wed Apr 30 15:04:10 2014 +0200
   328.3 @@ -0,0 +1,62 @@
   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 +
  328.22 +package org.apidesign.vm4brwsr;
  328.23 +
  328.24 +import java.io.IOException;
  328.25 +import java.io.InputStream;
  328.26 +import static org.testng.Assert.assertEquals;
  328.27 +import org.testng.annotations.AfterClass;
  328.28 +import org.testng.annotations.BeforeClass;
  328.29 +import org.testng.annotations.Test;
  328.30 +
  328.31 +/**
  328.32 + *
  328.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  328.34 + */
  328.35 +public class NoStringCnstntsTest {
  328.36 +    private static String code;
  328.37 +
  328.38 +    
  328.39 +    @Test public void dontGeneratePrimitiveFinalConstants() {
  328.40 +        assertEquals(code.indexOf("HELLO"), -1, "MISSING_CONSTANT field should not be generated");
  328.41 +    }
  328.42 +    
  328.43 +    @BeforeClass 
  328.44 +    public static void compileTheCode() throws Exception {
  328.45 +        final String res = "org/apidesign/vm4brwsr/StringSample";
  328.46 +        StringBuilder sb = new StringBuilder();
  328.47 +        class JustStaticMethod implements Bck2Brwsr.Resources {
  328.48 +            @Override
  328.49 +            public InputStream get(String resource) throws IOException {
  328.50 +                final String cn = res + ".class";
  328.51 +                if (resource.equals(cn)) {
  328.52 +                    return getClass().getClassLoader().getResourceAsStream(cn);
  328.53 +                }
  328.54 +                return null;
  328.55 +            }
  328.56 +        }
  328.57 +        Bck2Brwsr.generate(sb, new JustStaticMethod(), res);
  328.58 +        code = sb.toString();
  328.59 +    }
  328.60 +    @AfterClass
  328.61 +    public static void releaseTheCode() {
  328.62 +        code = null;
  328.63 +    }
  328.64 +    
  328.65 +}
   329.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Tue Apr 29 15:25:58 2014 +0200
   329.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Wed Apr 30 15:04:10 2014 +0200
   329.3 @@ -77,16 +77,22 @@
   329.4              new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)13, (byte)126 }
   329.5          );
   329.6      }
   329.7 -    /* XXX: JavaScript cannot represent as big longs as Java. 
   329.8 +    @Test public void deserializeMiddleLong() throws Exception {
   329.9 +        final byte[] arr = new byte[] {
  329.10 +            (byte)0, (byte)0, (byte)64, (byte)32, (byte)23, (byte)0, (byte)0, (byte)0
  329.11 +        };
  329.12 +        long exp = Numbers.deserLong(arr, 16);
  329.13 +        assertExec("Should be " + exp, Numbers.class, "deserLong__J_3BI", 
  329.14 +            Double.valueOf(exp), arr, 16);
  329.15 +    }
  329.16      @Test public void deserializeLargeLong() throws Exception {
  329.17          final byte[] arr = new byte[] {
  329.18              (byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0
  329.19          };
  329.20 -        long exp = Numbers.deserLong(arr);
  329.21 -        assertExec("Should be " + exp, "org_apidesign_vm4brwsr_Numbers_deserLong__JAB", 
  329.22 -            Double.valueOf(exp), arr);
  329.23 +        long exp = Numbers.deserLong(arr, 32);
  329.24 +        assertExec("Should be " + exp, Numbers.class, "deserLong__J_3BI", 
  329.25 +            Double.valueOf(exp), arr, 32);
  329.26      }
  329.27 -    */
  329.28      
  329.29      @Test public void deserializeFloatInJava() throws Exception {
  329.30          float f = 54324.32423f;
  329.31 @@ -111,6 +117,12 @@
  329.32          double f = 3.0;
  329.33          assertExec("Should be the same", Numbers.class, "deserDouble__D", f);
  329.34      }
  329.35 +    
  329.36 +    @Test public void bytesToLong() throws Exception {
  329.37 +        long exp = Numbers.bytesToLong((byte)30, (byte)20, 32);
  329.38 +        assertExec("Should be the same", Numbers.class, "bytesToLong__JBBI", 
  329.39 +            Double.valueOf(exp), 30, 20, 32);
  329.40 +    }
  329.41      /*
  329.42      @Test public void serDouble() throws IOException {
  329.43          double f = 3.0;
   330.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Tue Apr 29 15:25:58 2014 +0200
   330.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Wed Apr 30 15:04:10 2014 +0200
   330.3 @@ -55,12 +55,19 @@
   330.4          DataInputStream dis = new DataInputStream(is);
   330.5          return dis.readLong();
   330.6      }
   330.7 +    static long deserLong(byte[] arr, int shift) throws IOException {
   330.8 +        return deserLong(arr) >> shift;
   330.9 +    }
  330.10      static int deserInt() throws IOException {
  330.11          byte[] arr = {(byte) 71, (byte) 84, (byte) 52, (byte) 83};
  330.12          ByteArrayInputStream is = new ByteArrayInputStream(arr);
  330.13          DataInputStream dis = new DataInputStream(is);
  330.14          return dis.readInt();
  330.15      }
  330.16 +    static long bytesToLong(byte b1, byte b2, int shift) {
  330.17 +        return (((long)b1 << 56) +
  330.18 +                ((long)b2 & 255) << 48) >> shift;
  330.19 +    }
  330.20  
  330.21      static String intToString() {
  330.22          return new Integer(5).toString().toString();
   331.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   331.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ReloadingTest.java	Wed Apr 30 15:04:10 2014 +0200
   331.3 @@ -0,0 +1,72 @@
   331.4 +/**
   331.5 + * Back 2 Browser Bytecode Translator
   331.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   331.7 + *
   331.8 + * This program is free software: you can redistribute it and/or modify
   331.9 + * it under the terms of the GNU General Public License as published by
  331.10 + * the Free Software Foundation, version 2 of the License.
  331.11 + *
  331.12 + * This program is distributed in the hope that it will be useful,
  331.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  331.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  331.15 + * GNU General Public License for more details.
  331.16 + *
  331.17 + * You should have received a copy of the GNU General Public License
  331.18 + * along with this program. Look for COPYING file in the top folder.
  331.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  331.20 + */
  331.21 +package org.apidesign.vm4brwsr;
  331.22 +
  331.23 +import org.testng.annotations.BeforeClass;
  331.24 +import org.testng.annotations.AfterClass;
  331.25 +import org.testng.annotations.Test;
  331.26 +
  331.27 +/**
  331.28 + *
  331.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  331.30 + */
  331.31 +public class ReloadingTest {
  331.32 +    private static TestVM code;
  331.33 +    
  331.34 +    @Test public void verifyUsageOf() throws Exception {
  331.35 +        code.execCode("First hello", 
  331.36 +            Hello.class, "hello__Ljava_lang_String_2",
  331.37 +            "Hello World!"
  331.38 +        );
  331.39 +
  331.40 +        byte[] arr = BytesLoader.readClass("org/apidesign/vm4brwsr/Hello.class");
  331.41 +        for (int i = 0; i < arr.length; i++) {
  331.42 +            if (arr[i] == 'H' && arr[i + 1] == 'e' && arr[i + 2] == 'l') {
  331.43 +                arr[i] = 'A';
  331.44 +                arr[i + 1] = 'h';
  331.45 +                arr[i + 2] = 'o';
  331.46 +                arr[i + 3] = 'y';
  331.47 +                arr[i + 4] = ' ';
  331.48 +                break;
  331.49 +            }
  331.50 +        }
  331.51 +        
  331.52 +        code.execCode("Redefine class",
  331.53 +            Hello.class, "reloadYourSelf__Ljava_lang_Object_2_3B",
  331.54 +            null, arr
  331.55 +        );
  331.56 +
  331.57 +        code.execCode("Second hello", 
  331.58 +            Hello.class, "hello__Ljava_lang_String_2",
  331.59 +            "Ahoy  World!"
  331.60 +        );
  331.61 +    }
  331.62 +    
  331.63 +    
  331.64 +    @BeforeClass 
  331.65 +    public static void compileTheCode() throws Exception {
  331.66 +        code = TestVM.compileClass(
  331.67 +            "org/apidesign/vm4brwsr/Hello");
  331.68 +    }
  331.69 +    @AfterClass
  331.70 +    public static void releaseTheCode() {
  331.71 +        code = null;
  331.72 +    }
  331.73 +    
  331.74 +}
  331.75 +
   332.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java	Tue Apr 29 15:25:58 2014 +0200
   332.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java	Wed Apr 30 15:04:10 2014 +0200
   332.3 @@ -59,6 +59,10 @@
   332.4          
   332.5          return sb.toString().toString();
   332.6      }
   332.7 +    static long bytesToLong(byte b1, byte b2, int shift) {
   332.8 +        return (((long)b1 << 56) +
   332.9 +                ((long)b2 & 255) << 48) >> shift;
  332.10 +    }
  332.11  
  332.12      static String loadHello() throws IOException {
  332.13          Enumeration<URL> en;
   333.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesWithExtensionsTest.java	Tue Apr 29 15:25:58 2014 +0200
   333.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesWithExtensionsTest.java	Wed Apr 30 15:04:10 2014 +0200
   333.3 @@ -46,7 +46,7 @@
   333.4          );
   333.5      }
   333.6      */
   333.7 -    
   333.8 +
   333.9      private static TestVM code;
  333.10      
  333.11      @BeforeClass 
   334.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   334.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/SizeOfAMethodTest.java	Wed Apr 30 15:04:10 2014 +0200
   334.3 @@ -0,0 +1,96 @@
   334.4 +/**
   334.5 + * Back 2 Browser Bytecode Translator
   334.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   334.7 + *
   334.8 + * This program is free software: you can redistribute it and/or modify
   334.9 + * it under the terms of the GNU General Public License as published by
  334.10 + * the Free Software Foundation, version 2 of the License.
  334.11 + *
  334.12 + * This program is distributed in the hope that it will be useful,
  334.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  334.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  334.15 + * GNU General Public License for more details.
  334.16 + *
  334.17 + * You should have received a copy of the GNU General Public License
  334.18 + * along with this program. Look for COPYING file in the top folder.
  334.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  334.20 + */
  334.21 +/*
  334.22 + * To change this license header, choose License Headers in Project Properties.
  334.23 + * To change this template file, choose Tools | Templates
  334.24 + * and open the template in the editor.
  334.25 + */
  334.26 +
  334.27 +package org.apidesign.vm4brwsr;
  334.28 +
  334.29 +import java.io.IOException;
  334.30 +import java.io.InputStream;
  334.31 +import static org.testng.Assert.assertEquals;
  334.32 +import static org.testng.Assert.assertTrue;
  334.33 +import org.testng.annotations.AfterClass;
  334.34 +import org.testng.annotations.BeforeClass;
  334.35 +import org.testng.annotations.Test;
  334.36 +
  334.37 +/**
  334.38 + *
  334.39 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  334.40 + */
  334.41 +public class SizeOfAMethodTest {
  334.42 +    private static String code;
  334.43 +
  334.44 +    @Test public void sumXYShouldBeSmall() {
  334.45 +        String s = code;
  334.46 +        int beg = s.indexOf("c.sum__III");
  334.47 +        int end = s.indexOf("c.sum__III.access");
  334.48 +        
  334.49 +        assertTrue(beg > 0, "Found sum method in " + code);
  334.50 +        assertTrue(beg < end, "Found end of sum method in " + code);
  334.51 +        
  334.52 +        String method = s.substring(beg, end);
  334.53 +        
  334.54 +        
  334.55 +        assertEquals(method.indexOf("st"), -1, "There should be no stack operations:\n" + method);
  334.56 +    }
  334.57 +
  334.58 +    @Test public void emptyConstructorRequiresNoStack() {
  334.59 +        String s = code;
  334.60 +        int beg = s.indexOf("CLS.cons__V");
  334.61 +        int end = s.indexOf("CLS.cons__V.access");
  334.62 +        
  334.63 +        assertTrue(beg > 0, "Found constructor in " + code);
  334.64 +        assertTrue(beg < end, "Found end of constructor in " + code);
  334.65 +        
  334.66 +        String method = s.substring(beg, end);
  334.67 +        method = method.replace("constructor", "CNSTR");
  334.68 +        
  334.69 +        assertEquals(method.indexOf("st"), -1, "There should be no stack operations:\n" + method);
  334.70 +        assertEquals(method.indexOf("for"), -1, "There should be no for blocks:\n" + method);
  334.71 +    }
  334.72 +    
  334.73 +    @Test public void dontGeneratePrimitiveFinalConstants() {
  334.74 +        assertEquals(code.indexOf("MISSING_CONSTANT"), -1, "MISSING_CONSTANT field should not be generated");
  334.75 +    }
  334.76 +    
  334.77 +    @BeforeClass 
  334.78 +    public static void compileTheCode() throws Exception {
  334.79 +        final String res = "org/apidesign/vm4brwsr/StaticMethod";
  334.80 +        StringBuilder sb = new StringBuilder();
  334.81 +        class JustStaticMethod implements Bck2Brwsr.Resources {
  334.82 +            @Override
  334.83 +            public InputStream get(String resource) throws IOException {
  334.84 +                final String cn = res + ".class";
  334.85 +                if (resource.equals(cn)) {
  334.86 +                    return getClass().getClassLoader().getResourceAsStream(cn);
  334.87 +                }
  334.88 +                return null;
  334.89 +            }
  334.90 +        }
  334.91 +        Bck2Brwsr.generate(sb, new JustStaticMethod(), res);
  334.92 +        code = sb.toString();
  334.93 +    }
  334.94 +    @AfterClass
  334.95 +    public static void releaseTheCode() {
  334.96 +        code = null;
  334.97 +    }
  334.98 +    
  334.99 +}
   335.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java	Tue Apr 29 15:25:58 2014 +0200
   335.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java	Wed Apr 30 15:04:10 2014 +0200
   335.3 @@ -24,6 +24,7 @@
   335.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
   335.5   */
   335.6  public class StaticMethod {
   335.7 +    public static final int MISSING_CONSTANT = 1;
   335.8      private static int cnt;
   335.9      private static Object NULL;
  335.10  
  335.11 @@ -82,7 +83,7 @@
  335.12          if (n <= 1) {
  335.13              return 1;
  335.14          } else {
  335.15 -            return n * factRec(n - 1);
  335.16 +            return n * factRec(n - MISSING_CONSTANT);
  335.17          }
  335.18      }
  335.19      public static long factIter(int n) {
  335.20 @@ -99,6 +100,10 @@
  335.21          return cnt;
  335.22      }
  335.23      
  335.24 +    public static int helloWorldLength(String x) {
  335.25 +        return (StringSample.HELLO + x).length();
  335.26 +    }
  335.27 +    
  335.28      @JavaScriptBody(
  335.29          args={"i","j"}, body="\n\r\treturn (i + j).toString();"
  335.30      )
  335.31 @@ -128,6 +133,62 @@
  335.32          }
  335.33      }
  335.34      
  335.35 +    public static int castString(Object o) {
  335.36 +        return ((String)o).length();
  335.37 +    }
  335.38 +    
  335.39 +    public static int initInflater(int w, boolean nowrap) {
  335.40 +        Instance i = new Instance(w, 0.0);
  335.41 +        return i.sum(nowrap?-w:w, 1);
  335.42 +    }
  335.43 +    
  335.44 +    public static String toStringArr() {
  335.45 +        class N implements Next {
  335.46 +            int idx = 0;
  335.47 +            
  335.48 +            @Override
  335.49 +            public boolean hasNext() {
  335.50 +                return idx < 5;
  335.51 +            }
  335.52 +
  335.53 +            @Override
  335.54 +            public String next() {
  335.55 +                switch (idx++) {
  335.56 +                    case 0: return "Zero";
  335.57 +                    case 1: return "One";
  335.58 +                    case 2: return "Two";
  335.59 +                    case 3: return "Three";
  335.60 +                    case 4: return "Four";
  335.61 +                }
  335.62 +                throw new IllegalStateException();
  335.63 +            }
  335.64 +        }
  335.65 +        return toString(null, new N()).toString();
  335.66 +    }
  335.67 +    
  335.68 +    static String toString(Object thiz, Next it) {
  335.69 +        if (!it.hasNext()) {
  335.70 +            return "[]";
  335.71 +        }
  335.72 +
  335.73 +        StringBuilder sb = new StringBuilder();
  335.74 +        sb.append('[');
  335.75 +        for (;;) {
  335.76 +            String e = it.next();
  335.77 +            sb.append(e == thiz ? "(this Collection)" : e);
  335.78 +            if (!it.hasNext()) {
  335.79 +                return sb.append(']').toString();
  335.80 +            }
  335.81 +            sb.append(',').append(' ');
  335.82 +        }
  335.83 +    }
  335.84 +    
  335.85 +    static interface Next {
  335.86 +        boolean hasNext();
  335.87 +        String next();
  335.88 +    }
  335.89 +    
  335.90 +    
  335.91      static {
  335.92          // check order of initializers
  335.93          StaticUse.NON_NULL.equals(new Object());
   336.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Tue Apr 29 15:25:58 2014 +0200
   336.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Wed Apr 30 15:04:10 2014 +0200
   336.3 @@ -36,6 +36,15 @@
   336.4          );
   336.5      }
   336.6  
   336.7 +    @Test public void cast() throws Exception {
   336.8 +        assertExec(
   336.9 +            "Length is four", 
  336.10 +            StaticMethod.class, "castString__ILjava_lang_Object_2", 
  336.11 +            Double.valueOf(4), 
  336.12 +            "Ahoj"
  336.13 +        );
  336.14 +    }
  336.15 +
  336.16      @Test public void checkReallyInitializedValues() throws Exception {
  336.17          assertExec(
  336.18              "Return true", 
  336.19 @@ -161,6 +170,25 @@
  336.20              3, 3.75
  336.21          );
  336.22      }
  336.23 +  
  336.24 +    @Test public void inflaterInit() throws Exception {
  336.25 +        assertExec(
  336.26 +            "Down and minus",
  336.27 +            StaticMethod.class, "initInflater__IIZ",
  336.28 +            Double.valueOf(-9),
  336.29 +            10, true
  336.30 +        );
  336.31 +    }
  336.32 +
  336.33 +    @Test public void inflaterInitNoNeg() throws Exception {
  336.34 +        assertExec(
  336.35 +            "One up",
  336.36 +            StaticMethod.class, "initInflater__IIZ",
  336.37 +            Double.valueOf(11),
  336.38 +            10, false
  336.39 +        );
  336.40 +    }
  336.41 +    
  336.42      @Test public void mixedMethodFourParams() throws Exception {
  336.43          assertExec(
  336.44              "Should be two",
  336.45 @@ -196,6 +224,15 @@
  336.46          );
  336.47      }
  336.48      
  336.49 +    @Test public void collectionToString() throws Exception {
  336.50 +        String exp = StaticMethod.toStringArr();
  336.51 +        assertExec(
  336.52 +            "0 to 4",
  336.53 +            StaticMethod.class, "toStringArr__Ljava_lang_String_2",
  336.54 +            exp
  336.55 +        );
  336.56 +    }
  336.57 +    
  336.58      @Test public void or() throws Exception {
  336.59          assertExec(
  336.60              "Or will be 7",
  336.61 @@ -322,6 +359,13 @@
  336.62          );
  336.63      }
  336.64      
  336.65 +    @Test public void stringConstantIsCopied() throws Exception {
  336.66 +        assertExec("String constants are copied between class pools",
  336.67 +            StaticMethod.class, "helloWorldLength__ILjava_lang_String_2", 
  336.68 +            17, "Jardo"
  336.69 +        );
  336.70 +    }
  336.71 +    
  336.72      private static TestVM code;
  336.73      
  336.74      @BeforeClass 
   337.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java	Tue Apr 29 15:25:58 2014 +0200
   337.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java	Wed Apr 30 15:04:10 2014 +0200
   337.3 @@ -80,6 +80,10 @@
   337.4          return sb.toString().toString();
   337.5      }
   337.6      
   337.7 +    public static String unicode() {
   337.8 +        return "\r\n\u2028\u2029]";
   337.9 +    }
  337.10 +    
  337.11      public static String insertBuffer() {
  337.12          StringBuilder sb = new StringBuilder();
  337.13          sb.append("Jardo!");
   338.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Tue Apr 29 15:25:58 2014 +0200
   338.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Wed Apr 30 15:04:10 2014 +0200
   338.3 @@ -213,6 +213,16 @@
   338.4              exp, false, true
   338.5          );
   338.6      }
   338.7 +    
   338.8 +    @Test public void weirdUnicodeCharacters() throws Exception {
   338.9 +        String exp = StringSample.unicode();
  338.10 +        
  338.11 +        assertExec(
  338.12 +            "Unicode is OK",
  338.13 +            StringSample.class, "unicode__Ljava_lang_String_2",
  338.14 +            exp
  338.15 +        );
  338.16 +    }
  338.17  
  338.18      @Test public void valueOfOnJSArray() throws Exception {
  338.19          assertExec(
   339.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Tue Apr 29 15:25:58 2014 +0200
   339.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Wed Apr 30 15:04:10 2014 +0200
   339.3 @@ -25,23 +25,33 @@
   339.4  import java.net.URL;
   339.5  import java.util.Enumeration;
   339.6  import javax.script.Invocable;
   339.7 +import javax.script.ScriptContext;
   339.8  import javax.script.ScriptEngine;
   339.9  import javax.script.ScriptEngineManager;
  339.10  import javax.script.ScriptException;
  339.11  import static org.testng.Assert.*;
  339.12  
  339.13 -final class TestVM {
  339.14 +public final class TestVM {
  339.15      private final Invocable code;
  339.16      private final CharSequence codeSeq;
  339.17      private final Object bck2brwsr;
  339.18 +    private BytesLoader resources;
  339.19      
  339.20      
  339.21      private TestVM(Invocable code, CharSequence codeSeq) throws ScriptException, NoSuchMethodException {
  339.22          this.code = code;
  339.23          this.codeSeq = codeSeq;
  339.24 -        this.bck2brwsr = code.invokeFunction("bck2brwsr");
  339.25 +        this.bck2brwsr = ((ScriptEngine)code).eval("bck2brwsr(function(n) { return loader.get(n); })");
  339.26 +        ((ScriptEngine)code).getContext().setAttribute("loader", this, ScriptContext.ENGINE_SCOPE);
  339.27      }
  339.28      
  339.29 +    public void register(BytesLoader res) {
  339.30 +        this.resources = res;
  339.31 +    }
  339.32 +    
  339.33 +    public byte[] get(String res) throws IOException {
  339.34 +        return resources != null ? resources.get(res) : null;
  339.35 +    }
  339.36  
  339.37      public Object execCode(
  339.38          String msg, Class<?> clazz, String method, 
  339.39 @@ -234,11 +244,26 @@
  339.40              return ex.toString();
  339.41          }
  339.42      }
  339.43 -    
  339.44 +
  339.45 +    final CharSequence codeSeq() {
  339.46 +        return codeSeq;
  339.47 +    }
  339.48      
  339.49      private static class EmulationResources implements Bck2Brwsr.Resources {
  339.50          @Override
  339.51          public InputStream get(String name) throws IOException {
  339.52 +            if ("java/net/URI.class".equals(name)) {
  339.53 +                // skip
  339.54 +                return null;
  339.55 +            }
  339.56 +            if ("java/net/URLConnection.class".equals(name)) {
  339.57 +                // skip
  339.58 +                return null;
  339.59 +            }
  339.60 +            if ("java/lang/System.class".equals(name)) {
  339.61 +                // skip
  339.62 +                return null;
  339.63 +            }
  339.64              Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
  339.65              URL u = null;
  339.66              while (en.hasMoreElements()) {
   340.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   340.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/UnderTest.java	Wed Apr 30 15:04:10 2014 +0200
   340.3 @@ -0,0 +1,88 @@
   340.4 +/**
   340.5 + * Back 2 Browser Bytecode Translator
   340.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   340.7 + *
   340.8 + * This program is free software: you can redistribute it and/or modify
   340.9 + * it under the terms of the GNU General Public License as published by
  340.10 + * the Free Software Foundation, version 2 of the License.
  340.11 + *
  340.12 + * This program is distributed in the hope that it will be useful,
  340.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  340.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  340.15 + * GNU General Public License for more details.
  340.16 + *
  340.17 + * You should have received a copy of the GNU General Public License
  340.18 + * along with this program. Look for COPYING file in the top folder.
  340.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  340.20 + */
  340.21 +package org.apidesign.vm4brwsr;
  340.22 +
  340.23 +import org.testng.annotations.AfterClass;
  340.24 +import org.testng.annotations.BeforeClass;
  340.25 +import org.testng.annotations.Test;
  340.26 +
  340.27 +/** Checks behavior of classes and methods with underscore.
  340.28 + *
  340.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  340.30 + */
  340.31 +public class UnderTest {
  340.32 +    @Test public void one() throws Exception {
  340.33 +        assertExec(
  340.34 +            "Should be one", 
  340.35 +            Under_Score.class, "one__I", 
  340.36 +            Double.valueOf(1)
  340.37 +        );
  340.38 +    }
  340.39 +
  340.40 +    @Test public void onePlusOne() throws Exception {
  340.41 +        assertExec(
  340.42 +            "Should be two", 
  340.43 +            Under_Score.class, "one_1plus_1one__I", 
  340.44 +            Double.valueOf(2)
  340.45 +        );
  340.46 +    }
  340.47 +
  340.48 +    @Test public void two() throws Exception {
  340.49 +        assertExec(
  340.50 +            "Should be two", 
  340.51 +            Under_Score.class, "two__I", 
  340.52 +            Double.valueOf(2)
  340.53 +        );
  340.54 +    }
  340.55 +
  340.56 +    @Test public void staticField() throws Exception {
  340.57 +        assertExec(
  340.58 +            "Should be ten", 
  340.59 +            Under_Score.class, "staticField__I", 
  340.60 +            Double.valueOf(10)
  340.61 +        );
  340.62 +    }
  340.63 +
  340.64 +    @Test public void instance() throws Exception {
  340.65 +        assertExec(
  340.66 +            "Should be five", 
  340.67 +            Under_Score.class, "instance__I", 
  340.68 +            Double.valueOf(5)
  340.69 +        );
  340.70 +    }
  340.71 +
  340.72 +    
  340.73 +    private static TestVM code;
  340.74 +    
  340.75 +    @BeforeClass 
  340.76 +    public static void compileTheCode() throws Exception {
  340.77 +        StringBuilder sb = new StringBuilder();
  340.78 +        code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/Under_Score");
  340.79 +    }
  340.80 +    @AfterClass
  340.81 +    public static void releaseTheCode() {
  340.82 +        code = null;
  340.83 +    }
  340.84 +
  340.85 +    private void assertExec(
  340.86 +        String msg, Class<?> clazz, String method, 
  340.87 +        Object ret, Object... args
  340.88 +    ) throws Exception {
  340.89 +        code.assertExec(msg, clazz, method, ret, args);
  340.90 +    }
  340.91 +}
   341.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   341.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Under_Score.java	Wed Apr 30 15:04:10 2014 +0200
   341.3 @@ -0,0 +1,51 @@
   341.4 +/**
   341.5 + * Back 2 Browser Bytecode Translator
   341.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   341.7 + *
   341.8 + * This program is free software: you can redistribute it and/or modify
   341.9 + * it under the terms of the GNU General Public License as published by
  341.10 + * the Free Software Foundation, version 2 of the License.
  341.11 + *
  341.12 + * This program is distributed in the hope that it will be useful,
  341.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  341.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  341.15 + * GNU General Public License for more details.
  341.16 + *
  341.17 + * You should have received a copy of the GNU General Public License
  341.18 + * along with this program. Look for COPYING file in the top folder.
  341.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  341.20 + */
  341.21 +package org.apidesign.vm4brwsr;
  341.22 +
  341.23 +/**
  341.24 + *
  341.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  341.26 + */
  341.27 +public class Under_Score {
  341.28 +    public static int under_field = 10;
  341.29 +    public int instance_field = 5;
  341.30 +    
  341.31 +    public static int one() {
  341.32 +        return 1;
  341.33 +    }
  341.34 +    
  341.35 +    public static int one_plus_one() {
  341.36 +        return 1 + 1;
  341.37 +    }
  341.38 +    
  341.39 +    public static int two() {
  341.40 +        return one_plus_one();
  341.41 +    }
  341.42 +    
  341.43 +    public static int staticField() {
  341.44 +        return under_field;
  341.45 +    }
  341.46 +    
  341.47 +    public static int instance() {
  341.48 +        return new Under_Score().get_fld();
  341.49 +    }
  341.50 +    
  341.51 +    private int get_fld() {
  341.52 +        return instance_field;
  341.53 +    }
  341.54 +}
   342.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Tue Apr 29 15:25:58 2014 +0200
   342.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Wed Apr 30 15:04:10 2014 +0200
   342.3 @@ -79,7 +79,7 @@
   342.4                  }
   342.5              }
   342.6              w.append("\n];\n");
   342.7 -            w.append(code.toString());
   342.8 +            w.append(code.codeSeq());
   342.9              w.close();
  342.10              throw new Exception(ex.getMessage() + " file: " + f, ex);
  342.11          }
   343.1 --- a/rt/vmtest/pom.xml	Tue Apr 29 15:25:58 2014 +0200
   343.2 +++ b/rt/vmtest/pom.xml	Wed Apr 30 15:04:10 2014 +0200
   343.3 @@ -4,11 +4,11 @@
   343.4    <parent>
   343.5      <groupId>org.apidesign.bck2brwsr</groupId>
   343.6      <artifactId>rt</artifactId>
   343.7 -    <version>0.8-SNAPSHOT</version>
   343.8 +    <version>0.9-SNAPSHOT</version>
   343.9    </parent>
  343.10    <groupId>org.apidesign.bck2brwsr</groupId>
  343.11    <artifactId>vmtest</artifactId>
  343.12 -  <version>0.8-SNAPSHOT</version>
  343.13 +  <version>0.9-SNAPSHOT</version>
  343.14    
  343.15    <name>VM Testing APIs</name>
  343.16    <url>http://bck2brwsr.apidesign.org</url>
   344.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Tue Apr 29 15:25:58 2014 +0200
   344.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Wed Apr 30 15:04:10 2014 +0200
   344.3 @@ -17,6 +17,7 @@
   344.4   */
   344.5  package org.apidesign.bck2brwsr.vmtest;
   344.6  
   344.7 +import java.lang.annotation.Annotation;
   344.8  import java.util.ArrayList;
   344.9  import java.util.Arrays;
  344.10  import java.util.List;
  344.11 @@ -39,6 +40,7 @@
  344.12  public final class VMTest {
  344.13      private final List<Class> classes = new ArrayList<>();
  344.14      private final List<String> launcher = new ArrayList<>();
  344.15 +    private Class<? extends Annotation> annotation = BrwsrTest.class;
  344.16      
  344.17      private VMTest() {
  344.18      }
  344.19 @@ -104,6 +106,24 @@
  344.20          this.launcher.addAll(Arrays.asList(launcher));
  344.21          return this;
  344.22      }
  344.23 +
  344.24 +    /** Specifies which annotation annotates the test methods
  344.25 +     * to be executed. By 
  344.26 +     * default it is the {@link BrwsrTest} annotation. Methods in
  344.27 +     * {@link #withClasses(java.lang.Class[]) test classes} annotated by
  344.28 +     * this annotation will be executed.
  344.29 +     * 
  344.30 +     * @param aClass an annotation class 
  344.31 +     * @return this
  344.32 +     * @since 0.8
  344.33 +     */
  344.34 +    public final VMTest withTestAnnotation(Class<? extends Annotation> aClass) {
  344.35 +        if (!aClass.isAnnotation()) {
  344.36 +            throw new IllegalStateException();
  344.37 +        }
  344.38 +        this.annotation = aClass;
  344.39 +        return this;
  344.40 +    }
  344.41      
  344.42      /** Assembles the provided information into the final array of tests.
  344.43       * @return array of TestNG tests
  344.44 @@ -112,7 +132,8 @@
  344.45      public final Object[] build() {
  344.46          return CompareCase.create(
  344.47              launcher.toArray(new String[0]), 
  344.48 -            classes.toArray(new Class[0])
  344.49 +            classes.toArray(new Class[0]),
  344.50 +            annotation
  344.51          );
  344.52      }
  344.53  }
   345.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Tue Apr 29 15:25:58 2014 +0200
   345.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Wed Apr 30 15:04:10 2014 +0200
   345.3 @@ -17,6 +17,7 @@
   345.4   */
   345.5  package org.apidesign.bck2brwsr.vmtest.impl;
   345.6  
   345.7 +import java.lang.annotation.Annotation;
   345.8  import org.apidesign.bck2brwsr.vmtest.*;
   345.9  import java.lang.reflect.Method;
  345.10  import java.util.ArrayList;
  345.11 @@ -53,7 +54,7 @@
  345.12       * @param clazz the class to inspect
  345.13       * @return the set of created tests
  345.14       */
  345.15 -    public static Object[] create(String[] brwsr, Class[] classes) {
  345.16 +    public static Object[] create(String[] brwsr, Class[] classes, Class<? extends Annotation> brwsrTest) {
  345.17          List<Object> ret = new ArrayList<>();
  345.18          
  345.19          final LaunchSetup l = LaunchSetup.INSTANCE;
  345.20 @@ -70,7 +71,7 @@
  345.21              Method[] arr = clazz.getMethods();
  345.22              for (Method m : arr) {
  345.23                  registerCompareCases(m, l, ret, brwsr);
  345.24 -                registerBrwsrCases(m, l, ret, brwsr);
  345.25 +                registerBrwsrCases(brwsrTest, m, l, ret, brwsr);
  345.26              }
  345.27          }
  345.28          return ret.toArray();
  345.29 @@ -149,8 +150,8 @@
  345.30              ret.add(new CompareCase(m, real, cse));
  345.31          }
  345.32      }
  345.33 -    private static void registerBrwsrCases(Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
  345.34 -        BrwsrTest c = m.getAnnotation(BrwsrTest.class);
  345.35 +    private static void registerBrwsrCases(Class<? extends Annotation> brwsrTest, Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
  345.36 +        Object c = m.getAnnotation(brwsrTest);
  345.37          if (c == null) {
  345.38              return;
  345.39          }