--- a/jdk/.hgignore Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/.hgignore Mon Aug 24 22:27:30 2009 -0700
@@ -1,3 +1,6 @@
^build/
^dist/
^nbproject/private/
+^make/netbeans/.*/nbproject/private/
+^make/netbeans/.*/build/
+^make/netbeans/.*/dist/
--- a/jdk/make/java/nio/FILES_java.gmk Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/java/nio/FILES_java.gmk Mon Aug 24 22:27:30 2009 -0700
@@ -160,7 +160,6 @@
\
sun/nio/ByteBuffered.java \
\
- sun/nio/ch/AbstractFuture.java \
sun/nio/ch/AbstractPollArrayWrapper.java \
sun/nio/ch/AllocatedNativeObject.java \
sun/nio/ch/AsynchronousChannelGroupImpl.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/build.xml Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See commented blocks below for -->
+<!-- some examples of how to customize the build. -->
+<!-- (If you delete it and reopen the project it will be recreated.) -->
+<!-- By default, only the Clean and Build commands use this build script. -->
+<!-- Commands such as Run, Debug, and Test only use this build script if -->
+<!-- the Compile on Save feature is turned off for the project. -->
+<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
+<!-- in the project's Project Properties dialog box.-->
+<project name="jdwpgen" default="default" basedir=".">
+ <description>Builds, tests, and runs the project jdwpgen.</description>
+ <import file="nbproject/build-impl.xml"/>
+ <!--
+
+ There exist several targets which are by default empty and which can be
+ used for execution of your tasks. These targets are usually executed
+ before and after some main targets. They are:
+
+ -pre-init: called before initialization of project properties
+ -post-init: called after initialization of project properties
+ -pre-compile: called before javac compilation
+ -post-compile: called after javac compilation
+ -pre-compile-single: called before javac compilation of single file
+ -post-compile-single: called after javac compilation of single file
+ -pre-compile-test: called before javac compilation of JUnit tests
+ -post-compile-test: called after javac compilation of JUnit tests
+ -pre-compile-test-single: called before javac compilation of single JUnit test
+ -post-compile-test-single: called after javac compilation of single JUunit test
+ -pre-jar: called before JAR building
+ -post-jar: called after JAR building
+ -post-clean: called after cleaning build products
+
+ (Targets beginning with '-' are not intended to be called on their own.)
+
+ Example of inserting an obfuscator after compilation could look like this:
+
+ <target name="-post-compile">
+ <obfuscate>
+ <fileset dir="${build.classes.dir}"/>
+ </obfuscate>
+ </target>
+
+ For list of available properties check the imported
+ nbproject/build-impl.xml file.
+
+
+ Another way to customize the build is by overriding existing main targets.
+ The targets of interest are:
+
+ -init-macrodef-javac: defines macro for javac compilation
+ -init-macrodef-junit: defines macro for junit execution
+ -init-macrodef-debug: defines macro for class debugging
+ -init-macrodef-java: defines macro for class execution
+ -do-jar-with-manifest: JAR building (if you are using a manifest)
+ -do-jar-without-manifest: JAR building (if you are not using a manifest)
+ run: execution of project
+ -javadoc-build: Javadoc generation
+ test-report: JUnit report generation
+
+ An example of overriding the target for project execution could look like this:
+
+ <target name="run" depends="jdwpgen-impl.jar">
+ <exec dir="bin" executable="launcher.exe">
+ <arg file="${dist.jar}"/>
+ </exec>
+ </target>
+
+ Notice that the overridden target depends on the jar target and not only on
+ the compile target as the regular run target does. Again, for a list of available
+ properties which you can use, check the target you are overriding in the
+ nbproject/build-impl.xml file.
+
+ -->
+</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/build-impl.xml Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,642 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT ***
+*** EDIT ../build.xml INSTEAD ***
+
+For the purpose of easier reading the script
+is divided into following sections:
+
+ - initialization
+ - compilation
+ - jar
+ - execution
+ - debugging
+ - javadoc
+ - junit compilation
+ - junit execution
+ - junit debugging
+ - applet
+ - cleanup
+
+ -->
+<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="jdwpgen-impl">
+ <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
+ <!--
+ ======================
+ INITIALIZATION SECTION
+ ======================
+ -->
+ <target name="-pre-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init" name="-init-private">
+ <property file="nbproject/private/config.properties"/>
+ <property file="nbproject/private/configs/${config}.properties"/>
+ <property file="nbproject/private/private.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private" name="-init-user">
+ <property file="${user.properties.file}"/>
+ <!-- The two properties below are usually overridden -->
+ <!-- by the active platform. Just a fallback. -->
+ <property name="default.javac.source" value="1.4"/>
+ <property name="default.javac.target" value="1.4"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user" name="-init-project">
+ <property file="nbproject/configs/${config}.properties"/>
+ <property file="nbproject/project.properties"/>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
+ <available file="${manifest.file}" property="manifest.available"/>
+ <condition property="manifest.available+main.class">
+ <and>
+ <isset property="manifest.available"/>
+ <isset property="main.class"/>
+ <not>
+ <equals arg1="${main.class}" arg2="" trim="true"/>
+ </not>
+ </and>
+ </condition>
+ <condition property="manifest.available+main.class+mkdist.available">
+ <and>
+ <istrue value="${manifest.available+main.class}"/>
+ <isset property="libs.CopyLibs.classpath"/>
+ </and>
+ </condition>
+ <condition property="have.tests">
+ <or>
+ <available file="${test.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="have.sources">
+ <or>
+ <available file="${src.src.dir}"/>
+ </or>
+ </condition>
+ <condition property="netbeans.home+have.tests">
+ <and>
+ <isset property="netbeans.home"/>
+ <isset property="have.tests"/>
+ </and>
+ </condition>
+ <condition property="no.javadoc.preview">
+ <and>
+ <isset property="javadoc.preview"/>
+ <isfalse value="${javadoc.preview}"/>
+ </and>
+ </condition>
+ <property name="run.jvmargs" value=""/>
+ <property name="javac.compilerargs" value=""/>
+ <property name="work.dir" value="${basedir}"/>
+ <condition property="no.deps">
+ <and>
+ <istrue value="${no.dependencies}"/>
+ </and>
+ </condition>
+ <property name="javac.debug" value="true"/>
+ <property name="javadoc.preview" value="true"/>
+ <property name="application.args" value=""/>
+ <property name="source.encoding" value="${file.encoding}"/>
+ <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
+ <and>
+ <isset property="javadoc.encoding"/>
+ <not>
+ <equals arg1="${javadoc.encoding}" arg2=""/>
+ </not>
+ </and>
+ </condition>
+ <property name="javadoc.encoding.used" value="${source.encoding}"/>
+ <property name="includes" value="**"/>
+ <property name="excludes" value=""/>
+ <property name="do.depend" value="false"/>
+ <condition property="do.depend.true">
+ <istrue value="${do.depend}"/>
+ </condition>
+ <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
+ <and>
+ <isset property="jaxws.endorsed.dir"/>
+ <available file="nbproject/jaxws-build.xml"/>
+ </and>
+ </condition>
+ </target>
+ <target name="-post-init">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+ <fail unless="src.src.dir">Must set src.src.dir</fail>
+ <fail unless="test.src.dir">Must set test.src.dir</fail>
+ <fail unless="build.dir">Must set build.dir</fail>
+ <fail unless="dist.dir">Must set dist.dir</fail>
+ <fail unless="build.classes.dir">Must set build.classes.dir</fail>
+ <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
+ <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
+ <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
+ <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
+ <fail unless="dist.jar">Must set dist.jar</fail>
+ </target>
+ <target name="-init-macrodef-property">
+ <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <sequential>
+ <property name="@{name}" value="${@{value}}"/>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-javac">
+ <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="${javac.debug}" name="debug"/>
+ <attribute default="/does/not/exist" name="sourcepath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
+ <customize/>
+ </javac>
+ </sequential>
+ </macrodef>
+ <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${src.src.dir}" name="srcdir"/>
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <attribute default="${javac.classpath}" name="classpath"/>
+ <sequential>
+ <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </depend>
+ </sequential>
+ </macrodef>
+ <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${build.classes.dir}" name="destdir"/>
+ <sequential>
+ <fail unless="javac.includes">Must set javac.includes</fail>
+ <pathconvert pathsep="," property="javac.includes.binary">
+ <path>
+ <filelist dir="@{destdir}" files="${javac.includes}"/>
+ </path>
+ <globmapper from="*.java" to="*.class"/>
+ </pathconvert>
+ <delete>
+ <files includes="${javac.includes.binary}"/>
+ </delete>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-junit">
+ <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${includes}" name="includes"/>
+ <attribute default="${excludes}" name="excludes"/>
+ <attribute default="**" name="testincludes"/>
+ <sequential>
+ <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
+ <batchtest todir="${build.test.results.dir}">
+ <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
+ <filename name="@{testincludes}"/>
+ </fileset>
+ </batchtest>
+ <classpath>
+ <path path="${run.test.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <formatter type="brief" usefile="false"/>
+ <formatter type="xml"/>
+ <jvmarg line="${run.jvmargs}"/>
+ </junit>
+ </sequential>
+ </macrodef>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
+ <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="name"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <attribute default="" name="stopclassname"/>
+ <sequential>
+ <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ </nbjpdastart>
+ </sequential>
+ </macrodef>
+ <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${build.classes.dir}" name="dir"/>
+ <sequential>
+ <nbjpdareload>
+ <fileset dir="@{dir}" includes="${fix.classes}">
+ <include name="${fix.includes}*.class"/>
+ </fileset>
+ </nbjpdareload>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-debug-args">
+ <property name="version-output" value="java version "${ant.java.version}"/>
+ <condition property="have-jdk-older-than-1.4">
+ <or>
+ <contains string="${version-output}" substring="java version "1.0"/>
+ <contains string="${version-output}" substring="java version "1.1"/>
+ <contains string="${version-output}" substring="java version "1.2"/>
+ <contains string="${version-output}" substring="java version "1.3"/>
+ </or>
+ </condition>
+ <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
+ <istrue value="${have-jdk-older-than-1.4}"/>
+ </condition>
+ <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
+ <os family="windows"/>
+ </condition>
+ <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
+ <isset property="debug.transport"/>
+ </condition>
+ </target>
+ <target depends="-init-debug-args" name="-init-macrodef-debug">
+ <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
+ <attribute default="${main.class}" name="classname"/>
+ <attribute default="${debug.classpath}" name="classpath"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${debug-args-line}"/>
+ <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
+ <jvmarg line="${run.jvmargs}"/>
+ <classpath>
+ <path path="@{classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-macrodef-java">
+ <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <attribute default="${main.class}" name="classname"/>
+ <element name="customize" optional="true"/>
+ <sequential>
+ <java classname="@{classname}" dir="${work.dir}" fork="true">
+ <jvmarg line="${run.jvmargs}"/>
+ <classpath>
+ <path path="${run.classpath}"/>
+ </classpath>
+ <syspropertyset>
+ <propertyref prefix="run-sys-prop."/>
+ <mapper from="run-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <customize/>
+ </java>
+ </sequential>
+ </macrodef>
+ </target>
+ <target name="-init-presetdef-jar">
+ <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
+ <jar compress="${jar.compress}" jarfile="${dist.jar}">
+ <j2seproject1:fileset dir="${build.classes.dir}"/>
+ </jar>
+ </presetdef>
+ </target>
+ <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
+ <!--
+ ===================
+ COMPILATION SECTION
+ ===================
+ -->
+ <target depends="init" name="deps-jar" unless="no.deps"/>
+ <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
+ <target depends="init" name="-check-automatic-build">
+ <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
+ </target>
+ <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
+ <antcall target="clean"/>
+ </target>
+ <target depends="init,deps-jar" name="-pre-pre-compile">
+ <mkdir dir="${build.classes.dir}"/>
+ </target>
+ <target name="-pre-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-depend">
+ <j2seproject3:depend/>
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
+ <j2seproject3:javac/>
+ <copy todir="${build.classes.dir}">
+ <fileset dir="${src.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
+ <target name="-pre-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile/>
+ <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.src.dir}"/>
+ </target>
+ <target name="-post-compile-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
+ <!--
+ ====================
+ JAR BUILDING SECTION
+ ====================
+ -->
+ <target depends="init" name="-pre-pre-jar">
+ <dirname file="${dist.jar}" property="dist.jar.dir"/>
+ <mkdir dir="${dist.jar.dir}"/>
+ </target>
+ <target name="-pre-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
+ <j2seproject1:jar/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
+ <j2seproject1:jar manifest="${manifest.file}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
+ <j2seproject1:jar manifest="${manifest.file}">
+ <j2seproject1:manifest>
+ <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
+ </j2seproject1:manifest>
+ </j2seproject1:jar>
+ <echo>To run this application from the command line without Ant, try:</echo>
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <pathconvert property="run.classpath.with.dist.jar">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
+ </pathconvert>
+ <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
+ </target>
+ <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
+ <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
+ <pathconvert property="run.classpath.without.build.classes.dir">
+ <path path="${run.classpath}"/>
+ <map from="${build.classes.dir.resolved}" to=""/>
+ </pathconvert>
+ <pathconvert pathsep=" " property="jar.classpath">
+ <path path="${run.classpath.without.build.classes.dir}"/>
+ <chainedmapper>
+ <flattenmapper/>
+ <globmapper from="*" to="lib/*"/>
+ </chainedmapper>
+ </pathconvert>
+ <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
+ <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
+ <fileset dir="${build.classes.dir}"/>
+ <manifest>
+ <attribute name="Main-Class" value="${main.class}"/>
+ <attribute name="Class-Path" value="${jar.classpath}"/>
+ </manifest>
+ </copylibs>
+ <echo>To run this application from the command line without Ant, try:</echo>
+ <property location="${dist.jar}" name="dist.jar.resolved"/>
+ <echo>java -jar "${dist.jar.resolved}"</echo>
+ </target>
+ <target name="-post-jar">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
+ <!--
+ =================
+ EXECUTION SECTION
+ =================
+ -->
+ <target depends="init,compile" description="Run a main class." name="run">
+ <j2seproject1:java>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <target name="-do-not-recompile">
+ <property name="javac.includes.binary" value=""/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-single" name="run-single">
+ <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
+ <j2seproject1:java classname="${run.class}"/>
+ </target>
+ <!--
+ =================
+ DEBUGGING SECTION
+ =================
+ -->
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger">
+ <j2seproject1:nbjpdastart name="${debug.class}"/>
+ </target>
+ <target depends="init,compile" name="-debug-start-debuggee">
+ <j2seproject3:debug>
+ <customize>
+ <arg line="${application.args}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
+ <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
+ <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
+ </target>
+ <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
+ <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
+ <j2seproject3:debug classname="${debug.class}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
+ <target depends="init" name="-pre-debug-fix">
+ <fail unless="fix.includes">Must set fix.includes</fail>
+ <property name="javac.includes" value="${fix.includes}.java"/>
+ </target>
+ <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
+ <j2seproject1:nbjpdareload/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
+ <!--
+ ===============
+ JAVADOC SECTION
+ ===============
+ -->
+ <target depends="init" name="-javadoc-build">
+ <mkdir dir="${dist.javadoc.dir}"/>
+ <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
+ <classpath>
+ <path path="${javac.classpath}"/>
+ </classpath>
+ <fileset dir="${src.src.dir}" excludes="${excludes}" includes="${includes}">
+ <filename name="**/*.java"/>
+ </fileset>
+ </javadoc>
+ </target>
+ <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
+ <nbbrowse file="${dist.javadoc.dir}/index.html"/>
+ </target>
+ <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
+ <!--
+ =========================
+ JUNIT COMPILATION SECTION
+ =========================
+ -->
+ <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
+ <mkdir dir="${build.test.classes.dir}"/>
+ </target>
+ <target name="-pre-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target if="do.depend.true" name="-compile-test-depend">
+ <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
+ <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
+ <target name="-pre-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
+ <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
+ <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
+ <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
+ <copy todir="${build.test.classes.dir}">
+ <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
+ </copy>
+ </target>
+ <target name="-post-compile-test-single">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
+ <!--
+ =======================
+ JUNIT EXECUTION SECTION
+ =======================
+ -->
+ <target depends="init" if="have.tests" name="-pre-test-run">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
+ <j2seproject3:junit testincludes="**/*Test.java"/>
+ </target>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
+ <fail if="tests.failed">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init" if="have.tests" name="test-report"/>
+ <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
+ <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
+ <target depends="init" if="have.tests" name="-pre-test-run-single">
+ <mkdir dir="${build.test.results.dir}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
+ <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
+ <j2seproject3:junit excludes="" includes="${test.includes}"/>
+ </target>
+ <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
+ <fail if="tests.failed">Some tests failed; see details above.</fail>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
+ <!--
+ =======================
+ JUNIT DEBUGGING SECTION
+ =======================
+ -->
+ <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
+ <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
+ <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
+ <delete file="${test.report.file}"/>
+ <mkdir dir="${build.test.results.dir}"/>
+ <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
+ <customize>
+ <syspropertyset>
+ <propertyref prefix="test-sys-prop."/>
+ <mapper from="test-sys-prop.*" to="*" type="glob"/>
+ </syspropertyset>
+ <arg value="${test.class}"/>
+ <arg value="showoutput=true"/>
+ <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
+ <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
+ <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
+ </target>
+ <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
+ <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
+ <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
+ </target>
+ <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
+ <!--
+ =========================
+ APPLET EXECUTION SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" name="run-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject1:java classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject1:java>
+ </target>
+ <!--
+ =========================
+ APPLET DEBUGGING SECTION
+ =========================
+ -->
+ <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
+ <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
+ <j2seproject3:debug classname="sun.applet.AppletViewer">
+ <customize>
+ <arg value="${applet.url}"/>
+ </customize>
+ </j2seproject3:debug>
+ </target>
+ <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
+ <!--
+ ===============
+ CLEANUP SECTION
+ ===============
+ -->
+ <target depends="init" name="deps-clean" unless="no.deps"/>
+ <target depends="init" name="-do-clean">
+ <delete dir="${build.dir}"/>
+ <delete dir="${dist.dir}"/>
+ </target>
+ <target name="-post-clean">
+ <!-- Empty placeholder for easier customization. -->
+ <!-- You can override this target in the ../build.xml file. -->
+ </target>
+ <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
+</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/findbugs.settings Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,72 @@
+#FindBugs User Preferences
+#Mon Jun 15 13:37:16 PDT 2009
+detectorAbnormalFinallyBlockReturn=AbnormalFinallyBlockReturn|false
+detectorAbstractClassEmptyMethods=AbstractClassEmptyMethods|false
+detectorAbstractOverriddenMethod=AbstractOverriddenMethod|false
+detectorArrayBasedCollections=ArrayBasedCollections|false
+detectorArrayWrappedCallByReference=ArrayWrappedCallByReference|false
+detectorBloatedAssignmentScope=BloatedAssignmentScope|false
+detectorBloatedSynchronizedBlock=BloatedSynchronizedBlock|false
+detectorClassEnvy=ClassEnvy|false
+detectorCollectStatistics=CollectStatistics|false
+detectorConfusingAutoboxedOverloading=ConfusingAutoboxedOverloading|false
+detectorConstantListIndex=ConstantListIndex|false
+detectorCopiedOverriddenMethod=CopiedOverriddenMethod|false
+detectorCustomBuiltXML=CustomBuiltXML|false
+detectorCyclomaticComplexity=CyclomaticComplexity|false
+detectorDateComparison=DateComparison|false
+detectorDeclaredRuntimeException=DeclaredRuntimeException|false
+detectorDeletingWhileIterating=DeletingWhileIterating|false
+detectorDubiousListCollection=DubiousListCollection|false
+detectorFieldCouldBeLocal=FieldCouldBeLocal|false
+detectorFinalParameters=FinalParameters|false
+detectorFloatingPointLoops=FloatingPointLoops|false
+detectorInefficientStringBuffering=InefficientStringBuffering|false
+detectorInheritanceTypeChecking=InheritanceTypeChecking|false
+detectorJDBCVendorReliance=JDBCVendorReliance|false
+detectorListIndexedIterating=ListIndexedIterating|false
+detectorLiteralStringComparison=LiteralStringComparison|false
+detectorLocalSynchronizedCollection=LocalSynchronizedCollection|false
+detectorLostExceptionStackTrace=LostExceptionStackTrace|false
+detectorManualArrayCopy=ManualArrayCopy|false
+detectorMethodReturnsConstant=MethodReturnsConstant|false
+detectorNeedlessAutoboxing=NeedlessAutoboxing|false
+detectorNeedlessCustomSerialization=NeedlessCustomSerialization|false
+detectorNeedlessInstanceRetrieval=NeedlessInstanceRetrieval|false
+detectorNeedlessMemberCollectionSynchronization=NeedlessMemberCollectionSynchronization|false
+detectorNonCollectionMethodUse=NonCollectionMethodUse|false
+detectorNonOwnedSynchronization=NonOwnedSynchronization|false
+detectorNonRecycleableTaglibs=NonRecycleableTaglibs|false
+detectorOrphanedDOMNode=OrphanedDOMNode|false
+detectorOverlyConcreteParameter=OverlyConcreteParameter|false
+detectorParallelLists=ParallelLists|false
+detectorPartiallyConstructedObjectAccess=PartiallyConstructedObjectAccess|false
+detectorPossibleIncompleteSerialization=PossibleIncompleteSerialization|false
+detectorPossibleMemoryBloat=PossibleMemoryBloat|false
+detectorPossiblyRedundantMethodCalls=PossiblyRedundantMethodCalls|false
+detectorSQLInLoop=SQLInLoop|false
+detectorSection508Compliance=Section508Compliance|false
+detectorSillynessPotPourri=SillynessPotPourri|false
+detectorSloppyClassReflection=SloppyClassReflection|false
+detectorSluggishGui=SluggishGui|false
+detectorSpoiledChildInterfaceImplementor=SpoiledChildInterfaceImplementor|false
+detectorSpuriousThreadStates=SpuriousThreadStates|false
+detectorStaticArrayCreatedInMethod=StaticArrayCreatedInMethod|false
+detectorStaticMethodInstanceInvocation=StaticMethodInstanceInvocation|false
+detectorSuspiciousComparatorReturnValues=SuspiciousComparatorReturnValues|false
+detectorSuspiciousJDKVersionUse=SuspiciousJDKVersionUse|false
+detectorSuspiciousWaitOnConcurrentObject=SuspiciousWaitOnConcurrentObject|false
+detectorSyncCollectionIterators=SyncCollectionIterators|false
+detectorTailRecursion=TailRecursion|false
+detectorUnnecessaryStoreBeforeReturn=UnnecessaryStoreBeforeReturn|false
+detectorUnrelatedCollectionContents=UnrelatedCollectionContents|false
+detectorUnrelatedReturnValues=UnrelatedReturnValues|false
+detectorUseAddAll=UseAddAll|false
+detectorUseCharacterParameterizedMethod=UseCharacterParameterizedMethod|false
+detectorUseEnumCollections=UseEnumCollections|false
+detectorUseSplit=UseSplit|false
+detectorUseToArray=UseToArray|false
+detector_threshold=2
+effort=default
+filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false
+filter_settings_neg=|
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/genfiles.properties Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=b40e775f
+build.xml.script.CRC32=af8dc3cb
+build.xml.stylesheet.CRC32=958a1d3e
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=b40e775f
+nbproject/build-impl.xml.script.CRC32=624d12c5
+nbproject/build-impl.xml.stylesheet.CRC32=65b8de21
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/project.properties Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,65 @@
+application.title=jdwpgen
+application.vendor=sun
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/jdwpgen.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+file.reference.tools-jdwpgen=../../tools/src/build/tools/jdwpgen
+file.reference.tools-src=../../tools/src
+includes=build/tools/jdwpgen/**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=-Xlint:all
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=true
+javadoc.nonavbar=true
+javadoc.notree=true
+javadoc.private=true
+javadoc.splitindex=false
+javadoc.use=false
+javadoc.version=false
+javadoc.windowtitle=
+main.class=jdwpgen.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.src.dir=${file.reference.tools-src}
+test.src.dir=test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/project.xml Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.java.j2seproject</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
+ <name>jdwpgen</name>
+ <minimum-ant-version>1.6.5</minimum-ant-version>
+ <source-roots>
+ <root id="src.src.dir"/>
+ </source-roots>
+ <test-roots>
+ <root id="test.src.dir"/>
+ </test-roots>
+ </data>
+ </configuration>
+</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/netbeans/jdwpgen/nbproject/sqe.properties Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,2 @@
+#Path to FindbugsSettingsFile (relative)
+findbugs.settings.file=findbugs.settings
--- a/jdk/make/tools/src/build/tools/jdwpgen/AbstractNamedNode.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/AbstractNamedNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,7 +30,7 @@
abstract class AbstractNamedNode extends Node {
- NameNode nameNode;
+ NameNode nameNode = null;
String name;
public String name() {
--- a/jdk/make/tools/src/build/tools/jdwpgen/AltNode.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/AltNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,7 +30,7 @@
class AltNode extends AbstractGroupNode implements TypeNode {
- SelectNode select;
+ SelectNode select = null;
void constrain(Context ctx) {
super.constrain(ctx);
--- a/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/ConstantSetNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -33,13 +33,7 @@
/**
* The mapping between a constant and its value.
*/
- protected static Map<String, String> constantMap;
-
- ConstantSetNode(){
- if (constantMap == null) {
- constantMap = new HashMap<String, String>();
- }
- }
+ protected static final Map<String, String> constantMap = new HashMap<String, String>();
void prune() {
List<Node> addons = new ArrayList<Node>();
@@ -95,9 +89,6 @@
}
public static String getConstant(String key){
- if (constantMap == null) {
- return "";
- }
String com = constantMap.get(key);
if(com == null){
return "";
--- a/jdk/make/tools/src/build/tools/jdwpgen/Main.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/Main.java Mon Aug 24 22:27:30 2009 -0700
@@ -25,13 +25,11 @@
package build.tools.jdwpgen;
-import java.util.*;
import java.io.*;
class Main {
static String specSource;
- static Map nameMap = new HashMap();
static boolean genDebug = true;
static void usage() {
@@ -43,7 +41,6 @@
System.err.println("-doc <doc_output>");
System.err.println("-jdi <java_output>");
System.err.println("-include <include_file_output>");
- System.exit(1);
}
public static void main(String args[]) throws IOException {
@@ -66,6 +63,7 @@
} else {
System.err.println("Invalid option: " + arg);
usage();
+ return;
}
} else {
specSource = arg;
@@ -75,6 +73,7 @@
if (reader == null) {
System.err.println("<spec_input> must be specified");
usage();
+ return;
}
Parse parse = new Parse(reader);
--- a/jdk/make/tools/src/build/tools/jdwpgen/Node.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/Node.java Mon Aug 24 22:27:30 2009 -0700
@@ -36,7 +36,7 @@
int lineno;
List<String> commentList = new ArrayList<String>();
Node parent = null;
- Context context;
+ Context context = null;
static final int maxStructIndent = 5;
static int structIndent = 0; // horrible hack
@@ -82,7 +82,7 @@
}
void indent(PrintWriter writer, int depth) {
- for (int i = depth; i > 0; --i) {
+ for (int i = 0; i < depth; i++) {
writer.print(" ");
}
}
@@ -195,6 +195,6 @@
System.err.println(Main.specSource + ":" + lineno + ": " +
kind + " - " + errmsg);
System.err.println();
- System.exit(1);
+ throw new RuntimeException("Error: " + errmsg);
}
}
--- a/jdk/make/tools/src/build/tools/jdwpgen/Parse.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/Parse.java Mon Aug 24 22:27:30 2009 -0700
@@ -146,8 +146,12 @@
Node node = (Node)proto.getClass().newInstance();
node.set(kind, list, izer.lineno());
return node;
- } catch (Exception exc) {
+ } catch (InstantiationException exc) {
error(exc.toString());
+ return null;
+ } catch (IllegalAccessException exc) {
+ error(exc.toString());
+ return null;
}
}
} else {
@@ -166,6 +170,6 @@
void error(String errmsg) {
System.err.println(Main.specSource + ":" + izer.lineno() +
": " + errmsg);
- System.exit(1);
+ throw new RuntimeException("Error: " + errmsg);
}
}
--- a/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/RepeatNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,7 +30,7 @@
class RepeatNode extends AbstractTypeNode {
- Node member;
+ Node member = null;
void constrain(Context ctx) {
super.constrain(ctx);
--- a/jdk/make/tools/src/build/tools/jdwpgen/SelectNode.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/make/tools/src/build/tools/jdwpgen/SelectNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,7 +30,7 @@
class SelectNode extends AbstractGroupNode implements TypeNode {
- AbstractSimpleTypeNode typeNode;
+ AbstractSimpleTypeNode typeNode = null;
void prune() {
super.prune();
--- a/jdk/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/com/sun/security/auth/callback/TextCallbackHandler.java Mon Aug 24 22:27:30 2009 -0700
@@ -129,7 +129,7 @@
System.err.print(pc.getPrompt());
System.err.flush();
- pc.setPassword(Password.readPassword(System.in));
+ pc.setPassword(Password.readPassword(System.in, pc.isEchoOn()));
} else if (callbacks[i] instanceof ConfirmationCallback) {
confirmation = (ConfirmationCallback) callbacks[i];
--- a/jdk/src/share/classes/com/sun/security/sasl/Provider.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/com/sun/security/sasl/Provider.java Mon Aug 24 22:27:30 2009 -0700
@@ -51,7 +51,7 @@
" server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
public Provider() {
- super("SunSASL", 1.5, info);
+ super("SunSASL", 1.7d, info);
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
--- a/jdk/src/share/classes/java/lang/EnumConstantNotPresentException.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/EnumConstantNotPresentException.java Mon Aug 24 22:27:30 2009 -0700
@@ -28,8 +28,12 @@
/**
* Thrown when an application tries to access an enum constant by name
* and the enum type contains no constant with the specified name.
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
*
* @author Josh Bloch
+ * @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class EnumConstantNotPresentException extends RuntimeException {
--- a/jdk/src/share/classes/java/lang/String.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Mon Aug 24 22:27:30 2009 -0700
@@ -2301,6 +2301,54 @@
* @spec JSR-51
*/
public String[] split(String regex, int limit) {
+ /* fastpath if the regex is a
+ (1)one-char String and this character is not one of the
+ RegEx's meta characters ".$|()[{^?*+\\", or
+ (2)two-char String and the first char is the backslash and
+ the second is not the ascii digit or ascii letter.
+ */
+ char ch = 0;
+ if (((regex.count == 1 &&
+ ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
+ (regex.length() == 2 &&
+ regex.charAt(0) == '\\' &&
+ (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
+ ((ch-'a')|('z'-ch)) < 0 &&
+ ((ch-'A')|('Z'-ch)) < 0)) &&
+ (ch < Character.MIN_HIGH_SURROGATE ||
+ ch > Character.MAX_LOW_SURROGATE))
+ {
+ int off = 0;
+ int next = 0;
+ boolean limited = limit > 0;
+ ArrayList<String> list = new ArrayList<String>();
+ while ((next = indexOf(ch, off)) != -1) {
+ if (!limited || list.size() < limit - 1) {
+ list.add(substring(off, next));
+ off = next + 1;
+ } else { // last one
+ //assert (list.size() == limit - 1);
+ list.add(substring(off, count));
+ off = count;
+ break;
+ }
+ }
+ // If no match was found, return this
+ if (off == 0)
+ return new String[] { this };
+
+ // Add remaining segment
+ if (!limited || list.size() < limit)
+ list.add(substring(off, count));
+
+ // Construct result
+ int resultSize = list.size();
+ if (limit == 0)
+ while (resultSize > 0 && list.get(resultSize-1).length() == 0)
+ resultSize--;
+ String[] result = new String[resultSize];
+ return list.subList(0, resultSize).toArray(result);
+ }
return Pattern.compile(regex).split(this, limit);
}
--- a/jdk/src/share/classes/java/lang/TypeNotPresentException.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/TypeNotPresentException.java Mon Aug 24 22:27:30 2009 -0700
@@ -35,8 +35,12 @@
* <p>Note that this exception may be used when undefined type variables
* are accessed as well as when types (e.g., classes, interfaces or
* annotation types) are loaded.
+ * In particular, this exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
*
* @author Josh Bloch
+ * @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class TypeNotPresentException extends RuntimeException {
--- a/jdk/src/share/classes/java/lang/annotation/AnnotationFormatError.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/annotation/AnnotationFormatError.java Mon Aug 24 22:27:30 2009 -0700
@@ -28,8 +28,12 @@
/**
* Thrown when the annotation parser attempts to read an annotation
* from a class file and determines that the annotation is malformed.
+ * This error can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
*
* @author Josh Bloch
+ * @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationFormatError extends Error {
--- a/jdk/src/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,8 +30,12 @@
* Thrown to indicate that a program has attempted to access an element of
* an annotation whose type has changed after the annotation was compiled
* (or serialized).
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
*
* @author Josh Bloch
+ * @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationTypeMismatchException extends RuntimeException {
--- a/jdk/src/share/classes/java/lang/annotation/IncompleteAnnotationException.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/annotation/IncompleteAnnotationException.java Mon Aug 24 22:27:30 2009 -0700
@@ -30,8 +30,12 @@
* an annotation type that was added to the annotation type definition after
* the annotation was compiled (or serialized). This exception will not be
* thrown if the new element has a default value.
+ * This exception can be thrown by the {@linkplain
+ * java.lang.reflect.AnnotatedElement API used to read annotations
+ * reflectively}.
*
* @author Josh Bloch
+ * @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class IncompleteAnnotationException extends RuntimeException {
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Mon Aug 24 22:27:30 2009 -0700
@@ -50,6 +50,11 @@
* java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}.
*
+ * @see java.lang.EnumConstantNotPresentException
+ * @see java.lang.TypeNotPresentException
+ * @see java.lang.annotation.AnnotationFormatError
+ * @see java.lang.annotation.AnnotationTypeMismatchException
+ * @see java.lang.annotation.IncompleteAnnotationException
* @since 1.5
* @author Josh Bloch
*/
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -56,18 +56,18 @@
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
- * <p> This method initiates an operation to read a sequence of bytes from
- * this channel into the given buffer. The method returns a {@link Future}
- * representing the pending result of the operation. The result of the
- * operation, obtained by invoking the {@code Future} 's {@link
- * Future#get() get} method, is the number of bytes read or {@code -1} if
- * all bytes have been read and the channel has reached end-of-stream.
+ * <p> This method initiates an asynchronous read operation to read a
+ * sequence of bytes from this channel into the given buffer. The {@code
+ * handler} parameter is a completion handler that is invoked when the read
+ * operation completes (or fails). The result passed to the completion
+ * handler is the number of bytes read or {@code -1} if no bytes could be
+ * read because the channel has reached end-of-stream.
*
- * <p> This method initiates a read operation to read up to <i>r</i> bytes
- * from the channel, where <i>r</i> is the number of bytes remaining in the
- * buffer, that is, {@code dst.remaining()} at the time that the read is
- * attempted. Where <i>r</i> is 0, the read operation completes immediately
- * with a result of {@code 0} without initiating an I/O operation.
+ * <p> The read operation may read up to <i>r</i> bytes from the channel,
+ * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+ * {@code dst.remaining()} at the time that the read is attempted. Where
+ * <i>r</i> is 0, the read operation completes immediately with a result of
+ * {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is read, where
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
@@ -79,44 +79,46 @@
* <i>p</i> <tt>+</tt> <i>n</i>; its limit will not have changed.
*
* <p> Buffers are not safe for use by multiple concurrent threads so care
- * should be taken to not to access the buffer until the operaton has completed.
+ * should be taken to not access the buffer until the operation has
+ * completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one read to be outstanding at any given time. If a thread
* initiates a read operation before a previous read operation has
* completed then a {@link ReadPendingException} will be thrown.
*
- * <p> The <tt>handler</tt> parameter is used to specify a {@link
- * CompletionHandler}. When the read operation completes the handler's
- * {@link CompletionHandler#completed completed} method is executed.
- *
- *
* @param dst
* The buffer into which bytes are to be transferred
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The completion handler object; can be {@code null}
- *
- * @return A Future representing the result of the operation
+ * The completion handler
*
* @throws IllegalArgumentException
* If the buffer is read-only
* @throws ReadPendingException
* If the channel does not allow more than one read to be outstanding
* and a previous read has not completed
+ * @throws ShutdownChannelGroupException
+ * If the channel is associated with a {@link AsynchronousChannelGroup
+ * group} that has terminated
*/
- <A> Future<Integer> read(ByteBuffer dst,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ <A> void read(ByteBuffer dst,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
- * <p> An invocation of this method of the form <tt>c.read(dst)</tt>
- * behaves in exactly the same manner as the invocation
- * <blockquote><pre>
- * c.read(dst, null, null);</pre></blockquote>
+ * <p> This method initiates an asynchronous read operation to read a
+ * sequence of bytes from this channel into the given buffer. The method
+ * behaves in exactly the same manner as the {@link
+ * #read(ByteBuffer,Object,CompletionHandler)
+ * read(ByteBuffer,Object,CompletionHandler)} method except that instead
+ * of specifying a completion handler, this method returns a {@code Future}
+ * representing the pending result. The {@code Future}'s {@link Future#get()
+ * get} method returns the number of bytes read or {@code -1} if no bytes
+ * could be read because the channel has reached end-of-stream.
*
* @param dst
* The buffer into which bytes are to be transferred
@@ -134,17 +136,17 @@
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
- * <p> This method initiates an operation to write a sequence of bytes to
- * this channel from the given buffer. This method returns a {@link
- * Future} representing the pending result of the operation. The result
- * of the operation, obtained by invoking the <tt>Future</tt>'s {@link
- * Future#get() get} method, is the number of bytes written, possibly zero.
+ * <p> This method initiates an asynchronous write operation to write a
+ * sequence of bytes to this channel from the given buffer. The {@code
+ * handler} parameter is a completion handler that is invoked when the write
+ * operation completes (or fails). The result passed to the completion
+ * handler is the number of bytes written.
*
- * <p> This method initiates a write operation to write up to <i>r</i> bytes
- * to the channel, where <i>r</i> is the number of bytes remaining in the
- * buffer, that is, {@code src.remaining()} at the moment the write is
- * attempted. Where <i>r</i> is 0, the write operation completes immediately
- * with a result of {@code 0} without initiating an I/O operation.
+ * <p> The write operation may write up to <i>r</i> bytes to the channel,
+ * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+ * {@code src.remaining()} at the time that the write is attempted. Where
+ * <i>r</i> is 0, the write operation completes immediately with a result of
+ * {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is written, where
* <tt>0</tt> <tt><</tt> <i>n</i> <tt><=</tt> <i>r</i>.
@@ -156,41 +158,43 @@
* <i>p</i> <tt>+</tt> <i>n</i>; its limit will not have changed.
*
* <p> Buffers are not safe for use by multiple concurrent threads so care
- * should be taken to not to access the buffer until the operaton has completed.
+ * should be taken to not access the buffer until the operation has
+ * completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one write to be outstanding at any given time. If a thread
* initiates a write operation before a previous write operation has
* completed then a {@link WritePendingException} will be thrown.
*
- * <p> The <tt>handler</tt> parameter is used to specify a {@link
- * CompletionHandler}. When the write operation completes the handler's
- * {@link CompletionHandler#completed completed} method is executed.
- *
* @param src
* The buffer from which bytes are to be retrieved
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The completion handler object; can be {@code null}
- *
- * @return A Future representing the result of the operation
+ * The completion handler object
*
* @throws WritePendingException
* If the channel does not allow more than one write to be outstanding
* and a previous write has not completed
+ * @throws ShutdownChannelGroupException
+ * If the channel is associated with a {@link AsynchronousChannelGroup
+ * group} that has terminated
*/
- <A> Future<Integer> write(ByteBuffer src,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ <A> void write(ByteBuffer src,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
- * <p> An invocation of this method of the form <tt>c.write(src)</tt>
- * behaves in exactly the same manner as the invocation
- * <blockquote><pre>
- * c.write(src, null, null);</pre></blockquote>
+ * <p> This method initiates an asynchronous write operation to write a
+ * sequence of bytes to this channel from the given buffer. The method
+ * behaves in exactly the same manner as the {@link
+ * #write(ByteBuffer,Object,CompletionHandler)
+ * write(ByteBuffer,Object,CompletionHandler)} method except that instead
+ * of specifying a completion handler, this method returns a {@code Future}
+ * representing the pending result. The {@code Future}'s {@link Future#get()
+ * get} method returns the number of bytes written.
*
* @param src
* The buffer from which bytes are to be retrieved
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -34,7 +34,8 @@
*
* <ol>
* <li><pre>{@link Future}<V> <em>operation</em>(<em>...</em>)</pre></li>
- * <li><pre>Future<V> <em>operation</em>(<em>...</em> A attachment, {@link CompletionHandler}<V,? super A> handler)</pre></li>
+ * <li><pre>void <em>operation</em>(<em>...</em> A attachment, {@link
+ * CompletionHandler}<V,? super A> handler)</pre></li>
* </ol>
*
* where <i>operation</i> is the name of the I/O operation (read or write for
@@ -48,7 +49,7 @@
* interface may be used to check if the operation has completed, wait for its
* completion, and to retrieve the result. In the second form, a {@link
* CompletionHandler} is invoked to consume the result of the I/O operation when
- * it completes, fails, or is cancelled.
+ * it completes or fails.
*
* <p> A channel that implements this interface is <em>asynchronously
* closeable</em>: If an I/O operation is outstanding on the channel and the
@@ -63,33 +64,33 @@
* <h4>Cancellation</h4>
*
* <p> The {@code Future} interface defines the {@link Future#cancel cancel}
- * method to cancel execution of a task.
- *
- * <p> Where the {@code cancel} method is invoked with the {@code
- * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
- * may be interrupted by closing the channel. This will cause any other I/O
- * operations outstanding on the channel to complete with the exception {@link
- * AsynchronousCloseException}.
+ * method to cancel execution. This causes all threads waiting on the result of
+ * the I/O operation to throw {@link java.util.concurrent.CancellationException}.
+ * Whether the underlying I/O operation can be cancelled is highly implementation
+ * specific and therefore not specified. Where cancellation leaves the channel,
+ * or the entity to which it is connected, in an inconsistent state, then the
+ * channel is put into an implementation specific <em>error state</em> that
+ * prevents further attempts to initiate I/O operations that are <i>similar</i>
+ * to the operation that was cancelled. For example, if a read operation is
+ * cancelled but the implementation cannot guarantee that bytes have not been
+ * read from the channel then it puts the channel into an error state; further
+ * attempts to initiate a {@code read} operation cause an unspecified runtime
+ * exception to be thrown. Similarly, if a write operation is cancelled but the
+ * implementation cannot guarantee that bytes have not been written to the
+ * channel then subsequent attempts to initiate a {@code write} will fail with
+ * an unspecified runtime exception.
*
- * <p> If a {@code CompletionHandler} is specified when initiating an I/O
- * operation, and the {@code cancel} method is invoked to cancel the I/O
- * operation before it completes, then the {@code CompletionHandler}'s {@link
- * CompletionHandler#cancelled cancelled} method is invoked.
- *
- * <p> If an implementation of this interface supports a means to cancel I/O
- * operations, and where cancellation may leave the channel, or the entity to
- * which it is connected, in an inconsistent state, then the channel is put into
- * an implementation specific <em>error state</em> that prevents further
- * attempts to initiate I/O operations on the channel. For example, if a read
- * operation is cancelled but the implementation cannot guarantee that bytes
- * have not been read from the channel then it puts the channel into error state
- * state; further attempts to initiate a {@code read} operation causes an
- * unspecified runtime exception to be thrown.
+ * <p> Where the {@link Future#cancel cancel} method is invoked with the {@code
+ * mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
+ * may be interrupted by closing the channel. In that case all threads waiting
+ * on the result of the I/O operation throw {@code CancellationException} and
+ * any other I/O operations outstanding on the channel complete with the
+ * exception {@link AsynchronousCloseException}.
*
* <p> Where the {@code cancel} method is invoked to cancel read or write
- * operations then it recommended that all buffers used in the I/O operations be
- * discarded or care taken to ensure that the buffers are not accessed while the
- * channel remains open.
+ * operations then it is recommended that all buffers used in the I/O operations
+ * be discarded or care taken to ensure that the buffers are not accessed while
+ * the channel remains open.
*
* @since 1.7
*/
@@ -102,7 +103,7 @@
*
* <p> Any outstanding asynchronous operations upon this channel will
* complete with the exception {@link AsynchronousCloseException}. After a
- * channel is closed then further attempts to initiate asynchronous I/O
+ * channel is closed, further attempts to initiate asynchronous I/O
* operations complete immediately with cause {@link ClosedChannelException}.
*
* <p> This method otherwise behaves exactly as specified by the {@link
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousDatagramChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -109,19 +109,13 @@
* // print the source address of all packets that we receive
* dc.receive(buffer, buffer, new CompletionHandler<SocketAddress,ByteBuffer>() {
* public void completed(SocketAddress sa, ByteBuffer buffer) {
- * try {
- * System.out.println(sa);
- *
- * buffer.clear();
- * dc.receive(buffer, buffer, this);
- * } catch (...) { ... }
+ * System.out.println(sa);
+ * buffer.clear();
+ * dc.receive(buffer, buffer, this);
* }
* public void failed(Throwable exc, ByteBuffer buffer) {
* ...
* }
- * public void cancelled(ByteBuffer buffer) {
- * ...
- * }
* });
* </pre>
*
@@ -314,10 +308,10 @@
/**
* Receives a datagram via this channel.
*
- * <p> This method initiates the receiving of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The {@code Future}'s {@link Future#get() get} method returns
- * the source address of the datagram upon successful completion.
+ * <p> This method initiates the receiving of a datagram into the given
+ * buffer. The {@code handler} parameter is a completion handler that is
+ * invoked when the receive operation completes (or fails). The result
+ * passed to the completion handler is the datagram's source address.
*
* <p> The datagram is transferred into the given byte buffer starting at
* its current position, as if by a regular {@link AsynchronousByteChannel#read
@@ -350,28 +344,26 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the timeout is negative or the buffer is read-only
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<SocketAddress> receive(ByteBuffer dst,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<SocketAddress,? super A> handler);
+ public abstract <A> void receive(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<SocketAddress,? super A> handler);
/**
* Receives a datagram via this channel.
*
- * <p> This method initiates the receiving of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The {@code Future}'s {@link Future#get() get} method returns
- * the source address of the datagram upon successful completion.
+ * <p> This method initiates the receiving of a datagram into the given
+ * buffer. The {@code handler} parameter is a completion handler that is
+ * invoked when the receive operation completes (or fails). The result
+ * passed to the completion handler is the datagram's source address.
*
* <p> This method is equivalent to invoking {@link
* #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
@@ -382,34 +374,30 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the buffer is read-only
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public final <A> Future<SocketAddress> receive(ByteBuffer dst,
- A attachment,
- CompletionHandler<SocketAddress,? super A> handler)
+ public final <A> void receive(ByteBuffer dst,
+ A attachment,
+ CompletionHandler<SocketAddress,? super A> handler)
{
- return receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+ receive(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
* Receives a datagram via this channel.
*
- * <p> This method initiates the receiving of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The {@code Future}'s {@link Future#get() get} method returns
- * the source address of the datagram upon successful completion.
- *
- * <p> This method is equivalent to invoking {@link
- * #receive(ByteBuffer,long,TimeUnit,Object,CompletionHandler)} with a
- * timeout of {@code 0L}, and an attachment and completion handler
- * of {@code null}.
+ * <p> This method initiates the receiving of a datagram into the given
+ * buffer. The method behaves in exactly the same manner as the {@link
+ * #receive(ByteBuffer,Object,CompletionHandler)
+ * receive(ByteBuffer,Object,CompletionHandler)} method except that instead
+ * of specifying a completion handler, this method returns a {@code Future}
+ * representing the pending result. The {@code Future}'s {@link Future#get()
+ * get} method returns the datagram's source address.
*
* @param dst
* The buffer into which the datagram is to be transferred
@@ -419,84 +407,19 @@
* @throws IllegalArgumentException
* If the buffer is read-only
*/
- public final <A> Future<SocketAddress> receive(ByteBuffer dst) {
- return receive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
- }
+ public abstract Future<SocketAddress> receive(ByteBuffer dst);
/**
* Sends a datagram via this channel.
*
- * <p> This method initiates sending of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The operation sends the remaining bytes in the given buffer as a single
- * datagram to the given target address. The result of the operation, obtained
- * by invoking the {@code Future}'s {@link Future#get() get}
- * method, is the number of bytes sent.
- *
- * <p> The datagram is transferred from the byte buffer as if by a regular
- * {@link AsynchronousByteChannel#write write} operation.
- *
- * <p> If a timeout is specified and the timeout elapses before the operation
- * completes then the operation completes with the exception {@link
- * InterruptedByTimeoutException}. When a timeout elapses then the state of
- * the {@link ByteBuffer} is not defined. The buffers should be discarded or
- * at least care must be taken to ensure that the buffer is not accessed
- * while the channel remains open.
- *
- * <p> If there is a security manager installed and the channel is not
- * connected then this method verifies that the target address and port number
- * are permitted by the security manager's {@link SecurityManager#checkConnect
- * checkConnect} method. The overhead of this security check can be avoided
- * by first connecting the socket via the {@link #connect connect} method.
- *
- * @param src
- * The buffer containing the datagram to be sent
- * @param target
- * The address to which the datagram is to be sent
- * @param timeout
- * The timeout, or {@code 0L} for no timeout
- * @param unit
- * The time unit of the {@code timeout} argument
- * @param attachment
- * The object to attach to the I/O operation; can be {@code null}
- * @param handler
- * The handler for consuming the result; can be {@code null}
+ * <p> This method initiates sending of a datagram from the given buffer to
+ * the given address. The {@code handler} parameter is a completion handler
+ * that is invoked when the send completes (or fails). The result passed to
+ * the completion handler is the number of bytes sent.
*
- * @return a {@code Future} object representing the pending result
- *
- * @throws UnresolvedAddressException
- * If the given remote address is not fully resolved
- * @throws UnsupportedAddressTypeException
- * If the type of the given remote address is not supported
- * @throws IllegalArgumentException
- * If the timeout is negative, or if the channel's socket is
- * connected to an address that is not equal to {@code target}
- * @throws SecurityException
- * If a security manager has been installed and it does not permit
- * datagrams to be sent to the given address
- * @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
- */
- public abstract <A> Future<Integer> send(ByteBuffer src,
- SocketAddress target,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
-
- /**
- * Sends a datagram via this channel.
- *
- * <p> This method initiates sending of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The operation sends the remaining bytes in the given buffer as a single
- * datagram to the given target address. The result of the operation, obtained
- * by invoking the {@code Future}'s {@link Future#get() get}
- * method, is the number of bytes sent.
- *
- * <p> This method is equivalent to invoking {@link
- * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
- * with a timeout of {@code 0L}.
+ * <p> Otherwise this method works in the same manner as the {@link
+ * AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
+ * method.
*
* @param src
* The buffer containing the datagram to be sent
@@ -505,9 +428,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
@@ -520,30 +441,23 @@
* If a security manager has been installed and it does not permit
* datagrams to be sent to the given address
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public final <A> Future<Integer> send(ByteBuffer src,
- SocketAddress target,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
- {
- return send(src, target, 0L, TimeUnit.MILLISECONDS, attachment, handler);
- }
+ public abstract <A> void send(ByteBuffer src,
+ SocketAddress target,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* Sends a datagram via this channel.
*
- * <p> This method initiates sending of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The operation sends the remaining bytes in the given buffer as a single
- * datagram to the given target address. The result of the operation, obtained
- * by invoking the {@code Future}'s {@link Future#get() get}
- * method, is the number of bytes sent.
- *
- * <p> This method is equivalent to invoking {@link
- * #send(ByteBuffer,SocketAddress,long,TimeUnit,Object,CompletionHandler)}
- * with a timeout of {@code 0L} and an attachment and completion handler
- * of {@code null}.
+ * <p> This method initiates sending of a datagram from the given buffer to
+ * the given address. The method behaves in exactly the same manner as the
+ * {@link #send(ByteBuffer,SocketAddress,Object,CompletionHandler)
+ * send(ByteBuffer,SocketAddress,Object,CompletionHandler)} method except
+ * that instead of specifying a completion handler, this method returns a
+ * {@code Future} representing the pending result. The {@code Future}'s
+ * {@link Future#get() get} method returns the number of bytes sent.
*
* @param src
* The buffer containing the datagram to be sent
@@ -563,17 +477,15 @@
* If a security manager has been installed and it does not permit
* datagrams to be sent to the given address
*/
- public final Future<Integer> send(ByteBuffer src, SocketAddress target) {
- return send(src, target, 0L, TimeUnit.MILLISECONDS, null, null);
- }
+ public abstract Future<Integer> send(ByteBuffer src, SocketAddress target);
/**
* Receives a datagram via this channel.
*
- * <p> This method initiates the receiving of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The {@code Future}'s {@link Future#get() get} method returns
- * the number of bytes transferred upon successful completion.
+ * <p> This method initiates the receiving of a datagram into the given
+ * buffer. The {@code handler} parameter is a completion handler that is
+ * invoked when the receive operation completes (or fails). The result
+ * passed to the completion handler is number of bytes read.
*
* <p> This method may only be invoked if this channel is connected, and it
* only accepts datagrams from the peer that the channel is connected too.
@@ -599,120 +511,62 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the timeout is negative or buffer is read-only
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<Integer> read(ByteBuffer dst,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ public abstract <A> void read(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
@Override
- public final <A> Future<Integer> read(ByteBuffer dst,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public final <A> void read(ByteBuffer dst,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+ read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
@Override
- public final Future<Integer> read(ByteBuffer dst) {
- return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
- }
-
- /**
- * Writes a datagram to this channel.
- *
- * <p> This method initiates sending of a datagram, returning a
- * {@code Future} representing the pending result of the operation.
- * The operation sends the remaining bytes in the given buffer as a single
- * datagram. The result of the operation, obtained by invoking the
- * {@code Future}'s {@link Future#get() get} method, is the
- * number of bytes sent.
- *
- * <p> The datagram is transferred from the byte buffer as if by a regular
- * {@link AsynchronousByteChannel#write write} operation.
- *
- * <p> This method may only be invoked if this channel is connected,
- * in which case it sends datagrams directly to the socket's peer. Otherwise
- * it behaves exactly as specified in the {@link
- * AsynchronousByteChannel} interface.
- *
- * <p> If a timeout is specified and the timeout elapses before the operation
- * completes then the operation completes with the exception {@link
- * InterruptedByTimeoutException}. When a timeout elapses then the state of
- * the {@link ByteBuffer} is not defined. The buffers should be discarded or
- * at least care must be taken to ensure that the buffer is not accessed
- * while the channel remains open.
- *
- * @param src
- * The buffer containing the datagram to be sent
- * @param timeout
- * The timeout, or {@code 0L} for no timeout
- * @param unit
- * The time unit of the {@code timeout} argument
- * @param attachment
- * The object to attach to the I/O operation; can be {@code null}
- * @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
- *
- * @throws IllegalArgumentException
- * If the timeout is negative
- * @throws NotYetConnectedException
- * If this channel is not connected
- * @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
- */
- public abstract <A> Future<Integer> write(ByteBuffer src,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
- /**
- * @throws NotYetConnectedException
- * If this channel is not connected
- * @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
- */
- @Override
- public final <A> Future<Integer> write(ByteBuffer src,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
- {
- return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
- }
+ public abstract Future<Integer> read(ByteBuffer dst);
/**
* @throws NotYetConnectedException
* If this channel is not connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
@Override
- public final Future<Integer> write(ByteBuffer src) {
- return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
- }
+ public abstract <A> void write(ByteBuffer src,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
+
+
+ /**
+ * @throws NotYetConnectedException
+ * If this channel is not connected
+ * @throws ShutdownChannelGroupException
+ * If the channel group has terminated
+ */
+ @Override
+ public abstract Future<Integer> write(ByteBuffer src);
}
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -48,7 +48,12 @@
*
* <p> An asynchronous file channel does not have a <i>current position</i>
* within the file. Instead, the file position is specified to each read and
- * write operation.
+ * write methd that initiate asynchronous operations. A {@link CompletionHandler}
+ * is specified as a parameter and is invoked to consume the result of the I/O
+ * operation. This class also defines read and write methods that initiate
+ * asynchronous operations, returning a {@link Future} to represent the pending
+ * result of the operation. The {@code Future} may be used to check if the
+ * operation has completed, to wait for its completion.
*
* <p> In addition to read and write operations, this class defines the
* following operations: </p>
@@ -59,18 +64,11 @@
* out</i>} to the underlying storage device, ensuring that data are not
* lost in the event of a system crash. </p></li>
*
- * <li><p> A region of a file may be {@link FileLock <i>locked</i>}
- * against access by other programs. </p></li>
+ * <li><p> A region of a file may be {@link #lock <i>locked</i>} against
+ * access by other programs. </p></li>
*
* </ul>
*
- * <p> The {@link #read read}, {@link #write write}, and {@link #lock lock}
- * methods defined by this class are asynchronous and return a {@link Future}
- * to represent the pending result of the operation. This may be used to check
- * if the operation has completed, to wait for its completion, and to retrieve
- * the result. These method may optionally specify a {@link CompletionHandler}
- * that is invoked to consume the result of the I/O operation when it completes.
- *
* <p> An {@code AsynchronousFileChannel} is associated with a thread pool to
* which tasks are submitted to handle I/O events and dispatch to completion
* handlers that consume the results of I/O operations on the channel. The
@@ -123,22 +121,6 @@
}
/**
- * Closes this channel.
- *
- * <p> If this channel is associated with its own thread pool then closing
- * the channel causes the thread pool to shutdown after all actively
- * executing completion handlers have completed. No attempt is made to stop
- * or interrupt actively completion handlers.
- *
- * <p> This method otherwise behaves exactly as specified by the {@link
- * AsynchronousChannel} interface.
- *
- * @throws IOException {@inheritDoc}
- */
- @Override
- public abstract void close() throws IOException;
-
- /**
* Opens or creates a file for reading and/or writing, returning an
* asynchronous file channel to access the file.
*
@@ -215,9 +197,8 @@
* should be taken when configuring the {@code Executor}. Minimally it
* should support an unbounded work queue and should not run tasks on the
* caller thread of the {@link ExecutorService#execute execute} method.
- * {@link #close Closing} the channel results in the orderly {@link
- * ExecutorService#shutdown shutdown} of the executor service. Shutting down
- * the executor service by other means results in unspecified behavior.
+ * Shutting down the executor service while the channel is open results in
+ * unspecified behavior.
*
* <p> The {@code attrs} parameter is an optional array of file {@link
* FileAttribute file-attributes} to set atomically when creating the file.
@@ -276,7 +257,8 @@
* <p> An invocation of this method behaves in exactly the same way as the
* invocation
* <pre>
- * ch.{@link #open(Path,Set,ExecutorService,FileAttribute[]) open}(file, opts, null, new FileAttribute<?>[0]);
+ * ch.{@link #open(Path,Set,ExecutorService,FileAttribute[])
+ * open}(file, opts, null, new FileAttribute<?>[0]);
* </pre>
* where {@code opts} is a {@code Set} containing the options specified to
* this method.
@@ -405,10 +387,11 @@
/**
* Acquires a lock on the given region of this channel's file.
*
- * <p> This method initiates an operation to acquire a lock on the given region
- * of this channel's file. The method returns a {@code Future} representing
- * the pending result of the operation. Its {@link Future#get() get}
- * method returns the {@link FileLock} on successful completion.
+ * <p> This method initiates an operation to acquire a lock on the given
+ * region of this channel's file. The {@code handler} parameter is a
+ * completion handler that is invoked when the lock is acquired (or the
+ * operation fails). The result passed to the completion handler is the
+ * resulting {@code FileLock}.
*
* <p> The region specified by the {@code position} and {@code size}
* parameters need not be contained within, or even overlap, the actual
@@ -455,9 +438,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return a {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws OverlappingFileLockException
* If a lock that overlaps the requested region is already held by
@@ -466,26 +447,24 @@
* @throws IllegalArgumentException
* If the preconditions on the parameters do not hold
* @throws NonReadableChannelException
- * If {@code shared} is true this channel but was not opened for reading
+ * If {@code shared} is true but this channel was not opened for reading
* @throws NonWritableChannelException
* If {@code shared} is false but this channel was not opened for writing
- * @throws ShutdownChannelGroupException
- * If a handler is specified, the channel is closed, and the channel
- * was originally created with its own thread pool
*/
- public abstract <A> Future<FileLock> lock(long position,
- long size,
- boolean shared,
- A attachment,
- CompletionHandler<FileLock,? super A> handler);
+ public abstract <A> void lock(long position,
+ long size,
+ boolean shared,
+ A attachment,
+ CompletionHandler<FileLock,? super A> handler);
/**
* Acquires an exclusive lock on this channel's file.
*
- * <p> This method initiates an operation to acquire an exclusive lock on this
- * channel's file. The method returns a {@code Future} representing
- * the pending result of the operation. Its {@link Future#get() get}
- * method returns the {@link FileLock} on successful completion.
+ * <p> This method initiates an operation to acquire a lock on the given
+ * region of this channel's file. The {@code handler} parameter is a
+ * completion handler that is invoked when the lock is acquired (or the
+ * operation fails). The result passed to the completion handler is the
+ * resulting {@code FileLock}.
*
* <p> An invocation of this method of the form {@code ch.lock(att,handler)}
* behaves in exactly the same way as the invocation
@@ -496,7 +475,70 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
+ * The handler for consuming the result
+ *
+ * @throws OverlappingFileLockException
+ * If a lock is already held by this Java virtual machine, or there
+ * is already a pending attempt to lock a region
+ * @throws NonWritableChannelException
+ * If this channel was not opened for writing
+ */
+ public final <A> void lock(A attachment,
+ CompletionHandler<FileLock,? super A> handler)
+ {
+ lock(0L, Long.MAX_VALUE, false, attachment, handler);
+ }
+
+ /**
+ * Acquires a lock on the given region of this channel's file.
+ *
+ * <p> This method initiates an operation to acquire a lock on the given
+ * region of this channel's file. The method behaves in exactly the same
+ * manner as the {@link #lock(long, long, boolean, Object, CompletionHandler)}
+ * method except that instead of specifying a completion handler, this
+ * method returns a {@code Future} representing the pending result. The
+ * {@code Future}'s {@link Future#get() get} method returns the {@link
+ * FileLock} on successful completion.
+ *
+ * @param position
+ * The position at which the locked region is to start; must be
+ * non-negative
+ * @param size
+ * The size of the locked region; must be non-negative, and the sum
+ * {@code position} + {@code size} must be non-negative
+ * @param shared
+ * {@code true} to request a shared lock, in which case this
+ * channel must be open for reading (and possibly writing);
+ * {@code false} to request an exclusive lock, in which case this
+ * channel must be open for writing (and possibly reading)
+ *
+ * @return a {@code Future} object representing the pending result
+ *
+ * @throws OverlappingFileLockException
+ * If a lock is already held by this Java virtual machine, or there
+ * is already a pending attempt to lock a region
+ * @throws IllegalArgumentException
+ * If the preconditions on the parameters do not hold
+ * @throws NonReadableChannelException
+ * If {@code shared} is true but this channel was not opened for reading
+ * @throws NonWritableChannelException
+ * If {@code shared} is false but this channel was not opened for writing
+ */
+ public abstract Future<FileLock> lock(long position, long size, boolean shared);
+
+ /**
+ * Acquires an exclusive lock on this channel's file.
+ *
+ * <p> This method initiates an operation to acquire an exclusive lock on this
+ * channel's file. The method returns a {@code Future} representing the
+ * pending result of the operation. The {@code Future}'s {@link Future#get()
+ * get} method returns the {@link FileLock} on successful completion.
+ *
+ * <p> An invocation of this method behaves in exactly the same way as the
+ * invocation
+ * <pre>
+ * ch.{@link #lock(long,long,boolean) lock}(0L, Long.MAX_VALUE, false)
+ * </pre>
*
* @return a {@code Future} object representing the pending result
*
@@ -505,40 +547,9 @@
* is already a pending attempt to lock a region
* @throws NonWritableChannelException
* If this channel was not opened for writing
- * @throws ShutdownChannelGroupException
- * If a handler is specified, the channel is closed, and the channel
- * was originally created with its own thread pool
- */
- public final <A> Future<FileLock> lock(A attachment,
- CompletionHandler<FileLock,? super A> handler)
- {
- return lock(0L, Long.MAX_VALUE, false, attachment, handler);
- }
-
- /**
- * Acquires an exclusive lock on this channel's file.
- *
- * <p> This method initiates an operation to acquire an exclusive lock on this
- * channel's file. The method returns a {@code Future} representing the
- * pending result of the operation. Its {@link Future#get() get} method
- * returns the {@link FileLock} on successful completion.
- *
- * <p> An invocation of this method behaves in exactly the same way as the
- * invocation
- * <pre>
- * ch.{@link #lock(long,long,boolean,Object,CompletionHandler) lock}(0L, Long.MAX_VALUE, false, null, null)
- * </pre>
- *
- * @return A {@code Future} object representing the pending result
- *
- * @throws OverlappingFileLockException
- * If a lock is already held by this Java virtual machine, or there
- * is already a pending attempt to lock a region
- * @throws NonWritableChannelException
- * If this channel was not opened for writing
*/
public final Future<FileLock> lock() {
- return lock(0L, Long.MAX_VALUE, false, null, null);
+ return lock(0L, Long.MAX_VALUE, false);
}
/**
@@ -576,7 +587,7 @@
* blocked in this method and is attempting to lock an overlapping
* region of the same file
* @throws NonReadableChannelException
- * If {@code shared} is true this channel but was not opened for reading
+ * If {@code shared} is true but this channel was not opened for reading
* @throws NonWritableChannelException
* If {@code shared} is false but this channel was not opened for writing
*
@@ -629,11 +640,10 @@
* starting at the given file position.
*
* <p> This method initiates the reading of a sequence of bytes from this
- * channel into the given buffer, starting at the given file position. This
- * method returns a {@code Future} representing the pending result of the
- * operation. The Future's {@link Future#get() get} method returns the
- * number of bytes read or {@code -1} if the given position is greater than
- * or equal to the file's size at the time that the read is attempted.
+ * channel into the given buffer, starting at the given file position. The
+ * result of the read is the number of bytes read or {@code -1} if the given
+ * position is greater than or equal to the file's size at the time that the
+ * read is attempted.
*
* <p> This method works in the same manner as the {@link
* AsynchronousByteChannel#read(ByteBuffer,Object,CompletionHandler)}
@@ -649,22 +659,17 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the position is negative or the buffer is read-only
* @throws NonReadableChannelException
* If this channel was not opened for reading
- * @throws ShutdownChannelGroupException
- * If a handler is specified, the channel is closed, and the channel
- * was originally created with its own thread pool
*/
- public abstract <A> Future<Integer> read(ByteBuffer dst,
- long position,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ public abstract <A> void read(ByteBuffer dst,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* Reads a sequence of bytes from this channel into the given buffer,
@@ -673,13 +678,15 @@
* <p> This method initiates the reading of a sequence of bytes from this
* channel into the given buffer, starting at the given file position. This
* method returns a {@code Future} representing the pending result of the
- * operation. The Future's {@link Future#get() get} method returns the
- * number of bytes read or {@code -1} if the given position is greater
+ * operation. The {@code Future}'s {@link Future#get() get} method returns
+ * the number of bytes read or {@code -1} if the given position is greater
* than or equal to the file's size at the time that the read is attempted.
*
- * <p> This method is equivalent to invoking {@link
- * #read(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
- * and handler parameters set to {@code null}.
+ * <p> This method works in the same manner as the {@link
+ * AsynchronousByteChannel#read(ByteBuffer)} method, except that bytes are
+ * read starting at the given file position. If the given file position is
+ * greater than the file's size at the time that the read is attempted then
+ * no bytes are read.
*
* @param dst
* The buffer into which bytes are to be transferred
@@ -694,20 +701,12 @@
* @throws NonReadableChannelException
* If this channel was not opened for reading
*/
- public final Future<Integer> read(ByteBuffer dst, long position) {
- return read(dst, position, null, null);
- }
+ public abstract Future<Integer> read(ByteBuffer dst, long position);
/**
* Writes a sequence of bytes to this channel from the given buffer, starting
* at the given file position.
*
- * <p> This method initiates the writing of a sequence of bytes to this channel
- * from the given buffer, starting at the given file position. The method
- * returns a {@code Future} representing the pending result of the write
- * operation. The Future's {@link Future#get() get} method returns the
- * number of bytes written.
- *
* <p> This method works in the same manner as the {@link
* AsynchronousByteChannel#write(ByteBuffer,Object,CompletionHandler)}
* method, except that bytes are written starting at the given file position.
@@ -724,36 +723,35 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the position is negative
* @throws NonWritableChannelException
* If this channel was not opened for writing
- * @throws ShutdownChannelGroupException
- * If a handler is specified, the channel is closed, and the channel
- * was originally created with its own thread pool
*/
- public abstract <A> Future<Integer> write(ByteBuffer src,
- long position,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ public abstract <A> void write(ByteBuffer src,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer, starting
* at the given file position.
*
- * <p> This method initiates the writing of a sequence of bytes to this channel
- * from the given buffer, starting at the given file position. The method
- * returns a {@code Future} representing the pending result of the write
- * operation. The Future's {@link Future#get() get} method returns the
- * number of bytes written.
+ * <p> This method initiates the writing of a sequence of bytes to this
+ * channel from the given buffer, starting at the given file position. The
+ * method returns a {@code Future} representing the pending result of the
+ * write operation. The {@code Future}'s {@link Future#get() get} method
+ * returns the number of bytes written.
*
- * <p> This method is equivalent to invoking {@link
- * #write(ByteBuffer,long,Object,CompletionHandler)} with the {@code attachment}
- * and handler parameters set to {@code null}.
+ * <p> This method works in the same manner as the {@link
+ * AsynchronousByteChannel#write(ByteBuffer)} method, except that bytes are
+ * written starting at the given file position. If the given position is
+ * greater than the file's size, at the time that the write is attempted,
+ * then the file will be grown to accommodate the new bytes; the values of
+ * any bytes between the previous end-of-file and the newly-written bytes
+ * are unspecified.
*
* @param src
* The buffer from which bytes are to be transferred
@@ -768,7 +766,5 @@
* @throws NonWritableChannelException
* If this channel was not opened for writing
*/
- public final Future<Integer> write(ByteBuffer src, long position) {
- return write(src, position, null, null);
- }
+ public abstract Future<Integer> write(ByteBuffer src, long position);
}
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -85,9 +85,6 @@
* public void failed(Throwable exc, Void att) {
* ...
* }
- * public void cancelled(Void att) {
- * ...
- * }
* });
* </pre>
*
@@ -240,11 +237,11 @@
/**
* Accepts a connection.
*
- * <p> This method initiates accepting a connection made to this channel's
- * socket, returning a {@link Future} representing the pending result
- * of the operation. The {@code Future}'s {@link Future#get() get}
- * method will return the {@link AsynchronousSocketChannel} for the new
- * connection on successful completion.
+ * <p> This method initiates an asynchronous operation to accept a
+ * connection made to this channel's socket. The {@code handler} parameter is
+ * a completion handler that is invoked when a connection is accepted (or
+ * the operation fails). The result passed to the completion handler is
+ * the {@link AsynchronousSocketChannel} to the new connection.
*
* <p> When a new connection is accepted then the resulting {@code
* AsynchronousSocketChannel} will be bound to the same {@link
@@ -269,35 +266,35 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return an <tt>Future</tt> object representing the pending result
+ * The handler for consuming the result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<AsynchronousSocketChannel>
- accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
+ public abstract <A> void accept(A attachment,
+ CompletionHandler<AsynchronousSocketChannel,? super A> handler);
/**
* Accepts a connection.
*
- * <p> This method is equivalent to invoking {@link
- * #accept(Object,CompletionHandler)} with the {@code attachment}
- * and {@code handler} parameters set to {@code null}.
+ * <p> This method initiates an asynchronous operation to accept a
+ * connection made to this channel's socket. The method behaves in exactly
+ * the same manner as the {@link #accept(Object, CompletionHandler)} method
+ * except that instead of specifying a completion handler, this method
+ * returns a {@code Future} representing the pending result. The {@code
+ * Future}'s {@link Future#get() get} method returns the {@link
+ * AsynchronousSocketChannel} to the new connection on successful completion.
*
- * @return an <tt>Future</tt> object representing the pending result
+ * @return a {@code Future} object representing the pending result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
*/
- public final Future<AsynchronousSocketChannel> accept() {
- return accept(null, null);
- }
+ public abstract Future<AsynchronousSocketChannel> accept();
}
--- a/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -274,14 +274,11 @@
/**
* Connects this channel.
*
- * <p> This method initiates an operation to connect this channel, returning
- * a {@code Future} representing the pending result of the operation. If
- * the connection is successfully established then the {@code Future}'s
- * {@link Future#get() get} method will return {@code null}. If the
- * connection cannot be established then the channel is closed. In that case,
- * invoking the {@code get} method throws {@link
- * java.util.concurrent.ExecutionException} with an {@code IOException} as
- * the cause.
+ * <p> This method initiates an operation to connect this channel. The
+ * {@code handler} parameter is a completion handler that is invoked when
+ * the connection is successfully established or connection cannot be
+ * established. If the connection cannot be established then the channel is
+ * closed.
*
* <p> This method performs exactly the same security checks as the {@link
* java.net.Socket} class. That is, if a security manager has been
@@ -294,9 +291,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
@@ -307,23 +302,26 @@
* @throws ConnectionPendingException
* If a connection operation is already in progress on this channel
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*
* @see #getRemoteAddress
*/
- public abstract <A> Future<Void> connect(SocketAddress remote,
- A attachment,
- CompletionHandler<Void,? super A> handler);
+ public abstract <A> void connect(SocketAddress remote,
+ A attachment,
+ CompletionHandler<Void,? super A> handler);
/**
* Connects this channel.
*
- * <p> This method is equivalent to invoking {@link
- * #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
- * and handler parameters set to {@code null}.
+ * <p> This method initiates an operation to connect this channel. This
+ * method behaves in exactly the same manner as the {@link
+ * #connect(SocketAddress, Object, CompletionHandler)} method except that
+ * instead of specifying a completion handler, this method returns a {@code
+ * Future} representing the pending result. The {@code Future}'s {@link
+ * Future#get() get} method returns {@code null} on successful completion.
*
* @param remote
* The remote address to which this channel is to be connected
@@ -342,18 +340,17 @@
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*/
- public final Future<Void> connect(SocketAddress remote) {
- return connect(remote, null, null);
- }
+ public abstract Future<Void> connect(SocketAddress remote);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
- * <p> This method initiates the reading of a sequence of bytes from this
- * channel into the given buffer, returning a {@code Future} representing
- * the pending result of the operation. The {@code Future}'s {@link
- * Future#get() get} method returns the number of bytes read or {@code -1}
- * if all bytes have been read and channel has reached end-of-stream.
+ * <p> This method initiates an asynchronous read operation to read a
+ * sequence of bytes from this channel into the given buffer. The {@code
+ * handler} parameter is a completion handler that is invoked when the read
+ * operation completes (or fails). The result passed to the completion
+ * handler is the number of bytes read or {@code -1} if no bytes could be
+ * read because the channel has reached end-of-stream.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link
@@ -376,9 +373,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative or the buffer is
@@ -388,13 +383,13 @@
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<Integer> read(ByteBuffer dst,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ public abstract <A> void read(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* @throws IllegalArgumentException {@inheritDoc}
@@ -402,14 +397,14 @@
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
@Override
- public final <A> Future<Integer> read(ByteBuffer dst,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public final <A> void read(ByteBuffer dst,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+ read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
@@ -419,16 +414,18 @@
* If this channel is not yet connected
*/
@Override
- public final Future<Integer> read(ByteBuffer dst) {
- return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
- }
+ public abstract Future<Integer> read(ByteBuffer dst);
/**
* Reads a sequence of bytes from this channel into a subsequence of the
* given buffers. This operation, sometimes called a <em>scattering read</em>,
* is often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
- * variable-length body.
+ * variable-length body. The {@code handler} parameter is a completion
+ * handler that is invoked when the read operation completes (or fails). The
+ * result passed to the completion handler is the number of bytes read or
+ * {@code -1} if no bytes could be read because the channel has reached
+ * end-of-stream.
*
* <p> This method initiates a read of up to <i>r</i> bytes from this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
@@ -456,11 +453,6 @@
* I/O operation is performed with the maximum number of buffers allowed by
* the operating system.
*
- * <p> The return value from this method is a {@code Future} representing
- * the pending result of the operation. The {@code Future}'s {@link
- * Future#get() get} method returns the number of bytes read or {@code -1L}
- * if all bytes have been read and the channel has reached end-of-stream.
- *
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
@@ -485,9 +477,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
@@ -500,23 +490,24 @@
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<Long> read(ByteBuffer[] dsts,
- int offset,
- int length,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Long,? super A> handler);
+ public abstract <A> void read(ByteBuffer[] dsts,
+ int offset,
+ int length,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Long,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
- * <p> This method initiates the writing of a sequence of bytes to this channel
- * from the given buffer, returning a {@code Future} representing the
- * pending result of the operation. The {@code Future}'s {@link Future#get()
- * get} method will return the number of bytes written.
+ * <p> This method initiates an asynchronous write operation to write a
+ * sequence of bytes to this channel from the given buffer. The {@code
+ * handler} parameter is a completion handler that is invoked when the write
+ * operation completes (or fails). The result passed to the completion
+ * handler is the number of bytes written.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
@@ -539,9 +530,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative
@@ -550,28 +539,28 @@
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<Integer> write(ByteBuffer src,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler);
+ public abstract <A> void write(ByteBuffer src,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
/**
* @throws WritePendingException {@inheritDoc}
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
@Override
- public final <A> Future<Integer> write(ByteBuffer src,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public final <A> void write(ByteBuffer src,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
+ write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
@@ -580,16 +569,16 @@
* If this channel is not yet connected
*/
@Override
- public final Future<Integer> write(ByteBuffer src) {
- return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
- }
+ public abstract Future<Integer> write(ByteBuffer src);
/**
* Writes a sequence of bytes to this channel from a subsequence of the given
* buffers. This operation, sometimes called a <em>gathering write</em>, is
* often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
- * variable-length body.
+ * variable-length body. The {@code handler} parameter is a completion
+ * handler that is invoked when the write operation completes (or fails).
+ * The result passed to the completion handler is the number of bytes written.
*
* <p> This method initiates a write of up to <i>r</i> bytes to this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
@@ -616,10 +605,6 @@
* remaining), exceeds this limit, then the I/O operation is performed with
* the maximum number of buffers allowed by the operating system.
*
- * <p> The return value from this method is a {@code Future} representing
- * the pending result of the operation. The {@code Future}'s {@link
- * Future#get() get} method will return the number of bytes written.
- *
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
@@ -644,9 +629,7 @@
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
- * The handler for consuming the result; can be {@code null}
- *
- * @return A {@code Future} object representing the pending result
+ * The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
@@ -658,13 +641,13 @@
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
- * If a handler is specified, and the channel group is shutdown
+ * If the channel group has terminated
*/
- public abstract <A> Future<Long> write(ByteBuffer[] srcs,
- int offset,
- int length,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Long,? super A> handler);
+ public abstract <A> void write(ByteBuffer[] srcs,
+ int offset,
+ int length,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Long,? super A> handler);
}
--- a/jdk/src/share/classes/java/nio/channels/Channels.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/Channels.java Mon Aug 24 22:27:30 2009 -0700
@@ -182,7 +182,6 @@
}
/**
- * {@note new}
* Constructs a stream that reads bytes from the given channel.
*
* <p> The stream will not be buffered, and it will not support the {@link
@@ -258,7 +257,6 @@
}
/**
- * {@note new}
* Constructs a stream that writes bytes to the given channel.
*
* <p> The stream will not be buffered. The stream will be safe for access
--- a/jdk/src/share/classes/java/nio/channels/CompletionHandler.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/CompletionHandler.java Mon Aug 24 22:27:30 2009 -0700
@@ -32,11 +32,9 @@
* handler to be specified to consume the result of an asynchronous operation.
* The {@link #completed completed} method is invoked when the I/O operation
* completes successfully. The {@link #failed failed} method is invoked if the
- * I/O operations fails. The {@link #cancelled cancelled} method is invoked when
- * the I/O operation is cancelled by invoking the {@link
- * java.util.concurrent.Future#cancel cancel} method. The implementations of
- * these methods should complete in a timely manner so as to avoid keeping the
- * invoking thread from dispatching to other completion handlers.
+ * I/O operations fails. The implementations of these methods should complete
+ * in a timely manner so as to avoid keeping the invoking thread from dispatching
+ * to other completion handlers.
*
* @param <V> The result type of the I/O operation
* @param <A> The type of the object attached to the I/O operation
@@ -65,13 +63,4 @@
* The object attached to the I/O operation when it was initiated.
*/
void failed(Throwable exc, A attachment);
-
- /**
- * Invoked when an operation is cancelled by invoking the {@link
- * java.util.concurrent.Future#cancel cancel} method.
- *
- * @param attachment
- * The object attached to the I/O operation when it was initiated.
- */
- void cancelled(A attachment);
}
--- a/jdk/src/share/classes/java/nio/channels/FileChannel.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/FileChannel.java Mon Aug 24 22:27:30 2009 -0700
@@ -39,8 +39,7 @@
/**
* A channel for reading, writing, mapping, and manipulating a file.
*
- * <p> {@note revised}
- * A file channel is a {@link SeekableByteChannel} that is connected to
+ * <p> A file channel is a {@link SeekableByteChannel} that is connected to
* a file. It has a current <i>position</i> within its file which can
* be both {@link #position() <i>queried</i>} and {@link #position(long)
* <i>modified</i>}. The file itself contains a variable-length sequence
@@ -151,7 +150,6 @@
* @author Mike McCloskey
* @author JSR-51 Expert Group
* @since 1.4
- * @updated 1.7
*/
public abstract class FileChannel
@@ -164,7 +162,6 @@
protected FileChannel() { }
/**
- * {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> The {@code options} parameter determines how the file is opened.
@@ -293,7 +290,6 @@
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
/**
- * {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> An invocation of this method behaves in exactly the same way as the
--- a/jdk/src/share/classes/java/nio/channels/FileLock.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/FileLock.java Mon Aug 24 22:27:30 2009 -0700
@@ -114,7 +114,6 @@
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
- * @updated 1.7
*/
public abstract class FileLock {
@@ -161,7 +160,7 @@
}
/**
- * {@note new} Initializes a new instance of this class.
+ * Initializes a new instance of this class.
*
* @param channel
* The channel upon whose file this lock is held
@@ -199,7 +198,6 @@
}
/**
- * {@note revised}
* Returns the file channel upon whose file this lock was acquired.
*
* <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
@@ -213,7 +211,6 @@
}
/**
- * {@note new}
* Returns the channel upon whose file this lock was acquired.
*
* @return The channel upon whose file this lock was acquired.
--- a/jdk/src/share/classes/java/nio/channels/exceptions Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/exceptions Mon Aug 24 22:27:30 2009 -0700
@@ -190,5 +190,5 @@
gen ShutdownChannelGroupException "
* Unchecked exception thrown when an attempt is made to construct a channel in
* a group that is shutdown or the completion handler for an I/O operation
- * cannot be invoked because the channel group is shutdown." \
+ * cannot be invoked because the channel group has terminated." \
-3903801676350154157L
--- a/jdk/src/share/classes/java/nio/channels/package-info.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/channels/package-info.java Mon Aug 24 22:27:30 2009 -0700
@@ -285,7 +285,6 @@
* java.lang.NullPointerException NullPointerException} to be thrown.
*
* @since 1.4
- * @updated 1.7
* @author Mark Reinhold
* @author JSR-51 Expert Group
*/
--- a/jdk/src/share/classes/java/nio/file/FileRef.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileRef.java Mon Aug 24 22:27:30 2009 -0700
@@ -39,8 +39,6 @@
* metadata or file attributes.
*
* @since 1.7
- * @see java.io.Inputs
- * @see java.io.Outputs
* @see java.nio.file.attribute.Attributes
* @see java.io.File#toPath
*/
--- a/jdk/src/share/classes/java/util/Scanner.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/java/util/Scanner.java Mon Aug 24 22:27:30 2009 -0700
@@ -674,7 +674,6 @@
}
/**
- * {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the underlying platform's
@@ -694,7 +693,6 @@
}
/**
- * {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the specified charset.
--- a/jdk/src/share/classes/sun/nio/ch/AbstractFuture.java Thu Aug 20 11:20:21 2009 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.nio.ch;
-
-import java.nio.channels.AsynchronousChannel;
-import java.util.concurrent.Future;
-
-/**
- * Base implementation of Future used for asynchronous I/O
- */
-
-abstract class AbstractFuture<V,A>
- implements Future<V>
-{
- private final AsynchronousChannel channel;
- private final A attachment;
-
- protected AbstractFuture(AsynchronousChannel channel, A attachment) {
- this.channel = channel;
- this.attachment = attachment;
- }
-
- final AsynchronousChannel channel() {
- return channel;
- }
-
- final A attachment() {
- return attachment;
- }
-
- /**
- * Returns the result of the operation if it has completed successfully.
- */
- abstract V value();
-
- /**
- * Returns the exception if the operation has failed.
- */
- abstract Throwable exception();
-}
--- a/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -32,8 +32,8 @@
import java.io.FileDescriptor;
import java.util.Queue;
import java.util.concurrent.*;
-import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.security.PrivilegedAction;
import java.security.AccessController;
import java.security.AccessControlContext;
@@ -65,11 +65,8 @@
private final Queue<Runnable> taskQueue;
// group shutdown
- // shutdownLock is RW lock so as to allow for concurrent queuing of tasks
- // when using a fixed thread pool.
- private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
+ private final AtomicBoolean shutdown = new AtomicBoolean();
private final Object shutdownNowLock = new Object();
- private volatile boolean shutdown;
private volatile boolean terminateInitiated;
AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
@@ -214,7 +211,7 @@
@Override
public final boolean isShutdown() {
- return shutdown;
+ return shutdown.get();
}
@Override
@@ -260,17 +257,10 @@
@Override
public final void shutdown() {
- shutdownLock.writeLock().lock();
- try {
- if (shutdown) {
- // already shutdown
- return;
- }
- shutdown = true;
- } finally {
- shutdownLock.writeLock().unlock();
+ if (shutdown.getAndSet(true)) {
+ // already shutdown
+ return;
}
-
// if there are channels in the group then shutdown will continue
// when the last channel is closed
if (!isEmpty()) {
@@ -289,12 +279,7 @@
@Override
public final void shutdownNow() throws IOException {
- shutdownLock.writeLock().lock();
- try {
- shutdown = true;
- } finally {
- shutdownLock.writeLock().unlock();
- }
+ shutdown.set(true);
synchronized (shutdownNowLock) {
if (!terminateInitiated) {
terminateInitiated = true;
@@ -305,6 +290,18 @@
}
}
+ /**
+ * For use by AsynchronousFileChannel to release resources without shutting
+ * down the thread pool.
+ */
+ final void detachFromThreadPool() {
+ if (shutdown.getAndSet(true))
+ throw new AssertionError("Already shutdown");
+ if (!isEmpty())
+ throw new AssertionError("Group not empty");
+ shutdownHandlerTasks();
+ }
+
@Override
public final boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException
--- a/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -25,8 +25,10 @@
package sun.nio.ch;
+import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.concurrent.locks.*;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -101,6 +103,33 @@
// -- file locking --
+ abstract <A> Future<FileLock> implLock(long position,
+ long size,
+ boolean shared,
+ A attachment,
+ CompletionHandler<FileLock,? super A> handler);
+
+ @Override
+ public final Future<FileLock> lock(long position,
+ long size,
+ boolean shared)
+
+ {
+ return implLock(position, size, shared, null, null);
+ }
+
+ @Override
+ public final <A> void lock(long position,
+ long size,
+ boolean shared,
+ A attachment,
+ CompletionHandler<FileLock,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implLock(position, size, shared, attachment, handler);
+ }
+
private volatile FileLockTable fileLockTable;
final void ensureFileLockTableInitialized() throws IOException {
@@ -175,4 +204,50 @@
end();
}
}
+
+
+ // -- reading and writing --
+
+ abstract <A> Future<Integer> implRead(ByteBuffer dst,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
+
+ @Override
+ public final Future<Integer> read(ByteBuffer dst, long position) {
+ return implRead(dst, position, null, null);
+ }
+
+ @Override
+ public final <A> void read(ByteBuffer dst,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implRead(dst, position, attachment, handler);
+ }
+
+ abstract <A> Future<Integer> implWrite(ByteBuffer src,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler);
+
+
+ @Override
+ public final Future<Integer> write(ByteBuffer src, long position) {
+ return implWrite(src, position, null, null);
+ }
+
+ @Override
+ public final <A> void write(ByteBuffer src,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implWrite(src, position, attachment, handler);
+ }
}
--- a/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -35,6 +35,7 @@
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
+import java.util.concurrent.Future;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.net.NetHooks;
@@ -108,6 +109,29 @@
implClose();
}
+ /**
+ * Invoked by accept to accept connection
+ */
+ abstract Future<AsynchronousSocketChannel>
+ implAccept(Object attachment,
+ CompletionHandler<AsynchronousSocketChannel,Object> handler);
+
+
+ @Override
+ public final Future<AsynchronousSocketChannel> accept() {
+ return implAccept(null, null);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <A> void accept(A attachment,
+ CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);
+ }
+
final boolean isAcceptKilled() {
return acceptKilled;
}
--- a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -184,28 +184,53 @@
}
/**
+ * Invoked by connect to initiate the connect operation.
+ */
+ abstract <A> Future<Void> implConnect(SocketAddress remote,
+ A attachment,
+ CompletionHandler<Void,? super A> handler);
+
+ @Override
+ public final Future<Void> connect(SocketAddress remote) {
+ return implConnect(remote, null, null);
+ }
+
+ @Override
+ public final <A> void connect(SocketAddress remote,
+ A attachment,
+ CompletionHandler<Void,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implConnect(remote, attachment, handler);
+ }
+
+ /**
* Invoked by read to initiate the I/O operation.
*/
- abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
- boolean isScatteringRead,
+ abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+ ByteBuffer dst,
+ ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
- private <V extends Number,A> Future<V> read(ByteBuffer[] dsts,
- boolean isScatteringRead,
+ private <V extends Number,A> Future<V> read(boolean isScatteringRead,
+ ByteBuffer dst,
+ ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
- A attachment,
+ A att,
CompletionHandler<V,? super A> handler)
{
if (!isOpen()) {
- CompletedFuture<V,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable e = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(e);
+ Invoker.invoke(this, handler, att, null, e);
+ return null;
}
if (remoteAddress == null)
@@ -213,13 +238,13 @@
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
- boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining();
+ boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
boolean shutdown = false;
// check and update state
synchronized (readLock) {
if (readKilled)
- throw new RuntimeException("Reading not allowed due to timeout or cancellation");
+ throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
if (reading)
throw new ReadPendingException();
if (readShutdown) {
@@ -234,44 +259,53 @@
// immediately complete with -1 if shutdown for read
// immediately complete with 0 if no space remaining
if (shutdown || !hasSpaceToRead) {
- CompletedFuture<V,A> result;
+ Number result;
if (isScatteringRead) {
- Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
- result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+ result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
} else {
- int value = (shutdown) ? -1 : 0;
- result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
+ result = (shutdown) ? -1 : 0;
}
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withResult((V)result);
+ Invoker.invoke(this, handler, att, (V)result, null);
+ return null;
}
- return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler);
+ return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
+ }
+
+ @Override
+ public final Future<Integer> read(ByteBuffer dst) {
+ if (dst.isReadOnly())
+ throw new IllegalArgumentException("Read-only buffer");
+ return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
- public final <A> Future<Integer> read(ByteBuffer dst,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public final <A> void read(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
- ByteBuffer[] bufs = new ByteBuffer[1];
- bufs[0] = dst;
- return read(bufs, false, timeout, unit, attachment, handler);
+ read(false, dst, null, timeout, unit, attachment, handler);
}
@Override
- public final <A> Future<Long> read(ByteBuffer[] dsts,
- int offset,
- int length,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Long,? super A> handler)
+ public final <A> void read(ByteBuffer[] dsts,
+ int offset,
+ int length,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Long,? super A> handler)
{
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
@@ -279,39 +313,41 @@
if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
}
- return read(bufs, true, timeout, unit, attachment, handler);
+ read(true, null, bufs, timeout, unit, attachment, handler);
}
/**
* Invoked by write to initiate the I/O operation.
*/
- abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
- boolean isGatheringWrite,
+ abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+ ByteBuffer src,
+ ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
- private <V extends Number,A> Future<V> write(ByteBuffer[] srcs,
- boolean isGatheringWrite,
+ private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
+ ByteBuffer src,
+ ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
- A attachment,
+ A att,
CompletionHandler<V,? super A> handler)
{
- boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining();
+ boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
boolean closed = false;
if (isOpen()) {
if (remoteAddress == null)
throw new NotYetConnectedException();
- if (timeout < 0L)
+ if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
// check and update state
synchronized (writeLock) {
if (writeKilled)
- throw new RuntimeException("Writing not allowed due to timeout or cancellation");
+ throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
if (writing)
throw new WritePendingException();
if (writeShutdown) {
@@ -327,52 +363,57 @@
// channel is closed or shutdown for write
if (closed) {
- CompletedFuture<V,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable e = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(e);
+ Invoker.invoke(this, handler, att, null, e);
+ return null;
}
// nothing to write so complete immediately
if (!hasDataToWrite) {
- CompletedFuture<V,A> result;
- if (isGatheringWrite) {
- result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment);
- } else {
- result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment);
- }
- Invoker.invoke(handler, result);
- return result;
+ Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
+ if (handler == null)
+ return CompletedFuture.withResult((V)result);
+ Invoker.invoke(this, handler, att, (V)result, null);
+ return null;
}
- return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler);
+ return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
+ }
+
+ @Override
+ public final Future<Integer> write(ByteBuffer src) {
+ return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
- public final <A> Future<Integer> write(ByteBuffer src,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public final <A> void write(ByteBuffer src,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- ByteBuffer[] bufs = new ByteBuffer[1];
- bufs[0] = src;
- return write(bufs, false, timeout, unit, attachment, handler);
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ write(false, src, null, timeout, unit, attachment, handler);
}
@Override
- public final <A> Future<Long> write(ByteBuffer[] srcs,
- int offset,
- int length,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Long,? super A> handler)
+ public final <A> void write(ByteBuffer[] srcs,
+ int offset,
+ int length,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Long,? super A> handler)
{
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
srcs = Util.subsequence(srcs, offset, length);
- return write(srcs, true, timeout, unit, attachment, handler);
+ write(true, null, srcs, timeout, unit, attachment, handler);
}
@Override
@@ -461,7 +502,6 @@
}
@Override
- @SuppressWarnings("unchecked")
public final SocketAddress getRemoteAddress() throws IOException {
if (!isOpen())
throw new ClosedChannelException();
--- a/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/CompletedFuture.java Mon Aug 24 22:27:30 2009 -0700
@@ -25,7 +25,7 @@
package sun.nio.ch;
-import java.nio.channels.AsynchronousChannel;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.io.IOException;
@@ -35,39 +35,35 @@
* completed.
*/
-final class CompletedFuture<V,A>
- extends AbstractFuture<V,A>
-{
+final class CompletedFuture<V> implements Future<V> {
private final V result;
private final Throwable exc;
- private CompletedFuture(AsynchronousChannel channel,
- V result,
- Throwable exc,
- A attachment)
- {
- super(channel, attachment);
+ private CompletedFuture(V result, Throwable exc) {
this.result = result;
this.exc = exc;
}
@SuppressWarnings("unchecked")
- static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel,
- V result,
- A attachment)
- {
- return new CompletedFuture<V,A>(channel, result, null, attachment);
+ static <V> CompletedFuture<V> withResult(V result) {
+ return new CompletedFuture<V>(result, null);
}
@SuppressWarnings("unchecked")
- static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel,
- Throwable exc,
- A attachment)
- {
+ static <V> CompletedFuture<V> withFailure(Throwable exc) {
// exception must be IOException or SecurityException
if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
exc = new IOException(exc);
- return new CompletedFuture(channel, null, exc, attachment);
+ return new CompletedFuture(null, exc);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <V> CompletedFuture<V> withResult(V result, Throwable exc) {
+ if (exc == null) {
+ return withResult(result);
+ } else {
+ return withFailure(exc);
+ }
}
@Override
@@ -100,14 +96,4 @@
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
-
- @Override
- Throwable exception() {
- return exc;
- }
-
- @Override
- V value() {
- return result;
- }
}
--- a/jdk/src/share/classes/sun/nio/ch/Invoker.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Invoker.java Mon Aug 24 22:27:30 2009 -0700
@@ -117,33 +117,32 @@
* Invoke handler without checking the thread identity or number of handlers
* on the thread stack.
*/
- @SuppressWarnings("unchecked")
static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
- AbstractFuture<V,A> result)
+ A attachment,
+ V value,
+ Throwable exc)
{
- if (handler != null && !result.isCancelled()) {
- Throwable exc = result.exception();
- if (exc == null) {
- handler.completed(result.value(), result.attachment());
- } else {
- handler.failed(exc, result.attachment());
- }
+ if (exc == null) {
+ handler.completed(value, attachment);
+ } else {
+ handler.failed(exc, attachment);
+ }
- // clear interrupt
- Thread.interrupted();
- }
+ // clear interrupt
+ Thread.interrupted();
}
-
/**
- * Invoke handler after incrementing the invoke count.
+ * Invoke handler assuming thread identity already checked
*/
static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
CompletionHandler<V,? super A> handler,
- AbstractFuture<V,A> result)
+ A attachment,
+ V result,
+ Throwable exc)
{
myGroupAndInvokeCount.incrementInvokeCount();
- invokeUnchecked(handler, result);
+ Invoker.invokeUnchecked(handler, attachment, result, exc);
}
/**
@@ -151,64 +150,64 @@
* thread pool then the handler is invoked directly, otherwise it is
* invoked indirectly.
*/
- static <V,A> void invoke(CompletionHandler<V,? super A> handler,
- AbstractFuture<V,A> result)
+ static <V,A> void invoke(AsynchronousChannel channel,
+ CompletionHandler<V,? super A> handler,
+ A attachment,
+ V result,
+ Throwable exc)
{
- if (handler != null) {
- boolean invokeDirect = false;
- boolean identityOkay = false;
- GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
- if (thisGroupAndInvokeCount != null) {
- AsynchronousChannel channel = result.channel();
- if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
- identityOkay = true;
- if (identityOkay &&
- (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
- {
- // group match
- invokeDirect = true;
- }
+ boolean invokeDirect = false;
+ boolean identityOkay = false;
+ GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
+ if (thisGroupAndInvokeCount != null) {
+ if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
+ identityOkay = true;
+ if (identityOkay &&
+ (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
+ {
+ // group match
+ invokeDirect = true;
}
- if (invokeDirect) {
- thisGroupAndInvokeCount.incrementInvokeCount();
- invokeUnchecked(handler, result);
- } else {
- try {
- invokeIndirectly(handler, result);
- } catch (RejectedExecutionException ree) {
- // channel group shutdown; fallback to invoking directly
- // if the current thread has the right identity.
- if (identityOkay) {
- invokeUnchecked(handler, result);
- } else {
- throw new ShutdownChannelGroupException();
- }
+ }
+ if (invokeDirect) {
+ invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
+ } else {
+ try {
+ invokeIndirectly(channel, handler, attachment, result, exc);
+ } catch (RejectedExecutionException ree) {
+ // channel group shutdown; fallback to invoking directly
+ // if the current thread has the right identity.
+ if (identityOkay) {
+ invokeDirect(thisGroupAndInvokeCount,
+ handler, attachment, result, exc);
+ } else {
+ throw new ShutdownChannelGroupException();
}
}
}
}
/**
- * Invokes the handler "indirectly" in the channel group's thread pool.
+ * Invokes the handler indirectly via the channel group's thread pool.
*/
- static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
- final AbstractFuture<V,A> result)
+ static <V,A> void invokeIndirectly(AsynchronousChannel channel,
+ final CompletionHandler<V,? super A> handler,
+ final A attachment,
+ final V result,
+ final Throwable exc)
{
- if (handler != null) {
- AsynchronousChannel channel = result.channel();
- try {
- ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
- public void run() {
- GroupAndInvokeCount thisGroupAndInvokeCount =
- myGroupAndInvokeCount.get();
- if (thisGroupAndInvokeCount != null)
- thisGroupAndInvokeCount.setInvokeCount(1);
- invokeUnchecked(handler, result);
- }
- });
- } catch (RejectedExecutionException ree) {
- throw new ShutdownChannelGroupException();
- }
+ try {
+ ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
+ public void run() {
+ GroupAndInvokeCount thisGroupAndInvokeCount =
+ myGroupAndInvokeCount.get();
+ if (thisGroupAndInvokeCount != null)
+ thisGroupAndInvokeCount.setInvokeCount(1);
+ invokeUnchecked(handler, attachment, result, exc);
+ }
+ });
+ } catch (RejectedExecutionException ree) {
+ throw new ShutdownChannelGroupException();
}
}
@@ -216,19 +215,19 @@
* Invokes the handler "indirectly" in the given Executor
*/
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
- final AbstractFuture<V,A> result,
+ final A attachment,
+ final V value,
+ final Throwable exc,
Executor executor)
{
- if (handler != null) {
- try {
- executor.execute(new Runnable() {
- public void run() {
- invokeUnchecked(handler, result);
- }
- });
- } catch (RejectedExecutionException ree) {
- throw new ShutdownChannelGroupException();
- }
+ try {
+ executor.execute(new Runnable() {
+ public void run() {
+ invokeUnchecked(handler, attachment, value, exc);
+ }
+ });
+ } catch (RejectedExecutionException ree) {
+ throw new ShutdownChannelGroupException();
}
}
@@ -258,4 +257,52 @@
throw new ShutdownChannelGroupException();
}
}
+
+ /**
+ * Invoke handler with completed result. This method does not check the
+ * thread identity or the number of handlers on the thread stack.
+ */
+ static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
+ assert future.isDone();
+ CompletionHandler<V,? super A> handler = future.handler();
+ if (handler != null) {
+ invokeUnchecked(handler,
+ future.attachment(),
+ future.value(),
+ future.exception());
+ }
+ }
+
+ /**
+ * Invoke handler with completed result. If the current thread is in the
+ * channel group's thread pool then the handler is invoked directly,
+ * otherwise it is invoked indirectly.
+ */
+ static <V,A> void invoke(PendingFuture<V,A> future) {
+ assert future.isDone();
+ CompletionHandler<V,? super A> handler = future.handler();
+ if (handler != null) {
+ invoke(future.channel(),
+ handler,
+ future.attachment(),
+ future.value(),
+ future.exception());
+ }
+ }
+
+ /**
+ * Invoke handler with completed result. The handler is invoked indirectly,
+ * via the channel group's thread pool.
+ */
+ static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
+ assert future.isDone();
+ CompletionHandler<V,? super A> handler = future.handler();
+ if (handler != null) {
+ invokeIndirectly(future.channel(),
+ handler,
+ future.attachment(),
+ future.value(),
+ future.exception());
+ }
+ }
}
--- a/jdk/src/share/classes/sun/nio/ch/PendingFuture.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/PendingFuture.java Mon Aug 24 22:27:30 2009 -0700
@@ -34,13 +34,13 @@
* attachment of an additional arbitrary context object and a timer task.
*/
-final class PendingFuture<V,A>
- extends AbstractFuture<V,A>
-{
+final class PendingFuture<V,A> implements Future<V> {
private static final CancellationException CANCELLED =
new CancellationException();
+ private final AsynchronousChannel channel;
private final CompletionHandler<V,? super A> handler;
+ private final A attachment;
// true if result (or exception) is available
private volatile boolean haveResult;
@@ -56,14 +56,14 @@
// optional context object
private volatile Object context;
-
PendingFuture(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler,
A attachment,
Object context)
{
- super(channel, attachment);
+ this.channel = channel;
this.handler = handler;
+ this.attachment = attachment;
this.context = context;
}
@@ -71,14 +71,31 @@
CompletionHandler<V,? super A> handler,
A attachment)
{
- super(channel, attachment);
+ this.channel = channel;
this.handler = handler;
+ this.attachment = attachment;
+ }
+
+ PendingFuture(AsynchronousChannel channel) {
+ this(channel, null, null);
+ }
+
+ PendingFuture(AsynchronousChannel channel, Object context) {
+ this(channel, null, null, context);
+ }
+
+ AsynchronousChannel channel() {
+ return channel;
}
CompletionHandler<V,? super A> handler() {
return handler;
}
+ A attachment() {
+ return attachment;
+ }
+
void setContext(Object context) {
this.context = context;
}
@@ -113,36 +130,45 @@
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
- boolean setResult(V res) {
+ void setResult(V res) {
synchronized (this) {
if (haveResult)
- return false;
+ return;
result = res;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
- return true;
}
}
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
- boolean setFailure(Throwable x) {
+ void setFailure(Throwable x) {
if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x);
synchronized (this) {
if (haveResult)
- return false;
+ return;
exc = x;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
- return true;
+ }
+ }
+
+ /**
+ * Sets the result
+ */
+ void setResult(V res, Throwable x) {
+ if (x == null) {
+ setResult(res);
+ } else {
+ setFailure(x);
}
}
@@ -178,12 +204,10 @@
return result;
}
- @Override
Throwable exception() {
return (exc != CANCELLED) ? exc : null;
}
- @Override
V value() {
return result;
}
@@ -204,33 +228,6 @@
if (haveResult)
return false; // already completed
- // A shutdown of the channel group will close all channels and
- // shutdown the executor. To ensure that the completion handler
- // is executed we queue the task while holding the lock.
- if (handler != null) {
- prepareForWait();
- Runnable cancelTask = new Runnable() {
- public void run() {
- while (!haveResult) {
- try {
- latch.await();
- } catch (InterruptedException ignore) { }
- }
- handler.cancelled(attachment());
- }
- };
- AsynchronousChannel ch = channel();
- if (ch instanceof Groupable) {
- ((Groupable)ch).group().executeOnPooledThread(cancelTask);
- } else {
- if (ch instanceof AsynchronousFileChannelImpl) {
- ((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask);
- } else {
- throw new AssertionError("Should not get here");
- }
- }
- }
-
// notify channel
if (channel() instanceof Cancellable)
((Cancellable)channel()).onCancel(this);
@@ -249,7 +246,7 @@
} catch (IOException ignore) { }
}
- // release waiters (this also releases the invoker)
+ // release waiters
if (latch != null)
latch.countDown();
return true;
--- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -317,51 +317,71 @@
return new WrappedMembershipKey(this, key);
}
- @Override
- public <A> Future<Integer> send(ByteBuffer src,
- SocketAddress target,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ private <A> Future<Integer> implSend(ByteBuffer src,
+ SocketAddress target,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- if (timeout < 0L)
- throw new IllegalArgumentException("Negative timeout");
- if (unit == null)
- throw new NullPointerException();
-
- CompletedFuture<Integer,A> result;
+ int n = 0;
+ Throwable exc = null;
try {
- int n = dc.send(src, target);
- result = CompletedFuture.withResult(this, n, attachment);
+ n = dc.send(src, target);
} catch (IOException ioe) {
- result = CompletedFuture.withFailure(this, ioe, attachment);
+ exc = ioe;
}
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withResult(n, exc);
+ Invoker.invoke(this, handler, attachment, n, exc);
+ return null;
+ }
+
+ @Override
+ public Future<Integer> send(ByteBuffer src, SocketAddress target) {
+ return implSend(src, target, null, null);
}
@Override
- public <A> Future<Integer> write(ByteBuffer src,
- long timeout,
- TimeUnit unit,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ public <A> void send(ByteBuffer src,
+ SocketAddress target,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implSend(src, target, attachment, handler);
+ }
+
+ private <A> Future<Integer> implWrite(ByteBuffer src,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
- if (timeout < 0L)
- throw new IllegalArgumentException("Negative timeout");
- if (unit == null)
- throw new NullPointerException();
-
- CompletedFuture<Integer,A> result;
+ int n = 0;
+ Throwable exc = null;
try {
- int n = dc.write(src);
- result = CompletedFuture.withResult(this, n, attachment);
+ n = dc.write(src);
} catch (IOException ioe) {
- result = CompletedFuture.withFailure(this, ioe, attachment);
+ exc = ioe;
}
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withResult(n, exc);
+ Invoker.invoke(this, handler, attachment, n, exc);
+ return null;
+
+ }
+
+ @Override
+ public Future<Integer> write(ByteBuffer src) {
+ return implWrite(src, null, null);
+ }
+
+ @Override
+ public <A> void write(ByteBuffer src,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implWrite(src, attachment, handler);
}
/**
@@ -390,12 +410,11 @@
}
}
- @Override
- public <A> Future<SocketAddress> receive(final ByteBuffer dst,
- final long timeout,
- final TimeUnit unit,
- A attachment,
- final CompletionHandler<SocketAddress,? super A> handler)
+ private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
+ final long timeout,
+ final TimeUnit unit,
+ A attachment,
+ final CompletionHandler<SocketAddress,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
@@ -406,10 +425,11 @@
// complete immediately if channel closed
if (!isOpen()) {
- CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this,
- new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
final AccessControlContext acc = (System.getSecurityManager() == null) ?
@@ -471,7 +491,7 @@
x = new AsynchronousCloseException();
result.setFailure(x);
}
- Invoker.invokeUnchecked(handler, result);
+ Invoker.invokeUnchecked(result);
}
};
try {
@@ -483,11 +503,27 @@
}
@Override
- public <A> Future<Integer> read(final ByteBuffer dst,
- final long timeout,
- final TimeUnit unit,
- A attachment,
- final CompletionHandler<Integer,? super A> handler)
+ public Future<SocketAddress> receive(ByteBuffer dst) {
+ return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+ }
+
+ @Override
+ public <A> void receive(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<SocketAddress,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implReceive(dst, timeout, unit, attachment, handler);
+ }
+
+ private <A> Future<Integer> implRead(final ByteBuffer dst,
+ final long timeout,
+ final TimeUnit unit,
+ A attachment,
+ final CompletionHandler<Integer,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
@@ -495,18 +531,20 @@
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
- // another thread may disconnect before read is initiated
- if (!dc.isConnected())
- throw new NotYetConnectedException();
// complete immediately if channel closed
if (!isOpen()) {
- CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this,
- new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
+ // another thread may disconnect before read is initiated
+ if (!dc.isConnected())
+ throw new NotYetConnectedException();
+
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
Runnable task = new Runnable() {
@@ -563,7 +601,7 @@
x = new AsynchronousCloseException();
result.setFailure(x);
}
- Invoker.invokeUnchecked(handler, result);
+ Invoker.invokeUnchecked(result);
}
};
try {
@@ -575,6 +613,23 @@
}
@Override
+ public Future<Integer> read(ByteBuffer dst) {
+ return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
+ }
+
+ @Override
+ public <A> void read(ByteBuffer dst,
+ long timeout,
+ TimeUnit unit,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
+ {
+ if (handler == null)
+ throw new NullPointerException("'handler' is null");
+ implRead(dst, timeout, unit, attachment, handler);
+ }
+
+ @Override
public AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException
{
--- a/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -50,9 +50,6 @@
// Used to make native read and write calls
private static final FileDispatcher nd = new FileDispatcherImpl();
- // indicates if the associated thread pool is the default thread pool
- private final boolean isDefaultExecutor;
-
// Thread-safe set of IDs of native threads, for signalling
private final NativeThreadSet threads = new NativeThreadSet(2);
@@ -60,11 +57,9 @@
SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
boolean reading,
boolean writing,
- ExecutorService executor,
- boolean isDefaultexecutor)
+ ExecutorService executor)
{
super(fdObj, reading, writing, executor);
- this.isDefaultExecutor = isDefaultexecutor;
}
public static AsynchronousFileChannel open(FileDescriptor fdo,
@@ -73,17 +68,9 @@
ThreadPool pool)
{
// Executor is either default or based on pool parameters
- ExecutorService executor;
- boolean isDefaultexecutor;
- if (pool == null) {
- executor = DefaultExecutorHolder.defaultExecutor;
- isDefaultexecutor = true;
- } else {
- executor = pool.executor();
- isDefaultexecutor = false;
- }
- return new SimpleAsynchronousFileChannelImpl(fdo,
- reading, writing, executor, isDefaultexecutor);
+ ExecutorService executor = (pool == null) ?
+ DefaultExecutorHolder.defaultExecutor : pool.executor();
+ return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
}
@Override
@@ -114,16 +101,6 @@
// close file
nd.close(fdObj);
-
- // shutdown executor if specific to this channel
- if (!isDefaultExecutor) {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- executor.shutdown();
- return null;
- }
- });
- }
}
@Override
@@ -194,11 +171,11 @@
}
@Override
- public <A> Future<FileLock> lock(final long position,
- final long size,
- final boolean shared,
- A attachment,
- final CompletionHandler<FileLock,? super A> handler)
+ <A> Future<FileLock> implLock(final long position,
+ final long size,
+ final boolean shared,
+ final A attachment,
+ final CompletionHandler<FileLock,? super A> handler)
{
if (shared && !reading)
throw new NonReadableChannelException();
@@ -208,16 +185,19 @@
// add to lock table
final FileLockImpl fli = addToFileLockTable(position, size, shared);
if (fli == null) {
- CompletedFuture<FileLock,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invokeIndirectly(handler, result, executor);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
+ return null;
}
- final PendingFuture<FileLock,A> result =
- new PendingFuture<FileLock,A>(this, handler, attachment);
+ final PendingFuture<FileLock,A> result = (handler == null) ?
+ new PendingFuture<FileLock,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
+ Throwable exc = null;
+
int ti = threads.add();
try {
int n;
@@ -226,31 +206,36 @@
do {
n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
- if (n == FileDispatcher.LOCKED && isOpen()) {
- result.setResult(fli);
- } else {
+ if (n != FileDispatcher.LOCKED || !isOpen()) {
throw new AsynchronousCloseException();
}
} catch (IOException x) {
removeFromFileLockTable(fli);
if (!isOpen())
x = new AsynchronousCloseException();
- result.setFailure(x);
+ exc = x;
} finally {
end();
}
} finally {
threads.remove(ti);
}
- Invoker.invokeUnchecked(handler, result);
+ if (handler == null) {
+ result.setResult(fli, exc);
+ } else {
+ Invoker.invokeUnchecked(handler, attachment, fli, exc);
+ }
}
};
+ boolean executed = false;
try {
executor.execute(task);
- } catch (RejectedExecutionException ree) {
- // rollback
- removeFromFileLockTable(fli);
- throw new ShutdownChannelGroupException();
+ executed = true;
+ } finally {
+ if (!executed) {
+ // rollback
+ removeFromFileLockTable(fli);
+ }
}
return result;
}
@@ -301,10 +286,10 @@
}
@Override
- public <A> Future<Integer> read(final ByteBuffer dst,
- final long position,
- A attachment,
- final CompletionHandler<Integer,? super A> handler)
+ <A> Future<Integer> implRead(final ByteBuffer dst,
+ final long position,
+ final A attachment,
+ final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
throw new IllegalArgumentException("Negative position");
@@ -315,55 +300,52 @@
// complete immediately if channel closed or no space remaining
if (!isOpen() || (dst.remaining() == 0)) {
- CompletedFuture<Integer,A> result;
- if (isOpen()) {
- result = CompletedFuture.withResult(this, 0, attachment);
- } else {
- result = CompletedFuture.withFailure(this,
- new ClosedChannelException(), attachment);
- }
- Invoker.invokeIndirectly(handler, result, executor);
- return result;
+ Throwable exc = (isOpen()) ? null : new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withResult(0, exc);
+ Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
+ return null;
}
- final PendingFuture<Integer,A> result =
- new PendingFuture<Integer,A>(this, handler, attachment);
+ final PendingFuture<Integer,A> result = (handler == null) ?
+ new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
+ int n = 0;
+ Throwable exc = null;
+
int ti = threads.add();
try {
begin();
- int n;
do {
n = IOUtil.read(fdObj, dst, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
- result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
- result.setFailure(x);
+ exc = x;
} finally {
end();
threads.remove(ti);
}
- Invoker.invokeUnchecked(handler, result);
+ if (handler == null) {
+ result.setResult(n, exc);
+ } else {
+ Invoker.invokeUnchecked(handler, attachment, n, exc);
+ }
}
};
- try {
- executor.execute(task);
- } catch (RejectedExecutionException ree) {
- throw new ShutdownChannelGroupException();
- }
+ executor.execute(task);
return result;
}
@Override
- public <A> Future<Integer> write(final ByteBuffer src,
- final long position,
- A attachment,
- final CompletionHandler<Integer,? super A> handler)
+ <A> Future<Integer> implWrite(final ByteBuffer src,
+ final long position,
+ final A attachment,
+ final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
throw new IllegalArgumentException("Negative position");
@@ -372,47 +354,44 @@
// complete immediately if channel is closed or no bytes remaining
if (!isOpen() || (src.remaining() == 0)) {
- CompletedFuture<Integer,A> result;
- if (isOpen()) {
- result = CompletedFuture.withResult(this, 0, attachment);
- } else {
- result = CompletedFuture.withFailure(this,
- new ClosedChannelException(), attachment);
- }
- Invoker.invokeIndirectly(handler, result, executor);
- return result;
+ Throwable exc = (isOpen()) ? null : new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withResult(0, exc);
+ Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
+ return null;
}
- final PendingFuture<Integer,A> result =
- new PendingFuture<Integer,A>(this, handler, attachment);
+ final PendingFuture<Integer,A> result = (handler == null) ?
+ new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
+ int n = 0;
+ Throwable exc = null;
+
int ti = threads.add();
try {
begin();
- int n;
do {
n = IOUtil.write(fdObj, src, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
- result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
- result.setFailure(x);
+ exc = x;
} finally {
end();
threads.remove(ti);
}
- Invoker.invokeUnchecked(handler, result);
+ if (handler == null) {
+ result.setResult(n, exc);
+ } else {
+ Invoker.invokeUnchecked(handler, attachment, n, exc);
+ }
}
};
- try {
- executor.execute(task);
- } catch (RejectedExecutionException ree) {
- throw new ShutdownChannelGroupException();
- }
+ executor.execute(task);
return result;
}
}
--- a/jdk/src/share/classes/sun/nio/cs/ext/ISO2022.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ISO2022.java Mon Aug 24 22:27:30 2009 -0700
@@ -388,9 +388,9 @@
protected static class Encoder extends CharsetEncoder {
private final Surrogate.Parser sgp = new Surrogate.Parser();
- private final byte SS2 = (byte)0x8e;
- private final byte PLANE2 = (byte)0xA2;
- private final byte PLANE3 = (byte)0xA3;
+ public static final byte SS2 = (byte)0x8e;
+ public static final byte PLANE2 = (byte)0xA2;
+ public static final byte PLANE3 = (byte)0xA3;
private final byte MSB = (byte)0x80;
protected final byte maximumDesignatorLength = 4;
--- a/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java Mon Aug 24 22:27:30 2009 -0700
@@ -76,6 +76,15 @@
} catch (Exception e) { }
}
+ private byte[] bb = new byte[4];
+ public boolean canEncode(char c) {
+ int n = 0;
+ return (c <= '\u007f' ||
+ (n = ((EUC_TW.Encoder)ISOEncoder).toEUC(c, bb)) == 2 ||
+ (n == 4 && bb[0] == SS2 &&
+ (bb[1] == PLANE2 || bb[1] == PLANE3)));
+ }
+
/*
* Since ISO2022-CN-CNS possesses a CharsetEncoder
* without the corresponding CharsetDecoder half the
--- a/jdk/src/share/classes/sun/security/jgss/SunProvider.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/jgss/SunProvider.java Mon Aug 24 22:27:30 2009 -0700
@@ -62,7 +62,7 @@
public SunProvider() {
/* We are the Sun JGSS provider */
- super("SunJGSS", 1.0, INFO);
+ super("SunJGSS", 1.7d, INFO);
AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Aug 24 22:27:30 2009 -0700
@@ -41,6 +41,7 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
+import java.util.Comparator;
import java.util.StringTokenizer;
/**
@@ -229,10 +230,11 @@
/**
* Reads the service key from the keytab file.
* @param service the PrincipalName of the requested service.
- * @return the last service key in the keytab
+ * @return the last service key in the keytab with the highest kvno
*/
public EncryptionKey readServiceKey(PrincipalName service) {
KeyTabEntry entry = null;
+ EncryptionKey key = null;
if (entries != null) {
// Find latest entry for this service that has an etype
// that has been configured for use
@@ -240,9 +242,12 @@
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
- return new EncryptionKey(entry.keyblock,
+ if (key == null ||
+ entry.keyVersion > key.getKeyVersionNumber()) {
+ key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
+ }
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
@@ -250,12 +255,13 @@
}
}
}
- return null;
+ return key;
}
/**
* Reads all keys for a service from the keytab file that have
- * etypes that have been configured for use.
+ * etypes that have been configured for use. If there are multiple
+ * keys with same etype, the one with the highest kvno is returned.
* @param service the PrincipalName of the requested service
* @return an array containing all the service keys
*/
@@ -288,49 +294,39 @@
size = keys.size();
if (size == 0)
return null;
- EncryptionKey[] retVal = new EncryptionKey[size];
+ EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
// Sort keys according to default_tkt_enctypes
- int pos = 0;
- EncryptionKey k;
if (DEBUG) {
System.out.println("Ordering keys wrt default_tkt_enctypes list");
}
- int[] etypes = EType.getDefaults("default_tkt_enctypes");
- if (etypes == null || etypes == EType.getBuiltInDefaults()) {
- // Either no supported types specified in default_tkt_enctypes
- // or no default_tkt_enctypes entry at all. For both cases,
- // just return supported keys in the order retrieved
- for (int i = 0; i < size; i++) {
- retVal[pos++] = keys.get(i);
- }
- } else {
- for (int j = 0; j < etypes.length && pos < size; j++) {
- int target = etypes[j];
- for (int i = 0; i < size && pos < size; i++) {
- k = keys.get(i);
- if (k != null && k.getEType() == target) {
- if (DEBUG) {
- System.out.println(pos + ": " + k);
+
+ final int[] etypes = EType.getDefaults("default_tkt_enctypes");
+
+ // Sort the keys, k1 is preferred than k2 if:
+ // 1. k1's etype appears earlier in etypes than k2's
+ // 2. If same, k1's KVNO is higher
+ Arrays.sort(retVal, new Comparator<EncryptionKey>() {
+ @Override
+ public int compare(EncryptionKey o1, EncryptionKey o2) {
+ if (etypes != null && etypes != EType.getBuiltInDefaults()) {
+ int o1EType = o1.getEType();
+ int o2EType = o2.getEType();
+ if (o1EType != o2EType) {
+ for (int i=0; i<etypes.length; i++) {
+ if (etypes[i] == o1EType) {
+ return -1;
+ } else if (etypes[i] == o2EType) {
+ return 1;
+ }
}
- retVal[pos++] = k;
- keys.set(i, null); // Cleared from consideration
}
}
+ return o2.getKeyVersionNumber().intValue()
+ - o1.getKeyVersionNumber().intValue();
}
- // copy the rest
- for (int i = 0; i < size && pos < size; i++) {
- k = keys.get(i);
- if (k != null) {
- retVal[pos++] = k;
- }
- }
- }
- if (pos != size) {
- throw new RuntimeException(
- "Internal Error: did not copy all keys;expecting " + size +
- "; got " + pos);
- }
+ });
+
return retVal;
}
--- a/jdk/src/share/classes/sun/security/provider/Sun.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/Sun.java Mon Aug 24 22:27:30 2009 -0700
@@ -46,7 +46,7 @@
public Sun() {
/* We are the SUN provider */
- super("SUN", 1.6, INFO);
+ super("SUN", 1.7, INFO);
// if there is no security manager installed, put directly into
// the provider. Otherwise, create a temporary map and use a
--- a/jdk/src/share/classes/sun/security/smartcardio/SunPCSC.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/smartcardio/SunPCSC.java Mon Aug 24 22:27:30 2009 -0700
@@ -40,7 +40,7 @@
private static final long serialVersionUID = 6168388284028876579L;
public SunPCSC() {
- super("SunPCSC", 1.6d, "Sun PC/SC provider");
+ super("SunPCSC", 1.7d, "Sun PC/SC provider");
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
put("TerminalFactory.PC/SC", "sun.security.smartcardio.SunPCSC$Factory");
--- a/jdk/src/share/classes/sun/security/ssl/SunJSSE.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SunJSSE.java Mon Aug 24 22:27:30 2009 -0700
@@ -103,7 +103,7 @@
// standard constructor
protected SunJSSE() {
- super("SunJSSE", 1.6d, info);
+ super("SunJSSE", 1.7d, info);
subclassCheck();
if (Boolean.TRUE.equals(fips)) {
throw new ProviderException
--- a/jdk/src/share/classes/sun/security/util/Password.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/classes/sun/security/util/Password.java Mon Aug 24 22:27:30 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,14 @@
public class Password {
/** Reads user password from given input stream. */
public static char[] readPassword(InputStream in) throws IOException {
+ return readPassword(in, false);
+ }
+
+ /** Reads user password from given input stream.
+ * @param isEchoOn true if the password should be echoed on the screen
+ */
+ public static char[] readPassword(InputStream in, boolean isEchoOn)
+ throws IOException {
char[] consoleEntered = null;
byte[] consoleBytes = null;
@@ -44,7 +52,7 @@
try {
// Use the new java.io.Console class
Console con = null;
- if (in == System.in && ((con = System.console()) != null)) {
+ if (!isEchoOn && in == System.in && ((con = System.console()) != null)) {
consoleEntered = con.readPassword();
// readPassword returns "" if you just print ENTER,
// to be compatible with old Password class, change to null
--- a/jdk/src/share/native/sun/security/ec/ec.c Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/share/native/sun/security/ec/ec.c Mon Aug 24 22:27:30 2009 -0700
@@ -422,7 +422,7 @@
*/
if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
if (randomlen != 2 * len) {
- goto cleanup;
+ randomlen = 2 * len;
}
/* No need to generate - random bytes are now supplied */
/* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
--- a/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java Mon Aug 24 22:27:30 2009 -0700
@@ -248,12 +248,13 @@
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
+ final boolean isPooledThread = (myGroupAndInvokeCount != null);
boolean replaceMe = false;
Event ev;
try {
for (;;) {
// reset invoke count
- if (myGroupAndInvokeCount != null)
+ if (isPooledThread)
myGroupAndInvokeCount.resetInvokeCount();
try {
@@ -289,7 +290,7 @@
// process event
try {
- ev.channel().onEvent(ev.events());
+ ev.channel().onEvent(ev.events(), isPooledThread);
} catch (Error x) {
replaceMe = true; throw x;
} catch (RuntimeException x) {
--- a/jdk/src/solaris/classes/sun/nio/ch/Port.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/Port.java Mon Aug 24 22:27:30 2009 -0700
@@ -49,7 +49,7 @@
* Implemented by clients registered with this port.
*/
interface PollableChannel extends Closeable {
- void onEvent(int events);
+ void onEvent(int events, boolean mayInvokeDirect);
}
// maps fd to "pollable" channel
@@ -121,7 +121,7 @@
final Object attachForeignChannel(final Channel channel, FileDescriptor fd) {
int fdVal = IOUtil.fdVal(fd);
register(fdVal, new PollableChannel() {
- public void onEvent(int events) { }
+ public void onEvent(int events, boolean mayInvokeDirect) { }
public void close() throws IOException {
channel.close();
}
--- a/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Mon Aug 24 22:27:30 2009 -0700
@@ -151,12 +151,13 @@
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
+ final boolean isPooledThread = (myGroupAndInvokeCount != null);
boolean replaceMe = false;
long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
try {
for (;;) {
// reset invoke count
- if (myGroupAndInvokeCount != null)
+ if (isPooledThread)
myGroupAndInvokeCount.resetInvokeCount();
// wait for I/O completion event
@@ -205,7 +206,7 @@
if (ch != null) {
replaceMe = true;
// no need to translate events
- ch.onEvent(events);
+ ch.onEvent(events, isPooledThread);
}
}
} finally {
--- a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -59,10 +59,13 @@
private final Object updateLock = new Object();
// pending accept
- private PendingFuture<AsynchronousSocketChannel,Object> pendingAccept;
+ private boolean acceptPending;
+ private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
+ private Object acceptAttachment;
+ private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
// context for permission check when security manager set
- private AccessControlContext acc;
+ private AccessControlContext acceptAcc;
UnixAsynchronousServerSocketChannelImpl(Port port)
@@ -83,15 +86,6 @@
port.register(fdVal, this);
}
- // returns and clears the result of a pending accept
- private PendingFuture<AsynchronousSocketChannel,Object> grabPendingAccept() {
- synchronized (updateLock) {
- PendingFuture<AsynchronousSocketChannel,Object> result = pendingAccept;
- pendingAccept = null;
- return result;
- }
- }
-
@Override
void implClose() throws IOException {
// remove the mapping
@@ -101,17 +95,27 @@
nd.close(fd);
// if there is a pending accept then complete it
- final PendingFuture<AsynchronousSocketChannel,Object> result =
- grabPendingAccept();
- if (result != null) {
- // discard the stack trace as otherwise it may appear that implClose
- // has thrown the exception.
- AsynchronousCloseException x = new AsynchronousCloseException();
- x.setStackTrace(new StackTraceElement[0]);
- result.setFailure(x);
+ CompletionHandler<AsynchronousSocketChannel,Object> handler;
+ Object att;
+ PendingFuture<AsynchronousSocketChannel,Object> future;
+ synchronized (updateLock) {
+ if (!acceptPending)
+ return; // no pending accept
+ acceptPending = false;
+ handler = acceptHandler;
+ att = acceptAttachment;
+ future = acceptFuture;
+ }
+ // discard the stack trace as otherwise it may appear that implClose
+ // has thrown the exception.
+ AsynchronousCloseException x = new AsynchronousCloseException();
+ x.setStackTrace(new StackTraceElement[0]);
+ if (handler == null) {
+ future.setFailure(x);
+ } else {
// invoke by submitting task rather than directly
- Invoker.invokeIndirectly(result.handler(), result);
+ Invoker.invokeIndirectly(this, handler, att, null, x);
}
}
@@ -124,15 +128,17 @@
* Invoked by event handling thread when listener socket is polled
*/
@Override
- public void onEvent(int events) {
- PendingFuture<AsynchronousSocketChannel,Object> result = grabPendingAccept();
- if (result == null)
- return; // may have been grabbed by asynchronous close
+ public void onEvent(int events, boolean mayInvokeDirect) {
+ synchronized (updateLock) {
+ if (!acceptPending)
+ return; // may have been grabbed by asynchronous close
+ acceptPending = false;
+ }
// attempt to accept connection
FileDescriptor newfd = new FileDescriptor();
InetSocketAddress[] isaa = new InetSocketAddress[1];
- boolean accepted = false;
+ Throwable exc = null;
try {
begin();
int n = accept0(this.fd, newfd, isaa);
@@ -140,49 +146,52 @@
// spurious wakeup, is this possible?
if (n == IOStatus.UNAVAILABLE) {
synchronized (updateLock) {
- this.pendingAccept = result;
+ acceptPending = true;
}
port.startPoll(fdVal, Port.POLLIN);
return;
}
- // connection accepted
- accepted = true;
-
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- enableAccept();
- result.setFailure(x);
+ exc = x;
} finally {
end();
}
// Connection accepted so finish it when not holding locks.
AsynchronousSocketChannel child = null;
- if (accepted) {
+ if (exc == null) {
try {
- child = finishAccept(newfd, isaa[0], acc);
- enableAccept();
- result.setResult(child);
+ child = finishAccept(newfd, isaa[0], acceptAcc);
} catch (Throwable x) {
- enableAccept();
if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x);
- result.setFailure(x);
+ exc = x;
}
}
- // if an async cancel has already cancelled the operation then
- // close the new channel so as to free resources
- if (child != null && result.isCancelled()) {
- try {
- child.close();
- } catch (IOException ignore) { }
+ // copy field befores accept is re-renabled
+ CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
+ Object att = acceptAttachment;
+ PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
+
+ // re-enable accepting and invoke handler
+ enableAccept();
+
+ if (handler == null) {
+ future.setResult(child, exc);
+ // if an async cancel has already cancelled the operation then
+ // close the new channel so as to free resources
+ if (child != null && future.isCancelled()) {
+ try {
+ child.close();
+ } catch (IOException ignore) { }
+ }
+ } else {
+ Invoker.invoke(this, handler, att, child, exc);
}
-
- // invoke the handler
- Invoker.invoke(result.handler(), result);
}
/**
@@ -234,16 +243,18 @@
}
@Override
- @SuppressWarnings("unchecked")
- public <A> Future<AsynchronousSocketChannel> accept(A attachment,
- final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+ Future<AsynchronousSocketChannel> implAccept(Object att,
+ CompletionHandler<AsynchronousSocketChannel,Object> handler)
{
// complete immediately if channel is closed
if (!isOpen()) {
- CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invokeIndirectly(handler, result);
- return result;
+ Throwable e = new ClosedChannelException();
+ if (handler == null) {
+ return CompletedFuture.withFailure(e);
+ } else {
+ Invoker.invoke(this, handler, att, null, e);
+ return null;
+ }
}
if (localAddress == null)
throw new NotYetBoundException();
@@ -258,25 +269,31 @@
throw new AcceptPendingException();
// attempt accept
- AbstractFuture<AsynchronousSocketChannel,A> result = null;
FileDescriptor newfd = new FileDescriptor();
InetSocketAddress[] isaa = new InetSocketAddress[1];
+ Throwable exc = null;
try {
begin();
int n = accept0(this.fd, newfd, isaa);
if (n == IOStatus.UNAVAILABLE) {
- // no connection to accept
- result = new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
// need calling context when there is security manager as
// permission check may be done in a different thread without
// any application call frames on the stack
- synchronized (this) {
- this.acc = (System.getSecurityManager() == null) ?
+ PendingFuture<AsynchronousSocketChannel,Object> result = null;
+ synchronized (updateLock) {
+ if (handler == null) {
+ this.acceptHandler = null;
+ result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
+ this.acceptFuture = result;
+ } else {
+ this.acceptHandler = handler;
+ this.acceptAttachment = att;
+ }
+ this.acceptAcc = (System.getSecurityManager() == null) ?
null : AccessController.getContext();
- this.pendingAccept =
- (PendingFuture<AsynchronousSocketChannel,Object>)result;
+ this.acceptPending = true;
}
// register for connections
@@ -287,25 +304,30 @@
// accept failed
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- result = CompletedFuture.withFailure(this, x, attachment);
+ exc = x;
} finally {
end();
}
- // connection accepted immediately
- if (result == null) {
+ AsynchronousSocketChannel child = null;
+ if (exc == null) {
+ // connection accepted immediately
try {
- AsynchronousSocketChannel ch = finishAccept(newfd, isaa[0], null);
- result = CompletedFuture.withResult(this, ch, attachment);
+ child = finishAccept(newfd, isaa[0], null);
} catch (Throwable x) {
- result = CompletedFuture.withFailure(this, x, attachment);
+ exc = x;
}
}
- // re-enable accepting and invoke handler
+ // re-enable accepting before invoking handler
enableAccept();
- Invoker.invokeIndirectly(handler, result);
- return result;
+
+ if (handler == null) {
+ return CompletedFuture.withResult(child, exc);
+ } else {
+ Invoker.invokeIndirectly(this, handler, att, child, exc);
+ return null;
+ }
}
// -- Native methods --
--- a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -61,20 +61,33 @@
private final Object updateLock = new Object();
// pending connect (updateLock)
- private PendingFuture<Void,Object> pendingConnect;
+ private boolean connectPending;
+ private CompletionHandler<Void,Object> connectHandler;
+ private Object connectAttachment;
+ private PendingFuture<Void,Object> connectFuture;
- // pending remote address (statLock)
+ // pending remote address (stateLock)
private SocketAddress pendingRemote;
// pending read (updateLock)
+ private boolean readPending;
+ private boolean isScatteringRead;
+ private ByteBuffer readBuffer;
private ByteBuffer[] readBuffers;
- private boolean scatteringRead;
- private PendingFuture<Number,Object> pendingRead;
+ private CompletionHandler<Number,Object> readHandler;
+ private Object readAttachment;
+ private PendingFuture<Number,Object> readFuture;
+ private Future<?> readTimer;
// pending write (updateLock)
+ private boolean writePending;
+ private boolean isGatheringWrite;
+ private ByteBuffer writeBuffer;
private ByteBuffer[] writeBuffers;
- private boolean gatheringWrite;
- private PendingFuture<Number,Object> pendingWrite;
+ private CompletionHandler<Number,Object> writeHandler;
+ private Object writeAttachment;
+ private PendingFuture<Number,Object> writeFuture;
+ private Future<?> writeTimer;
UnixAsynchronousSocketChannelImpl(Port port)
@@ -128,43 +141,36 @@
private void updateEvents() {
assert Thread.holdsLock(updateLock);
int events = 0;
- if (pendingRead != null)
+ if (readPending)
events |= Port.POLLIN;
- if (pendingConnect != null || pendingWrite != null)
+ if (connectPending || writePending)
events |= Port.POLLOUT;
if (events != 0)
port.startPoll(fdVal, events);
}
- /**
- * Invoked by event handler thread when file descriptor is polled
- */
- @Override
- public void onEvent(int events) {
- boolean readable = (events & Port.POLLIN) > 0;
- boolean writable = (events & Port.POLLOUT) > 0;
- if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
- readable = true;
- writable = true;
- }
-
- PendingFuture<Void,Object> connectResult = null;
- PendingFuture<Number,Object> readResult = null;
- PendingFuture<Number,Object> writeResult = null;
+ // invoke to finish read and/or write operations
+ private void finish(boolean mayInvokeDirect,
+ boolean readable,
+ boolean writable)
+ {
+ boolean finishRead = false;
+ boolean finishWrite = false;
+ boolean finishConnect = false;
// map event to pending result
synchronized (updateLock) {
- if (readable && (pendingRead != null)) {
- readResult = pendingRead;
- pendingRead = null;
+ if (readable && this.readPending) {
+ this.readPending = false;
+ finishRead = true;
}
if (writable) {
- if (pendingWrite != null) {
- writeResult = pendingWrite;
- pendingWrite = null;
- } else if (pendingConnect != null) {
- connectResult = pendingConnect;
- pendingConnect = null;
+ if (this.writePending) {
+ this.writePending = false;
+ finishWrite = true;
+ } else if (this.connectPending) {
+ this.connectPending = false;
+ finishConnect = true;
}
}
}
@@ -172,36 +178,32 @@
// complete the I/O operation. Special case for when channel is
// ready for both reading and writing. In that case, submit task to
// complete write if write operation has a completion handler.
- if (readResult != null) {
- if (writeResult != null)
- finishWrite(writeResult, false);
- finishRead(readResult, true);
+ if (finishRead) {
+ if (finishWrite)
+ finishWrite(false);
+ finishRead(mayInvokeDirect);
return;
}
- if (writeResult != null) {
- finishWrite(writeResult, true);
+ if (finishWrite) {
+ finishWrite(mayInvokeDirect);
}
- if (connectResult != null) {
- finishConnect(connectResult, true);
+ if (finishConnect) {
+ finishConnect(mayInvokeDirect);
}
}
- // returns and clears the result of a pending read
- PendingFuture<Number,Object> grabPendingRead() {
- synchronized (updateLock) {
- PendingFuture<Number,Object> result = pendingRead;
- pendingRead = null;
- return result;
+ /**
+ * Invoked by event handler thread when file descriptor is polled
+ */
+ @Override
+ public void onEvent(int events, boolean mayInvokeDirect) {
+ boolean readable = (events & Port.POLLIN) > 0;
+ boolean writable = (events & Port.POLLOUT) > 0;
+ if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
+ readable = true;
+ writable = true;
}
- }
-
- // returns and clears the result of a pending write
- PendingFuture<Number,Object> grabPendingWrite() {
- synchronized (updateLock) {
- PendingFuture<Number,Object> result = pendingWrite;
- pendingWrite = null;
- return result;
- }
+ finish(mayInvokeDirect, readable, writable);
}
@Override
@@ -213,26 +215,7 @@
nd.close(fd);
// All outstanding I/O operations are required to fail
- final PendingFuture<Void,Object> readyToConnect;
- final PendingFuture<Number,Object> readyToRead;
- final PendingFuture<Number,Object> readyToWrite;
- synchronized (updateLock) {
- readyToConnect = pendingConnect;
- pendingConnect = null;
- readyToRead = pendingRead;
- pendingRead = null;
- readyToWrite = pendingWrite;
- pendingWrite = null;
- }
- if (readyToConnect != null) {
- finishConnect(readyToConnect, false);
- }
- if (readyToRead != null) {
- finishRead(readyToRead, false);
- }
- if (readyToWrite != null) {
- finishWrite(readyToWrite, false);
- }
+ finish(false, true, true);
}
@Override
@@ -240,9 +223,9 @@
if (task.getContext() == OpType.CONNECT)
killConnect();
if (task.getContext() == OpType.READ)
- killConnect();
+ killReading();
if (task.getContext() == OpType.WRITE)
- killConnect();
+ killWriting();
}
// -- connect --
@@ -255,15 +238,12 @@
}
}
- private void finishConnect(PendingFuture<Void,Object> result,
- boolean invokeDirect)
- {
+ private void finishConnect(boolean mayInvokeDirect) {
Throwable e = null;
try {
begin();
checkConnect(fdVal);
setConnected();
- result.setResult(null);
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
@@ -276,26 +256,38 @@
try {
close();
} catch (IOException ignore) { }
- result.setFailure(e);
}
- if (invokeDirect) {
- Invoker.invoke(result.handler(), result);
+
+
+ // invoke handler and set result
+ CompletionHandler<Void,Object> handler = connectHandler;
+ Object att = connectAttachment;
+ PendingFuture<Void,Object> future = connectFuture;
+ if (handler == null) {
+ future.setResult(null, e);
} else {
- Invoker.invokeIndirectly(result.handler(), result);
+ if (mayInvokeDirect) {
+ Invoker.invokeUnchecked(handler, att, null, e);
+ } else {
+ Invoker.invokeIndirectly(this, handler, att, null, e);
+ }
}
}
@Override
@SuppressWarnings("unchecked")
- public <A> Future<Void> connect(SocketAddress remote,
- A attachment,
- CompletionHandler<Void,? super A> handler)
+ <A> Future<Void> implConnect(SocketAddress remote,
+ A attachment,
+ CompletionHandler<Void,? super A> handler)
{
if (!isOpen()) {
- CompletedFuture<Void,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable e = new ClosedChannelException();
+ if (handler == null) {
+ return CompletedFuture.withFailure(e);
+ } else {
+ Invoker.invoke(this, handler, attachment, null, e);
+ return null;
+ }
}
InetSocketAddress isa = Net.checkAddress(remote);
@@ -317,7 +309,6 @@
notifyBeforeTcpConnect = (localAddress == null);
}
- AbstractFuture<Void,A> result = null;
Throwable e = null;
try {
begin();
@@ -327,15 +318,21 @@
int n = Net.connect(fd, isa.getAddress(), isa.getPort());
if (n == IOStatus.UNAVAILABLE) {
// connection could not be established immediately
- result = new PendingFuture<Void,A>(this, handler, attachment, OpType.CONNECT);
+ PendingFuture<Void,A> result = null;
synchronized (updateLock) {
- this.pendingConnect = (PendingFuture<Void,Object>)result;
+ if (handler == null) {
+ result = new PendingFuture<Void,A>(this, OpType.CONNECT);
+ this.connectFuture = (PendingFuture<Void,Object>)result;
+ } else {
+ this.connectHandler = (CompletionHandler<Void,Object>)handler;
+ this.connectAttachment = attachment;
+ }
+ this.connectPending = true;
updateEvents();
}
return result;
}
setConnected();
- result = CompletedFuture.withResult(this, null, attachment);
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
@@ -349,84 +346,111 @@
try {
close();
} catch (IOException ignore) { }
- result = CompletedFuture.withFailure(this, e, attachment);
}
-
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null) {
+ return CompletedFuture.withResult(null, e);
+ } else {
+ Invoker.invoke(this, handler, attachment, null, e);
+ return null;
+ }
}
// -- read --
- @SuppressWarnings("unchecked")
- private void finishRead(PendingFuture<Number,Object> result,
- boolean invokeDirect)
- {
+ private void finishRead(boolean mayInvokeDirect) {
int n = -1;
- PendingFuture<Number,Object> pending = null;
+ Throwable exc = null;
+
+ // copy fields as we can't access them after reading is re-enabled.
+ boolean scattering = isScatteringRead;
+ CompletionHandler<Number,Object> handler = readHandler;
+ Object att = readAttachment;
+ PendingFuture<Number,Object> future = readFuture;
+ Future<?> timeout = readTimer;
+
try {
begin();
- ByteBuffer[] dsts = readBuffers;
- if (dsts.length == 1) {
- n = IOUtil.read(fd, dsts[0], -1, nd, null);
+ if (scattering) {
+ n = (int)IOUtil.read(fd, readBuffers, nd);
} else {
- n = (int)IOUtil.read(fd, dsts, nd);
+ n = IOUtil.read(fd, readBuffer, -1, nd, null);
}
if (n == IOStatus.UNAVAILABLE) {
// spurious wakeup, is this possible?
- pending = result;
+ synchronized (updateLock) {
+ readPending = true;
+ }
return;
}
- // allow buffer(s) to be GC'ed.
- readBuffers = null;
+ // allow objects to be GC'ed.
+ this.readBuffer = null;
+ this.readBuffers = null;
+ this.readAttachment = null;
// allow another read to be initiated
- boolean wasScatteringRead = scatteringRead;
enableReading();
- // result is Integer or Long
- if (wasScatteringRead) {
- result.setResult(Long.valueOf(n));
- } else {
- result.setResult(Integer.valueOf(n));
- }
-
} catch (Throwable x) {
enableReading();
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- result.setFailure(x);
+ exc = x;
} finally {
// restart poll in case of concurrent write
synchronized (updateLock) {
- if (pending != null)
- this.pendingRead = pending;
updateEvents();
}
end();
}
- if (invokeDirect) {
- Invoker.invoke(result.handler(), result);
+ // cancel the associated timer
+ if (timeout != null)
+ timeout.cancel(false);
+
+ // create result
+ Number result = (exc != null) ? null : (scattering) ?
+ (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+ // invoke handler or set result
+ if (handler == null) {
+ future.setResult(result, exc);
} else {
- Invoker.invokeIndirectly(result.handler(), result);
+ if (mayInvokeDirect) {
+ Invoker.invokeUnchecked(handler, att, result, exc);
+ } else {
+ Invoker.invokeIndirectly(this, handler, att, result, exc);
+ }
}
}
private Runnable readTimeoutTask = new Runnable() {
public void run() {
- PendingFuture<Number,Object> result = grabPendingRead();
- if (result == null)
- return; // already completed
+ CompletionHandler<Number,Object> handler = null;
+ Object att = null;
+ PendingFuture<Number,Object> future = null;
+
+ synchronized (updateLock) {
+ if (!readPending)
+ return;
+ readPending = false;
+ handler = readHandler;
+ att = readAttachment;
+ future = readFuture;
+ }
// kill further reading before releasing waiters
enableReading(true);
- // set completed and invoke handler
- result.setFailure(new InterruptedByTimeoutException());
- Invoker.invokeIndirectly(result.handler(), result);
+ // invoke handler or set result
+ Exception exc = new InterruptedByTimeoutException();
+ if (handler == null) {
+ future.setFailure(exc);
+ } else {
+ AsynchronousChannel ch = UnixAsynchronousSocketChannelImpl.this;
+ Invoker.invokeIndirectly(ch, handler, att, null, exc);
+ }
}
};
@@ -435,8 +459,9 @@
*/
@Override
@SuppressWarnings("unchecked")
- <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
- boolean isScatteringRead,
+ <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+ ByteBuffer dst,
+ ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
@@ -450,144 +475,178 @@
boolean invokeDirect = false;
boolean attemptRead = false;
if (!disableSynchronousRead) {
- myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
- invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
- attemptRead = (handler == null) || invokeDirect ||
- !port.isFixedThreadPool(); // okay to attempt read with user thread pool
+ if (handler == null) {
+ attemptRead = true;
+ } else {
+ myGroupAndInvokeCount = Invoker.getGroupAndInvokeCount();
+ invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
+ // okay to attempt read with user thread pool
+ attemptRead = invokeDirect || !port.isFixedThreadPool();
+ }
}
- AbstractFuture<V,A> result;
+ int n = IOStatus.UNAVAILABLE;
+ Throwable exc = null;
+ boolean pending = false;
+
try {
begin();
- int n;
if (attemptRead) {
if (isScatteringRead) {
n = (int)IOUtil.read(fd, dsts, nd);
} else {
- n = IOUtil.read(fd, dsts[0], -1, nd, null);
+ n = IOUtil.read(fd, dst, -1, nd, null);
}
- } else {
- n = IOStatus.UNAVAILABLE;
}
if (n == IOStatus.UNAVAILABLE) {
- result = new PendingFuture<V,A>(this, handler, attachment, OpType.READ);
-
- // update evetns so that read will complete asynchronously
+ PendingFuture<V,A> result = null;
synchronized (updateLock) {
+ this.isScatteringRead = isScatteringRead;
+ this.readBuffer = dst;
this.readBuffers = dsts;
- this.scatteringRead = isScatteringRead;
- this.pendingRead = (PendingFuture<Number,Object>)result;
+ if (handler == null) {
+ this.readHandler = null;
+ result = new PendingFuture<V,A>(this, OpType.READ);
+ this.readFuture = (PendingFuture<Number,Object>)result;
+ this.readAttachment = null;
+ } else {
+ this.readHandler = (CompletionHandler<Number,Object>)handler;
+ this.readAttachment = attachment;
+ this.readFuture = null;
+ }
+ if (timeout > 0L) {
+ this.readTimer = port.schedule(readTimeoutTask, timeout, unit);
+ }
+ this.readPending = true;
updateEvents();
}
-
- // schedule timeout
- if (timeout > 0L) {
- Future<?> timeoutTask =
- port.schedule(readTimeoutTask, timeout, unit);
- ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
- }
+ pending = true;
return result;
}
-
- // data available
- enableReading();
-
- // result type is Long or Integer
- if (isScatteringRead) {
- result = (CompletedFuture<V,A>)CompletedFuture
- .withResult(this, Long.valueOf(n), attachment);
- } else {
- result = (CompletedFuture<V,A>)CompletedFuture
- .withResult(this, Integer.valueOf(n), attachment);
- }
} catch (Throwable x) {
- enableReading();
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- result = CompletedFuture.withFailure(this, x, attachment);
+ exc = x;
} finally {
+ if (!pending)
+ enableReading();
end();
}
- if (invokeDirect) {
- Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+ Number result = (exc != null) ? null : (isScatteringRead) ?
+ (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+ // read completed immediately
+ if (handler != null) {
+ if (invokeDirect) {
+ Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+ } else {
+ Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+ }
+ return null;
} else {
- Invoker.invokeIndirectly(handler, result);
+ return CompletedFuture.withResult((V)result, exc);
}
- return result;
}
// -- write --
- private void finishWrite(PendingFuture<Number,Object> result,
- boolean invokeDirect)
- {
- PendingFuture<Number,Object> pending = null;
+ private void finishWrite(boolean mayInvokeDirect) {
+ int n = -1;
+ Throwable exc = null;
+
+ // copy fields as we can't access them after reading is re-enabled.
+ boolean gathering = this.isGatheringWrite;
+ CompletionHandler<Number,Object> handler = this.writeHandler;
+ Object att = this.writeAttachment;
+ PendingFuture<Number,Object> future = this.writeFuture;
+ Future<?> timer = this.writeTimer;
+
try {
begin();
- ByteBuffer[] srcs = writeBuffers;
- int n;
- if (srcs.length == 1) {
- n = IOUtil.write(fd, srcs[0], -1, nd, null);
+ if (gathering) {
+ n = (int)IOUtil.write(fd, writeBuffers, nd);
} else {
- n = (int)IOUtil.write(fd, srcs, nd);
+ n = IOUtil.write(fd, writeBuffer, -1, nd, null);
}
if (n == IOStatus.UNAVAILABLE) {
// spurious wakeup, is this possible?
- pending = result;
+ synchronized (updateLock) {
+ writePending = true;
+ }
return;
}
- // allow buffer(s) to be GC'ed.
- writeBuffers = null;
+ // allow objects to be GC'ed.
+ this.writeBuffer = null;
+ this.writeBuffers = null;
+ this.writeAttachment = null;
// allow another write to be initiated
- boolean wasGatheringWrite = gatheringWrite;
enableWriting();
- // result is a Long or Integer
- if (wasGatheringWrite) {
- result.setResult(Long.valueOf(n));
- } else {
- result.setResult(Integer.valueOf(n));
- }
-
} catch (Throwable x) {
enableWriting();
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- result.setFailure(x);
+ exc = x;
} finally {
- // restart poll in case of concurrent read
- synchronized (this) {
- if (pending != null)
- this.pendingWrite = pending;
+ // restart poll in case of concurrent write
+ synchronized (updateLock) {
updateEvents();
}
end();
}
- if (invokeDirect) {
- Invoker.invoke(result.handler(), result);
+
+ // cancel the associated timer
+ if (timer != null)
+ timer.cancel(false);
+
+ // create result
+ Number result = (exc != null) ? null : (gathering) ?
+ (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+ // invoke handler or set result
+ if (handler == null) {
+ future.setResult(result, exc);
} else {
- Invoker.invokeIndirectly(result.handler(), result);
+ if (mayInvokeDirect) {
+ Invoker.invokeUnchecked(handler, att, result, exc);
+ } else {
+ Invoker.invokeIndirectly(this, handler, att, result, exc);
+ }
}
}
private Runnable writeTimeoutTask = new Runnable() {
public void run() {
- PendingFuture<Number,Object> result = grabPendingWrite();
- if (result == null)
- return; // already completed
+ CompletionHandler<Number,Object> handler = null;
+ Object att = null;
+ PendingFuture<Number,Object> future = null;
+
+ synchronized (updateLock) {
+ if (!writePending)
+ return;
+ writePending = false;
+ handler = writeHandler;
+ att = writeAttachment;
+ future = writeFuture;
+ }
// kill further writing before releasing waiters
enableWriting(true);
- // set completed and invoke handler
- result.setFailure(new InterruptedByTimeoutException());
- Invoker.invokeIndirectly(result.handler(), result);
+ // invoke handler or set result
+ Exception exc = new InterruptedByTimeoutException();
+ if (handler != null) {
+ Invoker.invokeIndirectly(UnixAsynchronousSocketChannelImpl.this,
+ handler, att, null, exc);
+ } else {
+ future.setFailure(exc);
+ }
}
};
@@ -596,8 +655,9 @@
*/
@Override
@SuppressWarnings("unchecked")
- <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
- boolean isGatheringWrite,
+ <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
+ ByteBuffer src,
+ ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
@@ -607,66 +667,72 @@
Invoker.getGroupAndInvokeCount();
boolean invokeDirect = Invoker.mayInvokeDirect(myGroupAndInvokeCount, port);
boolean attemptWrite = (handler == null) || invokeDirect ||
- !port.isFixedThreadPool(); // okay to attempt read with user thread pool
+ !port.isFixedThreadPool(); // okay to attempt write with user thread pool
- AbstractFuture<V,A> result;
+ int n = IOStatus.UNAVAILABLE;
+ Throwable exc = null;
+ boolean pending = false;
+
try {
begin();
- int n;
if (attemptWrite) {
if (isGatheringWrite) {
n = (int)IOUtil.write(fd, srcs, nd);
} else {
- n = IOUtil.write(fd, srcs[0], -1, nd, null);
+ n = IOUtil.write(fd, src, -1, nd, null);
}
- } else {
- n = IOStatus.UNAVAILABLE;
}
if (n == IOStatus.UNAVAILABLE) {
- result = new PendingFuture<V,A>(this, handler, attachment, OpType.WRITE);
-
- // update evetns so that read will complete asynchronously
+ PendingFuture<V,A> result = null;
synchronized (updateLock) {
+ this.isGatheringWrite = isGatheringWrite;
+ this.writeBuffer = src;
this.writeBuffers = srcs;
- this.gatheringWrite = isGatheringWrite;
- this.pendingWrite = (PendingFuture<Number,Object>)result;
+ if (handler == null) {
+ this.writeHandler = null;
+ result = new PendingFuture<V,A>(this, OpType.WRITE);
+ this.writeFuture = (PendingFuture<Number,Object>)result;
+ this.writeAttachment = null;
+ } else {
+ this.writeHandler = (CompletionHandler<Number,Object>)handler;
+ this.writeAttachment = attachment;
+ this.writeFuture = null;
+ }
+ if (timeout > 0L) {
+ this.writeTimer = port.schedule(writeTimeoutTask, timeout, unit);
+ }
+ this.writePending = true;
updateEvents();
}
-
- // schedule timeout
- if (timeout > 0L) {
- Future<?> timeoutTask =
- port.schedule(writeTimeoutTask, timeout, unit);
- ((PendingFuture<V,A>)result).setTimeoutTask(timeoutTask);
- }
+ pending = true;
return result;
}
-
- // data available
- enableWriting();
- if (isGatheringWrite) {
- result = (CompletedFuture<V,A>)CompletedFuture
- .withResult(this, Long.valueOf(n), attachment);
- } else {
- result = (CompletedFuture<V,A>)CompletedFuture
- .withResult(this, Integer.valueOf(n), attachment);
- }
} catch (Throwable x) {
- enableWriting();
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
- result = CompletedFuture.withFailure(this, x, attachment);
+ exc = x;
} finally {
+ if (!pending)
+ enableWriting();
end();
}
- if (invokeDirect) {
- Invoker.invokeDirect(myGroupAndInvokeCount, handler, result);
+
+ Number result = (exc != null) ? null : (isGatheringWrite) ?
+ (Number)Long.valueOf(n) : (Number)Integer.valueOf(n);
+
+ // write completed immediately
+ if (handler != null) {
+ if (invokeDirect) {
+ Invoker.invokeDirect(myGroupAndInvokeCount, handler, attachment, (V)result, exc);
+ } else {
+ Invoker.invokeIndirectly(this, handler, attachment, (V)result, exc);
+ }
+ return null;
} else {
- Invoker.invokeIndirectly(handler, result);
+ return CompletedFuture.withResult((V)result, exc);
}
- return result;
}
// -- Native methods --
--- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java Mon Aug 24 22:27:30 2009 -0700
@@ -65,9 +65,6 @@
// array of offsets of elements in path (created lazily)
private volatile int[] offsets;
- // file permissions (created lazily)
- private volatile FilePermission[] perms;
-
UnixPath(UnixFileSystem fs, byte[] path) {
this.fs = fs;
this.path = path;
@@ -768,45 +765,23 @@
}
}
- // create file permissions used for read and write checks
- private void checkReadOrWrite(boolean checkRead) {
- SecurityManager sm = System.getSecurityManager();
- if (sm == null)
- return;
- if (perms == null) {
- synchronized (this) {
- if (perms == null) {
- FilePermission[] p = new FilePermission[2];
- String pathForPermCheck = getPathForPermissionCheck();
- p[0] = new FilePermission(pathForPermCheck,
- SecurityConstants.FILE_READ_ACTION);
- p[1] = new FilePermission(pathForPermCheck,
- SecurityConstants.FILE_WRITE_ACTION);
- perms = p;
- }
- }
- }
- if (checkRead) {
- sm.checkPermission(perms[0]);
- } else {
- sm.checkPermission(perms[1]);
- }
- }
void checkRead() {
- checkReadOrWrite(true);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkRead(getPathForPermissionCheck());
}
void checkWrite() {
- checkReadOrWrite(false);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkWrite(getPathForPermissionCheck());
}
void checkDelete() {
SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- // permission not cached
+ if (sm != null)
sm.checkDelete(getPathForPermissionCheck());
- }
}
@Override
--- a/jdk/src/windows/classes/sun/nio/ch/Iocp.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/Iocp.java Mon Aug 24 22:27:30 2009 -0700
@@ -34,6 +34,8 @@
import java.util.concurrent.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.security.AccessController;
+import sun.security.action.GetPropertyAction;
import sun.misc.Unsafe;
/**
@@ -44,6 +46,7 @@
class Iocp extends AsynchronousChannelGroupImpl {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long INVALID_HANDLE_VALUE = -1L;
+ private static final boolean supportsThreadAgnosticIo;
// maps completion key to channel
private final ReadWriteLock keyToChannelLock = new ReentrantReadWriteLock();
@@ -87,6 +90,13 @@
<V,A> PendingFuture<V,A> getByOverlapped(long overlapped);
}
+ /**
+ * Indicates if this operating system supports thread agnostic I/O.
+ */
+ static boolean supportsThreadAgnosticIo() {
+ return supportsThreadAgnosticIo;
+ }
+
// release all resources
void implClose() {
synchronized (this) {
@@ -216,8 +226,9 @@
} while ((key == 0) || keyToChannel.containsKey(key));
// associate with I/O completion port
- if (handle != 0L)
+ if (handle != 0L) {
createIoCompletionPort(handle, port, key, 0);
+ }
// setup mapping
keyToChannel.put(key, ch);
@@ -282,7 +293,7 @@
/**
* Invoked if the I/O operation completes successfully.
*/
- public void completed(int bytesTransferred);
+ public void completed(int bytesTransferred, boolean canInvokeDirect);
/**
* Invoked if the I/O operation fails.
@@ -305,6 +316,7 @@
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
+ boolean canInvokeDirect = (myGroupAndInvokeCount != null);
CompletionStatus ioResult = new CompletionStatus();
boolean replaceMe = false;
@@ -382,7 +394,7 @@
ResultHandler rh = (ResultHandler)result.getContext();
replaceMe = true; // (if error/exception then replace thread)
if (error == 0) {
- rh.completed(ioResult.bytesTransferred());
+ rh.completed(ioResult.bytesTransferred(), canInvokeDirect);
} else {
rh.failed(error, translateErrorToIOException(error));
}
@@ -433,5 +445,11 @@
static {
Util.load();
initIDs();
+
+ // thread agnostic I/O on Vista/2008 or newer
+ String osversion = AccessController.doPrivileged(
+ new GetPropertyAction("os.version"));
+ String vers[] = osversion.split("\\.");
+ supportsThreadAgnosticIo = Integer.parseInt(vers[0]) >= 6;
}
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -146,10 +146,12 @@
// waits until all I/O operations have completed
ioCache.close();
- // disassociate from port and shutdown thread pool if not default
+ // disassociate from port
iocp.disassociate(completionKey);
+
+ // for the non-default group close the port
if (!isDefaultIocp)
- iocp.shutdown();
+ iocp.detachFromThreadPool();
}
@Override
@@ -258,14 +260,18 @@
}
// invoke completion handler
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
@Override
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
// release waiters and invoke completion handler
result.setResult(fli);
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
@Override
@@ -279,16 +285,16 @@
} else {
result.setFailure(new AsynchronousCloseException());
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
@Override
- public <A> Future<FileLock> lock(long position,
- long size,
- boolean shared,
- A attachment,
- CompletionHandler<FileLock,? super A> handler)
+ <A> Future<FileLock> implLock(final long position,
+ final long size,
+ final boolean shared,
+ A attachment,
+ final CompletionHandler<FileLock,? super A> handler)
{
if (shared && !reading)
throw new NonReadableChannelException();
@@ -298,10 +304,11 @@
// add to lock table
FileLockImpl fli = addToFileLockTable(position, size, shared);
if (fli == null) {
- CompletedFuture<FileLock,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
// create Future and task that will be invoked to acquire lock
@@ -310,13 +317,20 @@
LockTask lockTask = new LockTask<A>(position, fli, result);
result.setContext(lockTask);
- // initiate I/O (can only be done from thread in thread pool)
- try {
- Invoker.invokeOnThreadInThreadPool(this, lockTask);
- } catch (ShutdownChannelGroupException e) {
- // rollback
- removeFromFileLockTable(fli);
- throw e;
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ lockTask.run();
+ } else {
+ boolean executed = false;
+ try {
+ Invoker.invokeOnThreadInThreadPool(this, lockTask);
+ executed = true;
+ } finally {
+ if (!executed) {
+ // rollback
+ removeFromFileLockTable(fli);
+ }
+ }
}
return result;
}
@@ -461,14 +475,14 @@
releaseBufferIfSubstituted();
// invoke completion handler
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
* Executed when the I/O has completed
*/
@Override
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
updatePosition(bytesTransferred);
// return direct buffer to cache if substituted
@@ -476,14 +490,18 @@
// release waiters and invoke completion handler
result.setResult(bytesTransferred);
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
@Override
public void failed(int error, IOException x) {
// if EOF detected asynchronously then it is reported as error
if (error == ERROR_HANDLE_EOF) {
- completed(-1);
+ completed(-1, false);
} else {
// return direct buffer to cache if substituted
releaseBufferIfSubstituted();
@@ -494,16 +512,16 @@
} else {
result.setFailure(new AsynchronousCloseException());
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
}
@Override
- public <A> Future<Integer> read(ByteBuffer dst,
- long position,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ <A> Future<Integer> implRead(ByteBuffer dst,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
if (!reading)
throw new NonReadableChannelException();
@@ -514,10 +532,11 @@
// check if channel is closed
if (!isOpen()) {
- CompletedFuture<Integer,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
int pos = dst.position();
@@ -527,10 +546,10 @@
// no space remaining
if (rem == 0) {
- CompletedFuture<Integer,A> result =
- CompletedFuture.withResult(this, 0, attachment);
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withResult(0);
+ Invoker.invoke(this, handler, attachment, 0, null);
+ return null;
}
// create Future and task that initiates read
@@ -539,8 +558,12 @@
ReadTask readTask = new ReadTask<A>(dst, pos, rem, position, result);
result.setContext(readTask);
- // initiate I/O (can only be done from thread in thread pool)
- Invoker.invokeOnThreadInThreadPool(this, readTask);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ readTask.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, readTask);
+ }
return result;
}
@@ -639,14 +662,14 @@
}
// invoke completion handler
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
* Executed when the I/O has completed
*/
@Override
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
updatePosition(bytesTransferred);
// return direct buffer to cache if substituted
@@ -654,7 +677,11 @@
// release waiters and invoke completion handler
result.setResult(bytesTransferred);
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
@Override
@@ -668,15 +695,14 @@
} else {
result.setFailure(new AsynchronousCloseException());
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
- @Override
- public <A> Future<Integer> write(ByteBuffer src,
- long position,
- A attachment,
- CompletionHandler<Integer,? super A> handler)
+ <A> Future<Integer> implWrite(ByteBuffer src,
+ long position,
+ A attachment,
+ CompletionHandler<Integer,? super A> handler)
{
if (!writing)
throw new NonWritableChannelException();
@@ -685,10 +711,11 @@
// check if channel is closed
if (!isOpen()) {
- CompletedFuture<Integer,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
int pos = src.position();
@@ -698,10 +725,10 @@
// nothing to write
if (rem == 0) {
- CompletedFuture<Integer,A> result =
- CompletedFuture.withResult(this, 0, attachment);
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withResult(0);
+ Invoker.invoke(this, handler, attachment, 0, null);
+ return null;
}
// create Future and task to initiate write
@@ -710,8 +737,12 @@
WriteTask writeTask = new WriteTask<A>(src, pos, rem, position, result);
result.setContext(writeTask);
- // initiate I/O (can only be done from thread in thread pool)
- Invoker.invokeOnThreadInThreadPool(this, writeTask);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ writeTask.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, writeTask);
+ }
return result;
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -113,14 +113,14 @@
/**
* Task to initiate accept operation and to handle result.
*/
- private class AcceptTask<A> implements Runnable, Iocp.ResultHandler {
+ private class AcceptTask implements Runnable, Iocp.ResultHandler {
private final WindowsAsynchronousSocketChannelImpl channel;
private final AccessControlContext acc;
- private final PendingFuture<AsynchronousSocketChannel,A> result;
+ private final PendingFuture<AsynchronousSocketChannel,Object> result;
AcceptTask(WindowsAsynchronousSocketChannelImpl channel,
AccessControlContext acc,
- PendingFuture<AsynchronousSocketChannel,A> result)
+ PendingFuture<AsynchronousSocketChannel,Object> result)
{
this.channel = channel;
this.acc = acc;
@@ -222,14 +222,14 @@
}
// invoke completion handler
- Invoker.invokeIndirectly(result.handler(), result);
+ Invoker.invokeIndirectly(result);
}
/**
* Executed when the I/O has completed
*/
@Override
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
try {
// connection accept after group has shutdown
if (iocp.isShutdown()) {
@@ -269,7 +269,7 @@
}
// invoke handler (but not directly)
- Invoker.invokeIndirectly(result.handler(), result);
+ Invoker.invokeIndirectly(result);
}
@Override
@@ -283,19 +283,20 @@
} else {
result.setFailure(new AsynchronousCloseException());
}
- Invoker.invokeIndirectly(result.handler(), result);
+ Invoker.invokeIndirectly(result);
}
}
@Override
- public <A> Future<AsynchronousSocketChannel> accept(A attachment,
- final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
+ Future<AsynchronousSocketChannel> implAccept(Object attachment,
+ final CompletionHandler<AsynchronousSocketChannel,Object> handler)
{
if (!isOpen()) {
- CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invokeIndirectly(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invokeIndirectly(this, handler, attachment, null, exc);
+ return null;
}
if (isAcceptKilled())
throw new RuntimeException("Accept not allowed due to cancellation");
@@ -319,10 +320,10 @@
end();
}
if (ioe != null) {
- CompletedFuture<AsynchronousSocketChannel,A> result =
- CompletedFuture.withFailure(this, ioe, attachment);
- Invoker.invokeIndirectly(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withFailure(ioe);
+ Invoker.invokeIndirectly(this, handler, attachment, null, ioe);
+ return null;
}
// need calling context when there is security manager as
@@ -331,20 +332,21 @@
AccessControlContext acc = (System.getSecurityManager() == null) ?
null : AccessController.getContext();
- PendingFuture<AsynchronousSocketChannel,A> result =
- new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
- AcceptTask task = new AcceptTask<A>(ch, acc, result);
+ PendingFuture<AsynchronousSocketChannel,Object> result =
+ new PendingFuture<AsynchronousSocketChannel,Object>(this, handler, attachment);
+ AcceptTask task = new AcceptTask(ch, acc, result);
result.setContext(task);
// check and set flag to prevent concurrent accepting
if (!accepting.compareAndSet(false, true))
throw new AcceptPendingException();
- // initiate accept. As I/O operations are tied to the initiating thread
- // then it will only be invoked direcly if this thread is in the thread
- // pool. If this thread is not in the thread pool when a task is
- // submitted to initiate the accept.
- Invoker.invokeOnThreadInThreadPool(this, task);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ task.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, task);
+ }
return result;
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Mon Aug 24 22:27:30 2009 -0700
@@ -250,14 +250,14 @@
closeChannel();
result.setFailure(toIOException(exc));
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
* Invoked by handler thread when connection established.
*/
@Override
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
Throwable exc = null;
try {
begin();
@@ -276,7 +276,11 @@
result.setFailure(toIOException(exc));
}
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
/**
@@ -290,20 +294,21 @@
} else {
result.setFailure(new AsynchronousCloseException());
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
@Override
- public <A> Future<Void> connect(SocketAddress remote,
- A attachment,
- CompletionHandler<Void,? super A> handler)
+ <A> Future<Void> implConnect(SocketAddress remote,
+ A attachment,
+ CompletionHandler<Void,? super A> handler)
{
if (!isOpen()) {
- CompletedFuture<Void,A> result = CompletedFuture
- .withFailure(this, new ClosedChannelException(), attachment);
- Invoker.invoke(handler, result);
- return result;
+ Throwable exc = new ClosedChannelException();
+ if (handler == null)
+ return CompletedFuture.withFailure(exc);
+ Invoker.invoke(this, handler, attachment, null, exc);
+ return null;
}
InetSocketAddress isa = Net.checkAddress(remote);
@@ -337,10 +342,10 @@
try {
close();
} catch (IOException ignore) { }
- CompletedFuture<Void,A> result = CompletedFuture
- .withFailure(this, bindException, attachment);
- Invoker.invoke(handler, result);
- return result;
+ if (handler == null)
+ return CompletedFuture.withFailure(bindException);
+ Invoker.invoke(this, handler, attachment, null, bindException);
+ return null;
}
// setup task
@@ -349,8 +354,12 @@
ConnectTask task = new ConnectTask<A>(isa, result);
result.setContext(task);
- // initiate I/O (can only be done from thread in thread pool)
- Invoker.invokeOnThreadInThreadPool(this, task);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ task.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, task);
+ }
return result;
}
@@ -514,7 +523,7 @@
}
// invoke completion handler
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
@@ -522,7 +531,7 @@
*/
@Override
@SuppressWarnings("unchecked")
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
if (bytesTransferred == 0) {
bytesTransferred = -1; // EOF
} else {
@@ -543,7 +552,11 @@
result.setResult((V)Integer.valueOf(bytesTransferred));
}
}
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
@Override
@@ -561,7 +574,7 @@
enableReading();
result.setFailure(x);
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
@@ -579,13 +592,14 @@
}
// invoke handler without any locks
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
@Override
- <V extends Number,A> Future<V> readImpl(ByteBuffer[] bufs,
- boolean scatteringRead,
+ <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
+ ByteBuffer dst,
+ ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
@@ -594,7 +608,14 @@
// setup task
PendingFuture<V,A> result =
new PendingFuture<V,A>(this, handler, attachment);
- final ReadTask readTask = new ReadTask<V,A>(bufs, scatteringRead, result);
+ ByteBuffer[] bufs;
+ if (isScatteringRead) {
+ bufs = dsts;
+ } else {
+ bufs = new ByteBuffer[1];
+ bufs[0] = dst;
+ }
+ final ReadTask readTask = new ReadTask<V,A>(bufs, isScatteringRead, result);
result.setContext(readTask);
// schedule timeout
@@ -607,8 +628,12 @@
result.setTimeoutTask(timeoutTask);
}
- // initiate I/O (can only be done from thread in thread pool)
- Invoker.invokeOnThreadInThreadPool(this, readTask);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ readTask.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, readTask);
+ }
return result;
}
@@ -710,7 +735,7 @@
}
@Override
- @SuppressWarnings("unchecked")
+ //@SuppressWarnings("unchecked")
public void run() {
long overlapped = 0L;
boolean prepared = false;
@@ -759,7 +784,7 @@
}
// invoke completion handler
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
@@ -767,7 +792,7 @@
*/
@Override
@SuppressWarnings("unchecked")
- public void completed(int bytesTransferred) {
+ public void completed(int bytesTransferred, boolean canInvokeDirect) {
updateBuffers(bytesTransferred);
// return direct buffer to cache if substituted
@@ -784,7 +809,11 @@
result.setResult((V)Integer.valueOf(bytesTransferred));
}
}
- Invoker.invoke(result.handler(), result);
+ if (canInvokeDirect) {
+ Invoker.invokeUnchecked(result);
+ } else {
+ Invoker.invoke(result);
+ }
}
@Override
@@ -802,7 +831,7 @@
enableWriting();
result.setFailure(x);
}
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
/**
@@ -820,13 +849,14 @@
}
// invoke handler without any locks
- Invoker.invoke(result.handler(), result);
+ Invoker.invoke(result);
}
}
@Override
- <V extends Number,A> Future<V> writeImpl(ByteBuffer[] bufs,
- boolean gatheringWrite,
+ <V extends Number,A> Future<V> implWrite(boolean gatheringWrite,
+ ByteBuffer src,
+ ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
@@ -835,6 +865,13 @@
// setup task
PendingFuture<V,A> result =
new PendingFuture<V,A>(this, handler, attachment);
+ ByteBuffer[] bufs;
+ if (gatheringWrite) {
+ bufs = srcs;
+ } else {
+ bufs = new ByteBuffer[1];
+ bufs[0] = src;
+ }
final WriteTask writeTask = new WriteTask<V,A>(bufs, gatheringWrite, result);
result.setContext(writeTask);
@@ -849,7 +886,12 @@
}
// initiate I/O (can only be done from thread in thread pool)
- Invoker.invokeOnThreadInThreadPool(this, writeTask);
+ // initiate I/O
+ if (Iocp.supportsThreadAgnosticIo()) {
+ writeTask.run();
+ } else {
+ Invoker.invokeOnThreadInThreadPool(this, writeTask);
+ }
return result;
}
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Mon Aug 24 22:27:30 2009 -0700
@@ -46,6 +46,7 @@
@Override
public WindowsFileAttributes readAttributes() throws IOException {
+ file.checkRead();
try {
return WindowsFileAttributes.get(file, followLinks);
} catch (WindowsException x) {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java Mon Aug 24 22:27:30 2009 -0700
@@ -246,8 +246,8 @@
long lastWriteTime = unsafe.getLong(address + OFFSETOF_FIND_DATA_LASTWRITETIME);
long size = ((long)(unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZEHIGH)) << 32)
+ (unsafe.getInt(address + OFFSETOF_FIND_DATA_SIZELOW) & 0xFFFFFFFFL);
- int reparseTag = ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) ?
- + unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
+ int reparseTag = isReparsePoint(fileAttrs) ?
+ unsafe.getInt(address + OFFSETOF_FIND_DATA_RESERVED0) : 0;
return new WindowsFileAttributes(fileAttrs,
creationTime,
lastAccessTime,
@@ -275,7 +275,7 @@
int reparseTag = 0;
int fileAttrs = unsafe
.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
- if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
+ if (isReparsePoint(fileAttrs)) {
int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size);
try {
@@ -311,7 +311,7 @@
// just return the attributes
int fileAttrs = unsafe
.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
- if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+ if (!isReparsePoint(fileAttrs))
return fromFileAttributeData(address, 0);
} catch (WindowsException x) {
if (x.lastError() != ERROR_SHARING_VIOLATION)
@@ -358,7 +358,7 @@
}
/**
- * Returns true if the attribtues are of the same file - both files must
+ * Returns true if the attributes are of the same file - both files must
* be open.
*/
static boolean isSameFile(WindowsFileAttributes attrs1,
@@ -370,6 +370,13 @@
(attrs1.fileIndexLow == attrs2.fileIndexLow);
}
+ /**
+ * Returns true if the attributes are of a file with a reparse point.
+ */
+ static boolean isReparsePoint(int attributes) {
+ return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ }
+
// package-private
int attributes() {
return fileAttrs;
@@ -420,7 +427,7 @@
// package private
boolean isReparsePoint() {
- return (fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+ return isReparsePoint(fileAttrs);
}
boolean isDirectoryLink() {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java Mon Aug 24 22:27:30 2009 -0700
@@ -283,25 +283,15 @@
}
}
- // match in uppercase
- StringBuilder sb = new StringBuilder(expr.length());
- for (int i=0; i<expr.length(); i++) {
- sb.append(Character.toUpperCase(expr.charAt(i)));
- }
- expr = sb.toString();
+ // match in unicode_case_insensitive
+ final Pattern pattern = Pattern.compile(expr,
+ Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
// return matcher
- final Pattern pattern = Pattern.compile(expr);
return new PathMatcher() {
@Override
public boolean matches(Path path) {
- // match in uppercase
- String s = path.toString();
- StringBuilder sb = new StringBuilder(s.length());
- for (int i=0; i<s.length(); i++) {
- sb.append( Character.toUpperCase(s.charAt(i)) );
- }
- return pattern.matcher(sb).matches();
+ return pattern.matcher(path.toString()).matches();
}
};
}
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Mon Aug 24 22:27:30 2009 -0700
@@ -63,6 +63,30 @@
}
/**
+ * Returns the final path (all symbolic links resolved) or null if this
+ * operation is not supported.
+ */
+ private static String getFinalPath(WindowsPath input) throws IOException {
+ long h = 0;
+ try {
+ h = input.openForReadAttributeAccess(true);
+ } catch (WindowsException x) {
+ x.rethrowAsIOException(input);
+ }
+ try {
+ return stripPrefix(GetFinalPathNameByHandle(h));
+ } catch (WindowsException x) {
+ // ERROR_INVALID_LEVEL is the error returned when not supported
+ // (a sym link to file on FAT32 or Samba server for example)
+ if (x.lastError() != ERROR_INVALID_LEVEL)
+ x.rethrowAsIOException(input);
+ } finally {
+ CloseHandle(h);
+ }
+ return null;
+ }
+
+ /**
* Returns the final path of a given path as a String. This should be used
* prior to calling Win32 system calls that do not follow links.
*/
@@ -70,7 +94,6 @@
throws IOException
{
WindowsFileSystem fs = input.getFileSystem();
-
try {
// if not following links then don't need final path
if (!followLinks || !fs.supportsLinks())
@@ -84,25 +107,10 @@
x.rethrowAsIOException(input);
}
- // The file is a symbolic link so we open it and try to get the
- // normalized path. This should succeed on NTFS but may fail if there
- // is a link to a non-NFTS file system.
- long h = 0;
- try {
- h = input.openForReadAttributeAccess(true);
- } catch (WindowsException x) {
- x.rethrowAsIOException(input);
- }
- try {
- return stripPrefix(GetFinalPathNameByHandle(h));
- } catch (WindowsException x) {
- // ERROR_INVALID_LEVEL is the error returned when not supported by
- // the file system
- if (x.lastError() != ERROR_INVALID_LEVEL)
- x.rethrowAsIOException(input);
- } finally {
- CloseHandle(h);
- }
+ // The file is a symbolic link so attempt to get the final path
+ String result = getFinalPath(input);
+ if (result != null)
+ return result;
// Fallback: read target of link, resolve against parent, and repeat
// until file is not a link.
@@ -149,31 +157,9 @@
throws IOException
{
WindowsFileSystem fs = input.getFileSystem();
- if (!fs.supportsLinks())
+ if (resolveLinks && !fs.supportsLinks())
resolveLinks = false;
- // On Vista use GetFinalPathNameByHandle. This should succeed on NTFS
- // but may fail if there is a link to a non-NFTS file system.
- if (resolveLinks) {
- long h = 0;
- try {
- h = input.openForReadAttributeAccess(true);
- } catch (WindowsException x) {
- x.rethrowAsIOException(input);
- }
- try {
- return stripPrefix(GetFinalPathNameByHandle(h));
- } catch (WindowsException x) {
- if (x.lastError() != ERROR_INVALID_LEVEL)
- x.rethrowAsIOException(input);
- } finally {
- CloseHandle(h);
- }
- }
-
- // Not resolving links or we are on Windows Vista (or newer) with a
- // link to non-NFTS file system.
-
// Start with absolute path
String path = null;
try {
@@ -183,15 +169,12 @@
}
// Collapse "." and ".."
- try {
- path = GetFullPathName(path);
- } catch (WindowsException x) {
- x.rethrowAsIOException(input);
- }
-
- // eliminate all symbolic links
- if (resolveLinks) {
- path = resolveAllLinks(WindowsPath.createFromNormalizedPath(fs, path));
+ if (path.indexOf('.') >= 0) {
+ try {
+ path = GetFullPathName(path);
+ } catch (WindowsException x) {
+ x.rethrowAsIOException(input);
+ }
}
// string builder to build up components of path
@@ -229,12 +212,15 @@
throw new AssertionError("path type not recognized");
}
- // check root directory exists
- try {
- FirstFile fileData = FindFirstFile(sb.toString() + "*");
- FindClose(fileData.handle());
- } catch (WindowsException x) {
- x.rethrowAsIOException(path);
+ // if the result is only a root component then we simply check it exists
+ if (start >= path.length()) {
+ String result = sb.toString();
+ try {
+ GetFileAttributes(result);
+ } catch (WindowsException x) {
+ x.rethrowAsIOException(path);
+ }
+ return result;
}
// iterate through each component to get its actual name in the
@@ -246,13 +232,28 @@
String search = sb.toString() + path.substring(curr, end);
try {
FirstFile fileData = FindFirstFile(addLongPathPrefixIfNeeded(search));
- try {
- sb.append(fileData.name());
- if (next != -1) {
- sb.append('\\');
+ FindClose(fileData.handle());
+
+ // if a reparse point is encountered then we must return the
+ // final path.
+ if (resolveLinks &&
+ WindowsFileAttributes.isReparsePoint(fileData.attributes()))
+ {
+ String result = getFinalPath(input);
+ if (result == null) {
+ // Fallback to slow path, usually because there is a sym
+ // link to a file system that doesn't support sym links.
+ WindowsPath resolved = resolveAllLinks(
+ WindowsPath.createFromNormalizedPath(fs, path));
+ result = getRealPath(resolved, false);
}
- } finally {
- FindClose(fileData.handle());
+ return result;
+ }
+
+ // add the name to the result
+ sb.append(fileData.name());
+ if (next != -1) {
+ sb.append('\\');
}
} catch (WindowsException e) {
e.rethrowAsIOException(path);
@@ -342,7 +343,7 @@
/**
* Resolve all symbolic-links in a given absolute and normalized path
*/
- private static String resolveAllLinks(WindowsPath path)
+ private static WindowsPath resolveAllLinks(WindowsPath path)
throws IOException
{
assert path.isAbsolute();
@@ -401,7 +402,7 @@
}
}
- return path.toString();
+ return path;
}
/**
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java Mon Aug 24 22:27:30 2009 -0700
@@ -180,10 +180,12 @@
static class FirstFile {
private long handle;
private String name;
+ private int attributes;
private FirstFile() { }
public long handle() { return handle; }
public String name() { return name; }
+ public int attributes() { return attributes; }
}
private static native void FindFirstFile0(long lpFileName, FirstFile obj)
throws WindowsException;
--- a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c Mon Aug 24 22:27:30 2009 -0700
@@ -51,13 +51,25 @@
jfieldID path;
} ids;
+/**
+ * GetFinalPathNameByHandle is available on Windows Vista and newer
+ */
+typedef BOOL (WINAPI* GetFinalPathNameByHandleProc) (HANDLE, LPWSTR, DWORD, DWORD);
+static GetFinalPathNameByHandleProc GetFinalPathNameByHandle_func;
+
JNIEXPORT void JNICALL
Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
{
+ HANDLE handle;
jclass fileClass = (*env)->FindClass(env, "java/io/File");
if (!fileClass) return;
ids.path =
(*env)->GetFieldID(env, fileClass, "path", "Ljava/lang/String;");
+ handle = LoadLibrary("kernel32");
+ if (handle != NULL) {
+ GetFinalPathNameByHandle_func = (GetFinalPathNameByHandleProc)
+ GetProcAddress(handle, "GetFinalPathNameByHandleW");
+ }
}
/* -- Path operations -- */
@@ -65,6 +77,138 @@
extern int wcanonicalize(const WCHAR *path, WCHAR *out, int len);
extern int wcanonicalizeWithPrefix(const WCHAR *canonicalPrefix, const WCHAR *pathWithCanonicalPrefix, WCHAR *out, int len);
+/**
+ * Retrieves the fully resolved (final) path for the given path or NULL
+ * if the function fails.
+ */
+static WCHAR* getFinalPath(const WCHAR *path)
+{
+ HANDLE h;
+ WCHAR *result;
+ DWORD error;
+
+ /* Need Windows Vista or newer to get the final path */
+ if (GetFinalPathNameByHandle_func == NULL)
+ return NULL;
+
+ h = CreateFileW(path,
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_DELETE |
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ /**
+ * Allocate a buffer for the resolved path. For a long path we may need
+ * to allocate a larger buffer.
+ */
+ result = (WCHAR*)malloc(MAX_PATH * sizeof(WCHAR));
+ if (result != NULL) {
+ DWORD len = (*GetFinalPathNameByHandle_func)(h, result, MAX_PATH, 0);
+ if (len >= MAX_PATH) {
+ /* retry with a buffer of the right size */
+ result = (WCHAR*)realloc(result, (len+1) * sizeof(WCHAR));
+ if (result != NULL) {
+ len = (*GetFinalPathNameByHandle_func)(h, result, len, 0);
+ } else {
+ len = 0;
+ }
+ }
+ if (len > 0) {
+ /**
+ * Strip prefix (should be \\?\ or \\?\UNC)
+ */
+ if (result[0] == L'\\' && result[1] == L'\\' &&
+ result[2] == L'?' && result[3] == L'\\')
+ {
+ int isUnc = (result[4] == L'U' &&
+ result[5] == L'N' &&
+ result[6] == L'C');
+ int prefixLen = (isUnc) ? 7 : 4;
+ /* actual result length (includes terminator) */
+ int resultLen = len - prefixLen + (isUnc ? 1 : 0) + 1;
+
+ /* copy result without prefix into new buffer */
+ WCHAR *tmp = (WCHAR*)malloc(resultLen * sizeof(WCHAR));
+ if (tmp == NULL) {
+ len = 0;
+ } else {
+ WCHAR *p = result;
+ p += prefixLen;
+ if (isUnc) {
+ WCHAR *p2 = tmp;
+ p2[0] = L'\\';
+ p2++;
+ wcscpy(p2, p);
+ } else {
+ wcscpy(tmp, p);
+ }
+ free(result);
+ result = tmp;
+ }
+ }
+ }
+
+ /* unable to get final path */
+ if (len == 0 && result != NULL) {
+ free(result);
+ result = NULL;
+ }
+ }
+
+ error = GetLastError();
+ if (CloseHandle(h))
+ SetLastError(error);
+ return result;
+}
+
+/**
+ * Retrieves file information for the specified file. If the file is
+ * symbolic link then the information on fully resolved target is
+ * returned.
+ */
+static BOOL getFileInformation(const WCHAR *path,
+ BY_HANDLE_FILE_INFORMATION *finfo)
+{
+ BOOL result;
+ DWORD error;
+ HANDLE h = CreateFileW(path,
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_DELETE |
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return FALSE;
+ result = GetFileInformationByHandle(h, finfo);
+ error = GetLastError();
+ if (CloseHandle(h))
+ SetLastError(error);
+ return result;
+}
+
+/**
+ * If the given attributes are the attributes of a reparse point, then
+ * read and return the attributes of the final target.
+ */
+DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
+{
+ if ((a != INVALID_FILE_ATTRIBUTES) &&
+ ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+ {
+ BY_HANDLE_FILE_INFORMATION finfo;
+ BOOL res = getFileInformation(path, &finfo);
+ a = (res) ? finfo.dwFileAttributes : INVALID_FILE_ATTRIBUTES;
+ }
+ return a;
+}
+
JNIEXPORT jstring JNICALL
Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
jstring pathname)
@@ -202,12 +346,15 @@
return rv;
if (!isReservedDeviceNameW(pathbuf)) {
if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
- rv = (java_io_FileSystem_BA_EXISTS
- | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- ? java_io_FileSystem_BA_DIRECTORY
- : java_io_FileSystem_BA_REGULAR)
- | ((wfad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- ? java_io_FileSystem_BA_HIDDEN : 0));
+ DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
+ if (a != INVALID_FILE_ATTRIBUTES) {
+ rv = (java_io_FileSystem_BA_EXISTS
+ | ((a & FILE_ATTRIBUTE_DIRECTORY)
+ ? java_io_FileSystem_BA_DIRECTORY
+ : java_io_FileSystem_BA_REGULAR)
+ | ((a & FILE_ATTRIBUTE_HIDDEN)
+ ? java_io_FileSystem_BA_HIDDEN : 0));
+ }
} else { /* pagefile.sys is a special case */
if (GetLastError() == ERROR_SHARING_VIOLATION) {
rv = java_io_FileSystem_BA_EXISTS;
@@ -234,6 +381,7 @@
if (pathbuf == NULL)
return JNI_FALSE;
attr = GetFileAttributesW(pathbuf);
+ attr = getFinalAttributesIfReparsePoint(pathbuf, attr);
free(pathbuf);
if (attr == INVALID_FILE_ATTRIBUTES)
return JNI_FALSE;
@@ -272,6 +420,20 @@
if (pathbuf == NULL)
return JNI_FALSE;
a = GetFileAttributesW(pathbuf);
+
+ /* if reparse point, get final target */
+ if ((a != INVALID_FILE_ATTRIBUTES) &&
+ ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+ {
+ WCHAR *fp = getFinalPath(pathbuf);
+ if (fp == NULL) {
+ a = INVALID_FILE_ATTRIBUTES;
+ } else {
+ free(pathbuf);
+ pathbuf = fp;
+ a = GetFileAttributesW(pathbuf);
+ }
+ }
if (a != INVALID_FILE_ATTRIBUTES) {
if (enable)
a = a & ~FILE_ATTRIBUTE_READONLY;
@@ -305,7 +467,7 @@
/* Open existing or fail */
OPEN_EXISTING,
/* Backup semantics for directories */
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+ FILE_FLAG_BACKUP_SEMANTICS,
/* No template file */
NULL);
if (h != INVALID_HANDLE_VALUE) {
@@ -332,7 +494,16 @@
if (GetFileAttributesExW(pathbuf,
GetFileExInfoStandard,
&wfad)) {
- rv = wfad.nFileSizeHigh * ((jlong)MAXDWORD + 1) + wfad.nFileSizeLow;
+ if ((wfad.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
+ rv = wfad.nFileSizeHigh * ((jlong)MAXDWORD + 1) + wfad.nFileSizeLow;
+ } else {
+ /* file is a reparse point so read attributes of final target */
+ BY_HANDLE_FILE_INFORMATION finfo;
+ if (getFileInformation(pathbuf, &finfo)) {
+ rv = finfo.nFileSizeHigh * ((jlong)MAXDWORD + 1) +
+ finfo.nFileSizeLow;
+ }
+ }
} else {
if (GetLastError() == ERROR_SHARING_VIOLATION) {
/* The error is "share violation", which means the file/dir
@@ -360,31 +531,29 @@
if (pathbuf == NULL)
return JNI_FALSE;
h = CreateFileW(
- pathbuf, /* Wide char path name */
- GENERIC_READ | GENERIC_WRITE, /* Read and write permission */
+ pathbuf, /* Wide char path name */
+ GENERIC_READ | GENERIC_WRITE, /* Read and write permission */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* File sharing flags */
- NULL, /* Security attributes */
- CREATE_NEW, /* creation disposition */
- FILE_ATTRIBUTE_NORMAL, /* flags and attributes */
+ NULL, /* Security attributes */
+ CREATE_NEW, /* creation disposition */
+ FILE_ATTRIBUTE_NORMAL |
+ FILE_FLAG_OPEN_REPARSE_POINT, /* flags and attributes */
NULL);
if (h == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
if ((error != ERROR_FILE_EXISTS) && (error != ERROR_ALREADY_EXISTS)) {
-
- // If a directory by the named path already exists,
- // return false (behavior of solaris and linux) instead of
- // throwing an exception
- DWORD fattr = GetFileAttributesW(pathbuf);
- if ((fattr == INVALID_FILE_ATTRIBUTES) ||
- (fattr & ~FILE_ATTRIBUTE_DIRECTORY)) {
+ // return false rather than throwing an exception when there is
+ // an existing file.
+ DWORD a = GetFileAttributesW(pathbuf);
+ if (a == INVALID_FILE_ATTRIBUTES) {
SetLastError(error);
JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
}
}
free(pathbuf);
return JNI_FALSE;
- }
+ }
free(pathbuf);
CloseHandle(h);
return JNI_TRUE;
@@ -396,9 +565,9 @@
/* Returns 0 on success */
DWORD a;
- SetFileAttributesW(path, 0);
+ SetFileAttributesW(path, FILE_ATTRIBUTE_NORMAL);
a = GetFileAttributesW(path);
- if (a == ((DWORD)-1)) {
+ if (a == INVALID_FILE_ATTRIBUTES) {
return 1;
} else if (a & FILE_ATTRIBUTE_DIRECTORY) {
return !RemoveDirectoryW(path);
@@ -578,8 +747,13 @@
HANDLE h;
if (pathbuf == NULL)
return JNI_FALSE;
- h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
+ h = CreateFileW(pathbuf,
+ FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
if (h != INVALID_HANDLE_VALUE) {
LARGE_INTEGER modTime;
FILETIME t;
@@ -607,6 +781,21 @@
if (pathbuf == NULL)
return JNI_FALSE;
a = GetFileAttributesW(pathbuf);
+
+ /* if reparse point, get final target */
+ if ((a != INVALID_FILE_ATTRIBUTES) &&
+ ((a & FILE_ATTRIBUTE_REPARSE_POINT) != 0))
+ {
+ WCHAR *fp = getFinalPath(pathbuf);
+ if (fp == NULL) {
+ a = INVALID_FILE_ATTRIBUTES;
+ } else {
+ free(pathbuf);
+ pathbuf = fp;
+ a = GetFileAttributesW(pathbuf);
+ }
+ }
+
if (a != INVALID_FILE_ATTRIBUTES) {
if (SetFileAttributesW(pathbuf, a | FILE_ATTRIBUTE_READONLY))
rv = JNI_TRUE;
--- a/jdk/src/windows/native/sun/nio/ch/Iocp.c Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/native/sun/nio/ch/Iocp.c Mon Aug 24 22:27:30 2009 -0700
@@ -58,6 +58,16 @@
completionStatus_overlapped = (*env)->GetFieldID(env, clazz, "overlapped", "J");
}
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Iocp_osMajorVersion(JNIEnv* env, jclass this)
+{
+ OSVERSIONINFOEX ver;
+ ver.dwOSVersionInfoSize = sizeof(ver);
+ GetVersionEx((OSVERSIONINFO *) &ver);
+ return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) ?
+ (jint)(ver.dwMajorVersion) : (jint)0;
+}
+
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this,
jlong handle, jlong existingPort, jint completionKey, jint concurrency)
--- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c Mon Aug 24 22:27:30 2009 -0700
@@ -48,6 +48,7 @@
*/
static jfieldID findFirst_handle;
static jfieldID findFirst_name;
+static jfieldID findFirst_attributes;
static jfieldID findStream_handle;
static jfieldID findStream_name;
@@ -134,6 +135,7 @@
}
findFirst_handle = (*env)->GetFieldID(env, clazz, "handle", "J");
findFirst_name = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
+ findFirst_attributes = (*env)->GetFieldID(env, clazz, "attributes", "I");
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$FirstStream");
if (clazz == NULL) {
@@ -371,6 +373,7 @@
return;
(*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle));
(*env)->SetObjectField(env, obj, findFirst_name, name);
+ (*env)->SetIntField(env, obj, findFirst_attributes, data.dwFileAttributes);
} else {
throwWindowsException(env, GetLastError());
}
@@ -387,7 +390,7 @@
if (handle == INVALID_HANDLE_VALUE) {
throwWindowsException(env, GetLastError());
}
- return ptr_to_jlong(handle);
+ return ptr_to_jlong(handle);
}
JNIEXPORT jstring JNICALL
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/security/auth/callback/TextCallbackHandler/Password.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6825240
+ * @summary Password.readPassword() echos the input when System.Console is null
+ * @ignore run these by hand
+ */
+
+import com.sun.security.auth.callback.TextCallbackHandler;
+import javax.security.auth.callback.*;
+
+public class Password {
+ public static void main(String args[]) throws Exception {
+ TextCallbackHandler h = new TextCallbackHandler();
+ PasswordCallback nc = new PasswordCallback("Invisible: ", false);
+ PasswordCallback nc2 = new PasswordCallback("Visible: ", true);
+
+ System.out.println("Two passwords will be prompted for. The first one " +
+ "should have echo off, the second one on. Otherwise, this test fails");
+ Callback[] callbacks = { nc, nc2 };
+ h.handle(callbacks);
+ System.out.println("You input " + new String(nc.getPassword()) +
+ " and " + new String(nc2.getPassword()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/File/SymLinks.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6595866
+ * @summary Test java.io.File operations with sym links
+ */
+
+import java.io.*;
+import java.nio.file.Path;
+import java.nio.file.attribute.*;
+import static java.nio.file.LinkOption.*;
+
+public class SymLinks {
+ final static PrintStream out = System.out;
+
+ final static File top = new File(System.getProperty("test.dir", "."));
+
+ // files used by the test
+
+ final static File file = new File(top, "foofile");
+ final static File link2file = new File(top, "link2file");
+ final static File link2link2file = new File(top, "link2link2file");
+
+ final static File dir = new File(top, "foodir");
+ final static File link2dir = new File(top, "link2dir");
+ final static File link2link2dir = new File(top, "link2link2dir");
+
+ final static File link2nobody = new File(top, "link2nobody");
+ final static File link2link2nobody = new File(top, "link2link2nobody");
+
+ /**
+ * Setup files, directories, and sym links used by test.
+ */
+ static void setup() throws IOException {
+ // link2link2file -> link2file -> foofile
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(new byte[16*1024]);
+ } finally {
+ fos.close();
+ }
+ mklink(link2file, file);
+ mklink(link2link2file, link2file);
+
+ // link2link2dir -> link2dir -> dir
+ assertTrue(dir.mkdir());
+ mklink(link2dir, dir);
+ mklink(link2link2dir, link2dir);
+
+ // link2link2nobody -> link2nobody -> <does-not-exist>
+ mklink(link2nobody, new File(top, "DoesNotExist"));
+ mklink(link2link2nobody, link2nobody);
+ }
+
+ /**
+ * Remove files, directories, and sym links used by test.
+ */
+ static void cleanup() throws IOException {
+ if (file != null)
+ file.delete();
+ if (link2file != null)
+ link2file.toPath().deleteIfExists();
+ if (link2link2file != null)
+ link2link2file.toPath().deleteIfExists();
+ if (dir != null)
+ dir.delete();
+ if (link2dir != null)
+ link2dir.toPath().deleteIfExists();
+ if (link2link2dir != null)
+ link2link2dir.toPath().deleteIfExists();
+ if (link2nobody != null)
+ link2nobody.toPath().deleteIfExists();
+ if (link2link2nobody != null)
+ link2link2nobody.toPath().deleteIfExists();
+ }
+
+ /**
+ * Creates a sym link source->target
+ */
+ static void mklink(File source, File target) throws IOException {
+ source.toPath().createSymbolicLink(target.toPath());
+ }
+
+ /**
+ * Returns true if the "link" exists and is a sym link.
+ */
+ static boolean isSymLink(File link) {
+ try {
+ BasicFileAttributes attrs =
+ Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
+ return attrs.isSymbolicLink();
+ } catch (IOException x) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the last modified time of a sym link.
+ */
+ static long lastModifiedOfSymLink(File link) throws IOException {
+ BasicFileAttributes attrs =
+ Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS);
+ assertTrue(attrs.isSymbolicLink());
+ return attrs.lastModifiedTime().toMillis();
+ }
+
+ /**
+ * Returns true if sym links are supported on the file system where
+ * "dir" exists.
+ */
+ static boolean supportsSymLinks(File dir) {
+ Path link = dir.toPath().resolve("link");
+ Path target = dir.toPath().resolve("target");
+ try {
+ link.createSymbolicLink(target);
+ link.delete();
+ return true;
+ } catch (UnsupportedOperationException x) {
+ return false;
+ } catch (IOException x) {
+ return false;
+ }
+ }
+
+ static void assertTrue(boolean v) {
+ if (!v) throw new RuntimeException("Test failed");
+ }
+
+ static void assertFalse(boolean v) {
+ assertTrue(!v);
+ }
+
+ static void header(String h) {
+ out.println();
+ out.println();
+ out.println("-- " + h + " --");
+ }
+
+ /**
+ * Tests go here.
+ */
+ static void go() throws IOException {
+
+ // check setup
+ assertTrue(file.isFile());
+ assertTrue(isSymLink(link2file));
+ assertTrue(isSymLink(link2link2file));
+ assertTrue(dir.isDirectory());
+ assertTrue(isSymLink(link2dir));
+ assertTrue(isSymLink(link2link2dir));
+ assertTrue(isSymLink(link2nobody));
+ assertTrue(isSymLink(link2link2nobody));
+
+ header("createNewFile");
+
+ assertFalse(file.createNewFile());
+ assertFalse(link2file.createNewFile());
+ assertFalse(link2link2file.createNewFile());
+ assertFalse(dir.createNewFile());
+ assertFalse(link2dir.createNewFile());
+ assertFalse(link2link2dir.createNewFile());
+ assertFalse(link2nobody.createNewFile());
+ assertFalse(link2link2nobody.createNewFile());
+
+ header("mkdir");
+
+ assertFalse(file.mkdir());
+ assertFalse(link2file.mkdir());
+ assertFalse(link2link2file.mkdir());
+ assertFalse(dir.mkdir());
+ assertFalse(link2dir.mkdir());
+ assertFalse(link2link2dir.mkdir());
+ assertFalse(link2nobody.mkdir());
+ assertFalse(link2link2nobody.mkdir());
+
+ header("delete");
+
+ File link = new File(top, "mylink");
+ try {
+ mklink(link, file);
+ assertTrue(link.delete());
+ assertTrue(!isSymLink(link));
+ assertTrue(file.exists());
+
+ mklink(link, link2file);
+ assertTrue(link.delete());
+ assertTrue(!isSymLink(link));
+ assertTrue(link2file.exists());
+
+ mklink(link, dir);
+ assertTrue(link.delete());
+ assertTrue(!isSymLink(link));
+ assertTrue(dir.exists());
+
+ mklink(link, link2dir);
+ assertTrue(link.delete());
+ assertTrue(!isSymLink(link));
+ assertTrue(link2dir.exists());
+
+ mklink(link, link2nobody);
+ assertTrue(link.delete());
+ assertTrue(!isSymLink(link));
+ assertTrue(isSymLink(link2nobody));
+
+ } finally {
+ link.toPath().deleteIfExists();
+ }
+
+ header("renameTo");
+
+ File newlink = new File(top, "newlink");
+ assertTrue(link2file.renameTo(newlink));
+ try {
+ assertTrue(file.exists());
+ assertTrue(isSymLink(newlink));
+ assertTrue(!isSymLink(link2file));
+ } finally {
+ newlink.renameTo(link2file); // restore link
+ }
+
+ assertTrue(link2dir.renameTo(newlink));
+ try {
+ assertTrue(dir.exists());
+ assertTrue(isSymLink(newlink));
+ assertTrue(!isSymLink(link2dir));
+ } finally {
+ newlink.renameTo(link2dir); // restore link
+ }
+
+ header("list");
+
+ final String name = "entry";
+ File entry = new File(dir, name);
+ try {
+ assertTrue(dir.list().length == 0); // directory should be empty
+ assertTrue(link2dir.list().length == 0);
+ assertTrue(link2link2dir.list().length == 0);
+
+ assertTrue(entry.createNewFile());
+ assertTrue(dir.list().length == 1);
+ assertTrue(dir.list()[0].equals(name));
+
+ // access directory by following links
+ assertTrue(link2dir.list().length == 1);
+ assertTrue(link2dir.list()[0].equals(name));
+ assertTrue(link2link2dir.list().length == 1);
+ assertTrue(link2link2dir.list()[0].equals(name));
+
+ // files that are not directories
+ assertTrue(link2file.list() == null);
+ assertTrue(link2nobody.list() == null);
+
+ } finally {
+ entry.delete();
+ }
+
+ header("isXXX");
+
+ assertTrue(file.isFile());
+ assertTrue(link2file.isFile());
+ assertTrue(link2link2file.isFile());
+
+ assertTrue(dir.isDirectory());
+ assertTrue(link2dir.isDirectory());
+ assertTrue(link2link2dir.isDirectory());
+
+ // on Windows we test with the DOS hidden attribute set
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ DosFileAttributeView view = file.toPath()
+ .getFileAttributeView(DosFileAttributeView.class);
+ view.setHidden(true);
+ try {
+ assertTrue(file.isHidden());
+ assertTrue(link2file.isHidden());
+ assertTrue(link2link2file.isHidden());
+ } finally {
+ view.setHidden(false);
+ }
+ assertFalse(file.isHidden());
+ assertFalse(link2file.isHidden());
+ assertFalse(link2link2file.isHidden());
+ }
+
+ header("length");
+
+ long len = file.length();
+ assertTrue(len > 0L);
+ // these tests should follow links
+ assertTrue(link2file.length() == len);
+ assertTrue(link2link2file.length() == len);
+ assertTrue(link2nobody.length() == 0L);
+
+ header("lastModified / setLastModified");
+
+ // need time to diff between link and file
+ long origLastModified = file.lastModified();
+ assertTrue(origLastModified != 0L);
+ try { Thread.sleep(2000); } catch (InterruptedException x) { }
+ file.setLastModified(System.currentTimeMillis());
+
+ long lastModified = file.lastModified();
+ assertTrue(lastModified != origLastModified);
+ assertTrue(lastModifiedOfSymLink(link2file) != lastModified);
+ assertTrue(lastModifiedOfSymLink(link2link2file) != lastModified);
+ assertTrue(link2file.lastModified() == lastModified);
+ assertTrue(link2link2file.lastModified() == lastModified);
+ assertTrue(link2nobody.lastModified() == 0L);
+
+ origLastModified = dir.lastModified();
+ assertTrue(origLastModified != 0L);
+ dir.setLastModified(0L);
+ assertTrue(dir.lastModified() == 0L);
+ assertTrue(link2dir.lastModified() == 0L);
+ assertTrue(link2link2dir.lastModified() == 0L);
+ dir.setLastModified(origLastModified);
+
+ header("setXXX / canXXX");
+
+ assertTrue(file.canRead());
+ assertTrue(file.canWrite());
+ assertTrue(link2file.canRead());
+ assertTrue(link2file.canWrite());
+ assertTrue(link2link2file.canRead());
+ assertTrue(link2link2file.canWrite());
+
+ if (file.setReadOnly()) {
+ assertFalse(file.canWrite());
+ assertFalse(link2file.canWrite());
+ assertFalse(link2link2file.canWrite());
+
+ assertTrue(file.setWritable(true)); // make writable
+ assertTrue(file.canWrite());
+ assertTrue(link2file.canWrite());
+ assertTrue(link2link2file.canWrite());
+
+ assertTrue(link2file.setReadOnly()); // make read only
+ assertFalse(file.canWrite());
+ assertFalse(link2file.canWrite());
+ assertFalse(link2link2file.canWrite());
+
+ assertTrue(link2link2file.setWritable(true)); // make writable
+ assertTrue(file.canWrite());
+ assertTrue(link2file.canWrite());
+ assertTrue(link2link2file.canWrite());
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ if (supportsSymLinks(top)) {
+ try {
+ setup();
+ go();
+ } finally {
+ cleanup();
+ }
+ }
+ }
+
+}
--- a/jdk/test/java/lang/String/Split.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/lang/String/Split.java Mon Aug 24 22:27:30 2009 -0700
@@ -23,14 +23,18 @@
/**
* @test
+ * @bug 6840246
* @summary test String.split()
*/
+import java.util.Arrays;
+import java.util.Random;
import java.util.regex.*;
public class Split {
public static void main(String[] args) throws Exception {
String source = "0123456789";
+
for (int limit=-2; limit<3; limit++) {
for (int x=0; x<10; x++) {
String[] result = source.split(Integer.toString(x), limit);
@@ -80,5 +84,48 @@
throw new RuntimeException("String.split failure 8");
if (!result[0].equals(source))
throw new RuntimeException("String.split failure 9");
+
+ // check fastpath of String.split()
+ source = "0123456789abcdefgABCDEFG";
+ Random r = new Random();
+
+ for (boolean doEscape: new boolean[] {false, true}) {
+ for (int cp = 0; cp < 0x11000; cp++) {
+ Pattern p = null;
+ String regex = new String(Character.toChars(cp));
+ if (doEscape)
+ regex = "\\" + regex;
+ try {
+ p = Pattern.compile(regex);
+ } catch (PatternSyntaxException pse) {
+ // illegal syntax
+ try {
+ "abc".split(regex);
+ } catch (PatternSyntaxException pse0) {
+ continue;
+ }
+ throw new RuntimeException("String.split failure 11");
+ }
+ int off = r.nextInt(source.length());
+ String[] srcStrs = new String[] {
+ "",
+ source,
+ regex + source,
+ source + regex,
+ source.substring(0, 3)
+ + regex + source.substring(3, 9)
+ + regex + source.substring(9, 15)
+ + regex + source.substring(15),
+ source.substring(0, off) + regex + source.substring(off)
+ };
+ for (String src: srcStrs) {
+ for (int limit=-2; limit<3; limit++) {
+ if (!Arrays.equals(src.split(regex, limit),
+ p.split(src, limit)))
+ throw new RuntimeException("String.split failure 12");
+ }
+ }
+ }
+ }
}
}
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousChannelGroup
*/
@@ -50,8 +50,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
@@ -97,9 +95,6 @@
System.out.println("Read failed (expected)");
latch.countDown();
}
- public void cancelled(Void att) {
- throw new RuntimeException();
- }
});
// close channel or shutdown group
@@ -122,9 +117,6 @@
public void failed(Throwable exc, Void att) {
throw new RuntimeException(exc);
}
- public void cancelled(Void att) {
- throw new RuntimeException();
- }
});
latch.await();
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousChannelGroup
*/
@@ -90,14 +90,10 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
SocketAddress sa = new InetSocketAddress(InetAddress.getLocalHost(), port);
@@ -141,9 +137,6 @@
public void failed(Throwable exc, Integer groupId) {
fail(exc.getMessage());
}
- public void cancelled(Integer groupId) {
- fail("I/O operation was cancelled");
- }
});
// wait until
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousChannelGroup
* @build Restart
* @run main/othervm -XX:-UseVMInterruptibleIO Restart
@@ -111,8 +111,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// establish loopback connection which should cause completion
--- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousChannelGroup
*/
@@ -52,8 +52,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
System.out.println("Listener created.");
@@ -97,8 +95,6 @@
}
public void failed(Throwable exc, AsynchronousSocketChannel ch) {
}
- public void cancelled(AsynchronousSocketChannel ch) {
- }
});
}
System.out.println("All read operations outstanding.");
--- a/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4527345
+ * @bug 4527345 6842687
* @summary Unit test for AsynchronousDatagramChannel
*/
@@ -72,8 +72,6 @@
}
public void failed (Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
Thread.sleep(2000);
sender.send(ByteBuffer.wrap(msg), sa);
@@ -88,8 +86,6 @@
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
- public void cancelled(Void att) {
- }
});
Throwable result;
while ((result = exception.get()) == null) {
@@ -107,8 +103,6 @@
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
- public void cancelled(Void att) {
- }
});
ch.close();
while ((result = exception.get()) == null) {
@@ -162,8 +156,6 @@
}
public void failed (Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
Thread.sleep(2000);
sender.send(ByteBuffer.wrap(msg), sa);
@@ -178,8 +170,6 @@
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
- public void cancelled(Void att) {
- }
});
Throwable result;
while ((result = exception.get()) == null) {
@@ -197,8 +187,6 @@
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
- public void cancelled(Void att) {
- }
});
ch.close();
while ((result = exception.get()) == null) {
@@ -246,8 +234,6 @@
}
public void failed (Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
l2.await(5, TimeUnit.SECONDS);
@@ -272,8 +258,6 @@
throw new RuntimeException(exc);
}
}
- public void cancelled(Void att) {
- }
});
l3.await(5, TimeUnit.SECONDS);
@@ -323,8 +307,6 @@
}
public void failed (Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
l2.await(5, TimeUnit.SECONDS);
@@ -340,7 +322,7 @@
reader.close();
}
- static void cancelAndCheck(Future<?> result, CountDownLatch latch)
+ static void cancelAndCheck(Future<?> result)
throws InterruptedException
{
boolean cancelled = result.cancel(false);
@@ -356,37 +338,22 @@
} catch (ExecutionException e) {
throw new RuntimeException("Should not fail");
}
-
- // make sure that completion handler is invoked
- latch.await();
}
// basic cancel tests
static void doCancelTests() throws Exception {
InetAddress lh = InetAddress.getLocalHost();
- // timed and non-timed receive
+ // receive
for (int i=0; i<2; i++) {
AsynchronousDatagramChannel ch =
AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
- final CountDownLatch latch = new CountDownLatch(1);
- long timeout = (i == 0) ? 0L : 60L;
- Future<SocketAddress> remote = ch
- .receive(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, (Void)null,
- new CompletionHandler<SocketAddress,Void>() {
- public void completed(SocketAddress source, Void att) {
- }
- public void failed (Throwable exc, Void att) {
- }
- public void cancelled(Void att) {
- latch.countDown();
- }
- });
- cancelAndCheck(remote, latch);
+ Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100));
+ cancelAndCheck(remote);
ch.close();
}
- // timed and non-timed read
+ // read
for (int i=0; i<2; i++) {
AsynchronousDatagramChannel ch =
AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
@@ -394,18 +361,8 @@
((InetSocketAddress)(ch.getLocalAddress())).getPort()));
final CountDownLatch latch = new CountDownLatch(1);
long timeout = (i == 0) ? 0L : 60L;
- Future<Integer> result = ch
- .read(ByteBuffer.allocate(100), timeout, TimeUnit.SECONDS, (Void)null,
- new CompletionHandler<Integer,Void>() {
- public void completed(Integer bytesRead, Void att) {
- }
- public void failed (Throwable exc, Void att) {
- }
- public void cancelled(Void att) {
- latch.countDown();
- }
- });
- cancelAndCheck(result, latch);
+ Future<Integer> result = ch.read(ByteBuffer.allocate(100));
+ cancelAndCheck(result);
ch.close();
}
}
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272 6822643 6830721
+ * @bug 4607272 6822643 6830721 6842687
* @summary Unit test for AsynchronousFileChannel
*/
@@ -195,8 +195,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
throw new RuntimeException("OverlappingFileLockException expected");
} catch (OverlappingFileLockException x) {
@@ -229,8 +227,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// wait for handler to complete
@@ -318,8 +314,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
await(latch);
@@ -338,8 +332,41 @@
}
} finally {
ch.close();
+ executor.shutdown();
}
}
+
+
+ // test sharing a thread pool between many channels
+ ExecutorService executor = Executors
+ .newFixedThreadPool(1+rand.nextInt(10), threadFactory);
+ final int n = 50 + rand.nextInt(50);
+ AsynchronousFileChannel[] channels = new AsynchronousFileChannel[n];
+ try {
+ for (int i=0; i<n; i++) {
+ Set<StandardOpenOption> opts = EnumSet.of(WRITE);
+ channels[i] = AsynchronousFileChannel.open(file, opts, executor);
+ final CountDownLatch latch = new CountDownLatch(1);
+ channels[i].write(genBuffer(), 0L, (Void)null, new CompletionHandler<Integer,Void>() {
+ public void completed(Integer result, Void att) {
+ latch.countDown();
+ }
+ public void failed(Throwable exc, Void att) {
+ }
+ });
+ await(latch);
+
+ // close ~half the channels
+ if (rand.nextBoolean())
+ channels[i].close();
+ }
+ } finally {
+ // close remaining channels
+ for (int i=0; i<n; i++) {
+ if (channels[i] != null) channels[i].close();
+ }
+ executor.shutdown();
+ }
}
// exercise asynchronous close
@@ -409,17 +436,7 @@
.open(file, WRITE, SYNC);
// start write operation
- final CountDownLatch latch = new CountDownLatch(1);
- Future<Integer> res = ch.write(genBuffer(), 0L, (Void)null,
- new CompletionHandler<Integer,Void>() {
- public void completed(Integer result, Void att) {
- }
- public void failed(Throwable exc, Void att) {
- }
- public void cancelled(Void att) {
- latch.countDown();
- }
- });
+ Future<Integer> res = ch.write(genBuffer(), 0L);
// cancel operation
boolean cancelled = res.cancel(mayInterruptIfRunning);
@@ -456,10 +473,6 @@
throw new RuntimeException(x);
}
- // check that cancelled method is invoked
- if (cancelled)
- await(latch);
-
ch.close();
}
}
@@ -547,8 +560,6 @@
}
public void failed(Throwable exc, Long position) {
}
- public void cancelled(Long position) {
- }
});
// wait for writes to complete
@@ -574,8 +585,6 @@
}
public void failed(Throwable exc, Long position) {
}
- public void cancelled(Long position) {
- }
});
// wait for reads to complete
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for java.nio.channels.AsynchronousFileChannel
* @build CustomThreadPool MyThreadFactory
* @run main/othervm -Djava.nio.channels.DefaultThreadPool.threadFactory=MyThreadFactory CustomThreadPool
@@ -51,8 +51,6 @@
}
public void failed(Throwable exc, AtomicReference<Thread> invoker) {
}
- public void cancelled(AtomicReference<Thread> invoker) {
- }
});
Thread t;
while ((t = invoker.get()) == null) {
--- a/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Mon Aug 24 22:27:30 2009 -0700
@@ -23,7 +23,7 @@
/* @test
- * @bug 4607272 6814948
+ * @bug 4607272 6814948 6842687
* @summary Unit test for AsynchronousFileChannel#lock method
*/
@@ -97,7 +97,7 @@
slave.lock(0, 10, false);
// this VM acquires lock on non-overlapping range
- fl = ch.lock(10, 10, false, null, null).get();
+ fl = ch.lock(10, 10, false).get();
fl.release();
// done
--- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousServerSocketChannel
* @run main/timeout=180 Basic
*/
@@ -104,8 +104,6 @@
public void failed(Throwable exc, Void att) {
exception.set(exc);
}
- public void cancelled(Void att) {
- }
});
// check AcceptPendingException
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4607272
+ * @bug 4607272 6842687
* @summary Unit test for AsynchronousSocketChannel
* @run main/timeout=600 Basic
*/
@@ -187,8 +187,6 @@
public void failed(Throwable exc, Void att) {
connectException.set(exc);
}
- public void cancelled(Void att) {
- }
});
while (connectException.get() == null) {
Thread.sleep(100);
@@ -289,8 +287,6 @@
public void failed(Throwable x, AsynchronousSocketChannel ch) {
writeException.set(x);
}
- public void cancelled(AsynchronousSocketChannel ch) {
- }
});
// give time for socket buffer to fill up.
@@ -330,18 +326,8 @@
SocketChannel peer = server.accept();
// start read operation
- final CountDownLatch latch = new CountDownLatch(1);
ByteBuffer buf = ByteBuffer.allocate(1);
- Future<Integer> res = ch.read(buf, (Void)null,
- new CompletionHandler<Integer,Void>() {
- public void completed(Integer result, Void att) {
- }
- public void failed(Throwable exc, Void att) {
- }
- public void cancelled(Void att) {
- latch.countDown();
- }
- });
+ Future<Integer> res = ch.read(buf);
// cancel operation
boolean cancelled = res.cancel(mayInterruptIfRunning);
@@ -362,8 +348,11 @@
} catch (CancellationException x) {
}
- // check that completion handler executed.
- latch.await();
+ // check that the cancel doesn't impact writing to the channel
+ if (!mayInterruptIfRunning) {
+ buf = ByteBuffer.wrap("a".getBytes());
+ ch.write(buf).get();
+ }
ch.close();
peer.close();
@@ -408,8 +397,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
latch.await();
@@ -460,8 +447,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// trickle the writing
@@ -507,26 +492,24 @@
}
// scattering read that completes ascynhronously
- final CountDownLatch latch = new CountDownLatch(1);
+ final CountDownLatch l1 = new CountDownLatch(1);
ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
new CompletionHandler<Long,Void>() {
public void completed(Long result, Void att) {
long n = result;
if (n <= 0)
throw new RuntimeException("No bytes read");
- latch.countDown();
+ l1.countDown();
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// write some bytes
sc.write(genBuffer());
// read should now complete
- latch.await();
+ l1.await();
// write more bytes
sc.write(genBuffer());
@@ -535,10 +518,20 @@
for (int i=0; i<dsts.length; i++) {
dsts[i].rewind();
}
- long n = ch
- .read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null, null).get();
- if (n <= 0)
- throw new RuntimeException("No bytes read");
+
+ final CountDownLatch l2 = new CountDownLatch(1);
+ ch.read(dsts, 0, dsts.length, 0L, TimeUnit.SECONDS, (Void)null,
+ new CompletionHandler<Long,Void>() {
+ public void completed(Long result, Void att) {
+ long n = result;
+ if (n <= 0)
+ throw new RuntimeException("No bytes read");
+ l2.countDown();
+ }
+ public void failed(Throwable exc, Void att) {
+ }
+ });
+ l2.await();
ch.close();
sc.close();
@@ -574,8 +567,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// read to EOF or buffer full
@@ -613,19 +604,29 @@
ch.connect(server.address()).get();
SocketChannel sc = server.accept();
+ // number of bytes written
+ final AtomicLong bytesWritten = new AtomicLong(0);
+
// write buffers (should complete immediately)
ByteBuffer[] srcs = genBuffers(1);
- long n = ch
- .write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null, null).get();
- if (n <= 0)
- throw new RuntimeException("No bytes written");
+ final CountDownLatch l1 = new CountDownLatch(1);
+ ch.write(srcs, 0, srcs.length, 0L, TimeUnit.SECONDS, (Void)null,
+ new CompletionHandler<Long,Void>() {
+ public void completed(Long result, Void att) {
+ long n = result;
+ if (n <= 0)
+ throw new RuntimeException("No bytes read");
+ bytesWritten.addAndGet(n);
+ l1.countDown();
+ }
+ public void failed(Throwable exc, Void att) {
+ }
+ });
+ l1.await();
// set to true to signal that no more buffers should be written
final AtomicBoolean continueWriting = new AtomicBoolean(true);
- // number of bytes written
- final AtomicLong bytesWritten = new AtomicLong(n);
-
// write until socket buffer is full so as to create the conditions
// for when a write does not complete immediately
srcs = genBuffers(1);
@@ -644,8 +645,6 @@
}
public void failed(Throwable exc, Void att) {
}
- public void cancelled(Void att) {
- }
});
// give time for socket buffer to fill up.
@@ -658,7 +657,7 @@
ByteBuffer buf = ByteBuffer.allocateDirect(4096);
long total = 0L;
do {
- n = sc.read(buf);
+ int n = sc.read(buf);
if (n <= 0)
throw new RuntimeException("No bytes read");
buf.rewind();
@@ -714,15 +713,27 @@
System.out.println("-- timeout when reading --");
+ ByteBuffer dst = ByteBuffer.allocate(512);
+
+ final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
+
// this read should timeout
- ByteBuffer dst = ByteBuffer.allocate(512);
- try {
- ch.read(dst, 3, TimeUnit.SECONDS, (Void)null, null).get();
- throw new RuntimeException("Read did not timeout");
- } catch (ExecutionException x) {
- if (!(x.getCause() instanceof InterruptedByTimeoutException))
- throw new RuntimeException("InterruptedByTimeoutException expected");
+ ch.read(dst, 3, TimeUnit.SECONDS, (Void)null,
+ new CompletionHandler<Integer,Void>()
+ {
+ public void completed(Integer result, Void att) {
+ throw new RuntimeException("Should not complete");
+ }
+ public void failed(Throwable exc, Void att) {
+ readException.set(exc);
+ }
+ });
+ // wait for exception
+ while (readException.get() == null) {
+ Thread.sleep(100);
}
+ if (!(readException.get() instanceof InterruptedByTimeoutException))
+ throw new RuntimeException("InterruptedByTimeoutException expected");
// after a timeout then further reading should throw unspecified runtime exception
boolean exceptionThrown = false;
@@ -752,8 +763,6 @@
public void failed(Throwable exc, AsynchronousSocketChannel ch) {
writeException.set(exc);
}
- public void cancelled(AsynchronousSocketChannel ch) {
- }
});
// wait for exception
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6842687
+ * @summary Unit test for AsynchronousSocketChannel/AsynchronousServerSocketChannel
+ */
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.net.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Initiates I/O operation on a thread that terminates before the I/O completes.
+ */
+
+public class DieBeforeComplete {
+
+ public static void main(String[] args) throws Exception {
+ final AsynchronousServerSocketChannel listener =
+ AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+
+ InetAddress lh = InetAddress.getLocalHost();
+ int port = ((InetSocketAddress) (listener.getLocalAddress())).getPort();
+ final SocketAddress sa = new InetSocketAddress(lh, port);
+
+ // -- accept --
+
+ // initiate accept in a thread that dies before connection is established
+ Future<AsynchronousSocketChannel> r1 =
+ initiateAndDie(new Task<AsynchronousSocketChannel>() {
+ public Future<AsynchronousSocketChannel> run() {
+ return listener.accept();
+ }});
+
+ // establish and accept connection
+ SocketChannel peer = SocketChannel.open(sa);
+ final AsynchronousSocketChannel channel = r1.get();
+
+ // --- read --
+
+ // initiate read in a thread that dies befores bytes are available
+ final ByteBuffer dst = ByteBuffer.allocate(100);
+ Future<Integer> r2 = initiateAndDie(new Task<Integer>() {
+ public Future<Integer> run() {
+ return channel.read(dst);
+ }});
+
+ // send bytes
+ peer.write(ByteBuffer.wrap("hello".getBytes()));
+ int nread = r2.get();
+ if (nread <= 0)
+ throw new RuntimeException("Should have read at least one byte");
+
+ // -- write --
+
+ // initiate writes in threads that dies
+ boolean completedImmediately;
+ Future<Integer> r3;
+ do {
+ final ByteBuffer src = ByteBuffer.wrap(new byte[10000]);
+ r3 = initiateAndDie(new Task<Integer>() {
+ public Future<Integer> run() {
+ return channel.write(src);
+ }});
+ try {
+ int nsent = r3.get(5, TimeUnit.SECONDS);
+ if (nsent <= 0)
+ throw new RuntimeException("Should have wrote at least one byte");
+ completedImmediately = true;
+ } catch (TimeoutException x) {
+ completedImmediately = false;
+ }
+ } while (completedImmediately);
+
+ // drain connection
+ peer.configureBlocking(false);
+ ByteBuffer src = ByteBuffer.allocateDirect(10000);
+ do {
+ src.clear();
+ nread = peer.read(src);
+ if (nread == 0) {
+ Thread.sleep(100);
+ nread = peer.read(src);
+ }
+ } while (nread > 0);
+
+ // write should complete now
+ int nsent = r3.get();
+ if (nsent <= 0)
+ throw new RuntimeException("Should have wrote at least one byte");
+ }
+
+ static interface Task<T> {
+ Future<T> run();
+ }
+
+ static <T> Future<T> initiateAndDie(final Task<T> task) {
+ final AtomicReference<Future<T>> result = new AtomicReference<Future<T>>();
+ Runnable r = new Runnable() {
+ public void run() {
+ result.set(task.run());
+ }
+ };
+ Thread t = new Thread(r);
+ t.start();
+ while (t.isAlive()) {
+ try {
+ t.join();
+ } catch (InterruptedException x) {
+ }
+ }
+ return result.get();
+ }
+}
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 6834246
+ * @bug 6834246 6842687
* @summary Stress test connections through the loopback interface
*/
@@ -114,8 +114,6 @@
exc.printStackTrace();
closeUnchecked(channel);
}
- public void cancelled(Void att) {
- }
});
}
@@ -156,8 +154,6 @@
exc.printStackTrace();
closeUnchecked(channel);
}
- public void cancelled(Void att) {
- }
});
}
--- a/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 6543863
+ * @bug 6543863 6842687
* @summary Try to cause a deadlock between (Asynchronous)FileChannel.close
* and FileLock.release
*/
@@ -56,7 +56,7 @@
AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE);
for (int i=0; i<LOCK_COUNT; i++) {
try {
- locks[i] = ch.lock(i, 1, true, null, null).get();
+ locks[i] = ch.lock(i, 1, true).get();
} catch (InterruptedException x) {
throw new RuntimeException(x);
} catch (ExecutionException x) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Path/CheckPermissions.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,695 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 6866804
+ * @summary Unit test for java.nio.file.Path
+ * @library ..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.nio.channels.SeekableByteChannel;
+import java.security.Permission;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Checks each method that accesses the file system does the right permission
+ * check when there is a security manager set.
+ */
+
+public class CheckPermissions {
+
+ static class Checks {
+ private List<Permission> permissionsChecked = new ArrayList<Permission>();
+ private Set<String> propertiesChecked = new HashSet<String>();
+ private List<String> readsChecked = new ArrayList<String>();
+ private List<String> writesChecked = new ArrayList<String>();
+ private List<String> deletesChecked = new ArrayList<String>();
+ private List<String> execsChecked = new ArrayList<String>();
+
+ List<Permission> permissionsChecked() { return permissionsChecked; }
+ Set<String> propertiesChecked() { return propertiesChecked; }
+ List<String> readsChecked() { return readsChecked; }
+ List<String> writesChecked() { return writesChecked; }
+ List<String> deletesChecked() { return deletesChecked; }
+ List<String> execsChecked() { return execsChecked; }
+ }
+
+ static ThreadLocal<Checks> myChecks =
+ new ThreadLocal<Checks>() {
+ @Override protected Checks initialValue() {
+ return null;
+ }
+ };
+
+ static void prepare() {
+ myChecks.set(new Checks());
+ }
+
+ static void assertCheckPermission(Class<? extends Permission> type,
+ String name)
+ {
+ for (Permission perm: myChecks.get().permissionsChecked()) {
+ if (type.isInstance(perm) && perm.getName().equals(name))
+ return;
+ }
+ throw new RuntimeException(type.getName() + "\"" + name + "\") not checked");
+ }
+
+ static void assertCheckPropertyAccess(String key) {
+ if (!myChecks.get().propertiesChecked().contains(key))
+ throw new RuntimeException("Property " + key + " not checked");
+ }
+
+ static void assertChecked(Path file, List<String> list) {
+ String s = file.toString();
+ for (String f: list) {
+ if (f.endsWith(s))
+ return;
+ }
+ throw new RuntimeException("Access not checked");
+ }
+
+ static void assertCheckRead(Path file) {
+ assertChecked(file, myChecks.get().readsChecked());
+ }
+
+ static void assertCheckWrite(Path file) {
+ assertChecked(file, myChecks.get().writesChecked());
+ }
+
+ static void assertCheckDelete(Path file) {
+ assertChecked(file, myChecks.get().deletesChecked());
+ }
+
+ static void assertCheckExec(Path file) {
+ assertChecked(file, myChecks.get().execsChecked());
+ }
+
+ static class LoggingSecurityManager extends SecurityManager {
+ static void install() {
+ System.setSecurityManager(new LoggingSecurityManager());
+ }
+
+ @Override
+ public void checkPermission(Permission perm) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.permissionsChecked().add(perm);
+ }
+
+ @Override
+ public void checkPropertyAccess(String key) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.propertiesChecked().add(key);
+ }
+
+ @Override
+ public void checkRead(String file) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.readsChecked().add(file);
+ }
+
+ @Override
+ public void checkWrite(String file) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.writesChecked().add(file);
+ }
+
+ @Override
+ public void checkDelete(String file) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.deletesChecked().add(file);
+ }
+
+ @Override
+ public void checkExec(String file) {
+ Checks checks = myChecks.get();
+ if (checks != null)
+ checks.execsChecked().add(file);
+ }
+ }
+
+ static void testBasicFileAttributeView(BasicFileAttributeView view, Path file)
+ throws IOException
+ {
+ prepare();
+ view.readAttributes();
+ assertCheckRead(file);
+
+ prepare();
+ FileTime now = FileTime.fromMillis(System.currentTimeMillis());
+ view.setTimes(null, now, now);
+ assertCheckWrite(file);
+ }
+
+ static void testPosixFileAttributeView(PosixFileAttributeView view, Path file)
+ throws IOException
+ {
+ prepare();
+ PosixFileAttributes attrs = view.readAttributes();
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+ prepare();
+ view.setPermissions(attrs.permissions());
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+ prepare();
+ view.setOwner(attrs.owner());
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+ prepare();
+ view.setOwner(attrs.owner());
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+ }
+
+ public static void main(String[] args) throws IOException {
+ Path dir = Paths.get(System.getProperty("test.src", "."));
+ Path file = dir.resolve("file1234").createFile();
+ try {
+ LoggingSecurityManager.install();
+
+ // -- checkAccess --
+
+ prepare();
+ file.checkAccess();
+ assertCheckRead(file);
+
+ prepare();
+ file.checkAccess(AccessMode.READ);
+ assertCheckRead(file);
+
+ prepare();
+ file.checkAccess(AccessMode.WRITE);
+ assertCheckWrite(file);
+
+ prepare();
+ try {
+ file.checkAccess(AccessMode.EXECUTE);
+ } catch (AccessDeniedException x) { }
+ assertCheckExec(file);
+
+ prepare();
+ try {
+ file.checkAccess(AccessMode.READ, AccessMode.WRITE, AccessMode.EXECUTE);
+ } catch (AccessDeniedException x) { }
+ assertCheckRead(file);
+ assertCheckWrite(file);
+ assertCheckExec(file);
+
+ // -- copyTo --
+
+ Path target = dir.resolve("target1234");
+ prepare();
+ file.copyTo(target);
+ try {
+ assertCheckRead(file);
+ assertCheckWrite(target);
+ } finally {
+ target.delete();
+ }
+
+ if (TestUtil.supportsLinks(dir)) {
+ Path link = dir.resolve("link1234").createSymbolicLink(file);
+ try {
+ prepare();
+ link.copyTo(target, LinkOption.NOFOLLOW_LINKS);
+ try {
+ assertCheckRead(link);
+ assertCheckWrite(target);
+ assertCheckPermission(LinkPermission.class, "symbolic");
+ } finally {
+ target.delete();
+ }
+ } finally {
+ link.delete();
+ }
+ }
+
+ // -- createDirectory --
+
+ Path subdir = dir.resolve("subdir1234");
+ prepare();
+ subdir.createDirectory();
+ try {
+ assertCheckWrite(subdir);
+ } finally {
+ subdir.delete();
+ }
+
+ // -- createFile --
+
+ Path fileToCreate = dir.resolve("file7890");
+ prepare();
+ try {
+ fileToCreate.createFile();
+ assertCheckWrite(fileToCreate);
+ } finally {
+ fileToCreate.delete();
+ }
+
+ // -- createSymbolicLink --
+
+ if (TestUtil.supportsLinks(dir)) {
+ prepare();
+ Path link = dir.resolve("link1234").createSymbolicLink(file);
+ try {
+ assertCheckWrite(link);
+ assertCheckPermission(LinkPermission.class, "symbolic");
+ } finally {
+ link.delete();
+ }
+ }
+
+ // -- delete/deleteIfExists --
+
+ Path fileToDelete = dir.resolve("file7890");
+
+ fileToDelete.createFile();
+ prepare();
+ fileToDelete.delete();
+ assertCheckDelete(fileToDelete);
+
+ fileToDelete.createFile();
+ prepare();
+ fileToDelete.deleteIfExists();
+ assertCheckDelete(fileToDelete);
+
+ // -- exists/notExists --
+
+ prepare();
+ file.exists();
+ assertCheckRead(file);
+
+ prepare();
+ file.notExists();
+ assertCheckRead(file);
+
+ // -- getFileStore --
+
+ prepare();
+ file.getFileStore();
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class, "getFileStoreAttributes");
+
+ // -- isSameFile --
+
+ prepare();
+ file.isSameFile(dir);
+ assertCheckRead(file);
+ assertCheckRead(dir);
+
+ // -- moveTo --
+
+ Path target2 = dir.resolve("target1234");
+ prepare();
+ file.moveTo(target2);
+ try {
+ assertCheckWrite(file);
+ assertCheckWrite(target2);
+ } finally {
+ // restore file
+ target2.moveTo(file);
+ }
+
+ // -- newByteChannel --
+
+ SeekableByteChannel sbc;
+
+ prepare();
+ sbc = file.newByteChannel();
+ try {
+ assertCheckRead(file);
+ } finally {
+ sbc.close();
+ }
+ prepare();
+ sbc = file.newByteChannel(StandardOpenOption.WRITE);
+ try {
+ assertCheckWrite(file);
+ } finally {
+ sbc.close();
+ }
+ prepare();
+ sbc = file.newByteChannel(StandardOpenOption.READ, StandardOpenOption.WRITE);
+ try {
+ assertCheckRead(file);
+ assertCheckWrite(file);
+ } finally {
+ sbc.close();
+ }
+
+ prepare();
+ sbc = file.newByteChannel(StandardOpenOption.DELETE_ON_CLOSE);
+ try {
+ assertCheckRead(file);
+ assertCheckDelete(file);
+ } finally {
+ sbc.close();
+ }
+ file.createFile(); // restore file
+
+
+ // -- newInputStream/newOutptuStream --
+
+ prepare();
+ InputStream in = file.newInputStream();
+ try {
+ assertCheckRead(file);
+ } finally {
+ in.close();
+ }
+ prepare();
+ OutputStream out = file.newOutputStream();
+ try {
+ assertCheckWrite(file);
+ } finally {
+ out.close();
+ }
+
+ // -- newDirectoryStream --
+
+ prepare();
+ DirectoryStream<Path> stream = dir.newDirectoryStream();
+ try {
+ assertCheckRead(dir);
+
+ if (stream instanceof SecureDirectoryStream<?>) {
+ Path entry;
+ SecureDirectoryStream<Path> sds =
+ (SecureDirectoryStream<Path>)stream;
+
+ // newByteChannel
+ entry = file.getName();
+ prepare();
+ sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.READ));
+ try {
+ assertCheckRead(file);
+ } finally {
+ sbc.close();
+ }
+ prepare();
+ sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.WRITE));
+ try {
+ assertCheckWrite(file);
+ } finally {
+ sbc.close();
+ }
+
+ // deleteFile
+ entry = file.getName();
+ prepare();
+ sds.deleteFile(entry);
+ assertCheckDelete(file);
+ dir.resolve(entry).createFile(); // restore file
+
+ // deleteDirectory
+ entry = Paths.get("subdir1234");
+ dir.resolve(entry).createDirectory();
+ prepare();
+ sds.deleteDirectory(entry);
+ assertCheckDelete(dir.resolve(entry));
+
+ // move
+ entry = Paths.get("tempname1234");
+ prepare();
+ sds.move(file.getName(), sds, entry);
+ assertCheckWrite(file);
+ assertCheckWrite(dir.resolve(entry));
+ sds.move(entry, sds, file.getName()); // restore file
+
+ // newDirectoryStream
+ entry = Paths.get("subdir1234");
+ dir.resolve(entry).createDirectory();
+ try {
+ prepare();
+ sds.newDirectoryStream(entry).close();
+ assertCheckRead(dir.resolve(entry));
+ } finally {
+ dir.resolve(entry).delete();
+ }
+
+ // getFileAttributeView to access attributes of directory
+ testBasicFileAttributeView(sds
+ .getFileAttributeView(BasicFileAttributeView.class), dir);
+ testPosixFileAttributeView(sds
+ .getFileAttributeView(PosixFileAttributeView.class), dir);
+
+ // getFileAttributeView to access attributes of entry
+ entry = file.getName();
+ testBasicFileAttributeView(sds
+ .getFileAttributeView(entry, BasicFileAttributeView.class), file);
+ testPosixFileAttributeView(sds
+ .getFileAttributeView(entry, PosixFileAttributeView.class), file);
+
+ } else {
+ System.out.println("SecureDirectoryStream not tested");
+ }
+
+ } finally {
+ stream.close();
+ }
+
+ // -- toAbsolutePath --
+
+ prepare();
+ file.getName().toAbsolutePath();
+ assertCheckPropertyAccess("user.dir");
+
+ // -- toRealPath --
+
+ prepare();
+ file.toRealPath(true);
+ assertCheckRead(file);
+
+ prepare();
+ file.toRealPath(false);
+ assertCheckRead(file);
+
+ prepare();
+ Paths.get(".").toRealPath(true);
+ assertCheckPropertyAccess("user.dir");
+
+ prepare();
+ Paths.get(".").toRealPath(false);
+ assertCheckPropertyAccess("user.dir");
+
+ // -- register --
+
+ WatchService watcher = FileSystems.getDefault().newWatchService();
+ try {
+ prepare();
+ dir.register(watcher, StandardWatchEventKind.ENTRY_DELETE);
+ assertCheckRead(dir);
+ } finally {
+ watcher.close();
+ }
+
+ // -- getAttribute/setAttribute/readAttributes --
+
+ prepare();
+ file.getAttribute("size");
+ assertCheckRead(file);
+
+ prepare();
+ file.setAttribute("lastModifiedTime",
+ FileTime.fromMillis(System.currentTimeMillis()));
+ assertCheckWrite(file);
+
+ prepare();
+ file.readAttributes("*");
+ assertCheckRead(file);
+
+ // -- BasicFileAttributeView --
+ testBasicFileAttributeView(file
+ .getFileAttributeView(BasicFileAttributeView.class), file);
+
+ // -- PosixFileAttributeView --
+
+ {
+ PosixFileAttributeView view =
+ file.getFileAttributeView(PosixFileAttributeView.class);
+ if (view != null &&
+ file.getFileStore().supportsFileAttributeView(PosixFileAttributeView.class))
+ {
+ testPosixFileAttributeView(view, file);
+ } else {
+ System.out.println("PosixFileAttributeView not tested");
+ }
+ }
+
+ // -- DosFileAttributeView --
+
+ {
+ DosFileAttributeView view =
+ file.getFileAttributeView(DosFileAttributeView.class);
+ if (view != null &&
+ file.getFileStore().supportsFileAttributeView(DosFileAttributeView.class))
+ {
+ prepare();
+ view.readAttributes();
+ assertCheckRead(file);
+
+ prepare();
+ view.setArchive(false);
+ assertCheckWrite(file);
+
+ prepare();
+ view.setHidden(false);
+ assertCheckWrite(file);
+
+ prepare();
+ view.setReadOnly(false);
+ assertCheckWrite(file);
+
+ prepare();
+ view.setSystem(false);
+ assertCheckWrite(file);
+ } else {
+ System.out.println("DosFileAttributeView not tested");
+ }
+ }
+
+ // -- FileOwnerAttributeView --
+
+ {
+ FileOwnerAttributeView view =
+ file.getFileAttributeView(FileOwnerAttributeView.class);
+ if (view != null &&
+ file.getFileStore().supportsFileAttributeView(FileOwnerAttributeView.class))
+ {
+ prepare();
+ UserPrincipal owner = view.getOwner();
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+ prepare();
+ view.setOwner(owner);
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+
+ } else {
+ System.out.println("FileOwnerAttributeView not tested");
+ }
+ }
+
+ // -- UserDefinedFileAttributeView --
+
+ {
+ UserDefinedFileAttributeView view =
+ file.getFileAttributeView(UserDefinedFileAttributeView.class);
+ if (view != null &&
+ file.getFileStore().supportsFileAttributeView(UserDefinedFileAttributeView.class))
+ {
+ prepare();
+ view.write("test", ByteBuffer.wrap(new byte[100]));
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class,
+ "accessUserDefinedAttributes");
+
+ prepare();
+ view.read("test", ByteBuffer.allocate(100));
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class,
+ "accessUserDefinedAttributes");
+
+ prepare();
+ view.size("test");
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class,
+ "accessUserDefinedAttributes");
+
+ prepare();
+ view.list();
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class,
+ "accessUserDefinedAttributes");
+
+ prepare();
+ view.delete("test");
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class,
+ "accessUserDefinedAttributes");
+ } else {
+ System.out.println("UserDefinedFileAttributeView not tested");
+ }
+ }
+
+ // -- AclFileAttributeView --
+ {
+ AclFileAttributeView view =
+ file.getFileAttributeView(AclFileAttributeView.class);
+ if (view != null &&
+ file.getFileStore().supportsFileAttributeView(AclFileAttributeView.class))
+ {
+ prepare();
+ List<AclEntry> acl = view.getAcl();
+ assertCheckRead(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+ prepare();
+ view.setAcl(acl);
+ assertCheckWrite(file);
+ assertCheckPermission(RuntimePermission.class, "accessUserInformation");
+ } else {
+ System.out.println("AclFileAttributeView not tested");
+ }
+ }
+
+ // -- UserPrincipalLookupService
+
+ UserPrincipalLookupService lookupService =
+ FileSystems.getDefault().getUserPrincipalLookupService();
+ UserPrincipal owner = Attributes.getOwner(file);
+
+ prepare();
+ lookupService.lookupPrincipalByName(owner.getName());
+ assertCheckPermission(RuntimePermission.class,
+ "lookupUserInformation");
+
+ try {
+ UserPrincipal group = Attributes.readPosixFileAttributes(file).group();
+ prepare();
+ lookupService.lookupPrincipalByGroupName(group.getName());
+ assertCheckPermission(RuntimePermission.class,
+ "lookupUserInformation");
+ } catch (UnsupportedOperationException ignore) {
+ System.out.println("lookupPrincipalByGroupName not tested");
+ }
+
+
+ } finally {
+ file.deleteIfExists();
+ }
+ }
+}
--- a/jdk/test/java/nio/file/Path/Misc.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/file/Path/Misc.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333 6866804
+ * @bug 4313887 6838333 6867101
* @summary Unit test for java.nio.file.Path for miscellenous methods not
* covered by other tests
* @library ..
--- a/jdk/test/java/nio/file/PathMatcher/Basic.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/java/nio/file/PathMatcher/Basic.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887
+ * @bug 4313887 6866397
* @summary Unit test for java.nio.file.PathMatcher
*/
@@ -68,6 +68,20 @@
}
}
+ static void assertRegExMatch(String path, String pattern) {
+ System.out.format("Test regex pattern: %s", pattern);
+ Path file = Paths.get(path);
+ boolean matched = file.getFileSystem()
+ .getPathMatcher("regex:" + pattern).matches(file);
+ if (matched) {
+ System.out.println(" OKAY");
+ } else {
+ System.out.println(" ==> UNEXPECTED RESULT!");
+ failures++;
+ }
+ }
+
+
public static void main(String[] args) {
// basic
assertMatch("foo.html", "foo.html");
@@ -140,21 +154,13 @@
assertMatch("one*two", "one\\*two");
}
-
+ // regex syntax
+ assertRegExMatch("foo.html", ".*\\.html");
- // regex syntax
- {
- String pattern = ".*\\.html";
- System.out.format("Test regex pattern: %s", pattern);
- Path file = Paths.get("foo.html");
- boolean matched = file.getFileSystem()
- .getPathMatcher("regex:" + pattern).matches(file);
- if (matched) {
- System.out.println(" OKAY");
- } else {
- System.out.println(" ==> UNEXPECTED RESULT!");
- failures++;
- }
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ assertRegExMatch("foo012", "foo\\d+");
+ assertRegExMatch("fo o", "fo\\so");
+ assertRegExMatch("foo", "\\w+");
}
// unknown syntax
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/CommentsInXml.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4619564
+ * @summary XMl Comments in Preferences File lead to ClassCastException
+ * @author kladko
+ */
+
+import java.io.*;
+import java.util.prefs.*;
+
+public class CommentsInXml {
+
+ public static void main(String[] argv) throws Exception {
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ bos.write(new String(
+ "<!DOCTYPE preferences SYSTEM " +
+ "\"http://java.sun.com/dtd/preferences.dtd\"> " +
+ "<preferences EXTERNAL_XML_VERSION=\"1.0\"> " +
+ " <root type=\"user\"> " +
+ " <map> " +
+ " </map> " +
+ " <node name=\"hlrAgent\"> <!-- HLR Agent --> " +
+ " <map> " +
+ " <entry key=\"agentName\" value=\"HLRAgent\" />" +
+ " </map> " +
+ " </node> " +
+ " </root> " +
+ "</preferences> "
+ ).getBytes());
+
+ Preferences ur = Preferences.userRoot();
+ ur.importPreferences(new ByteArrayInputStream(bos.toByteArray()));
+ ur.node("hlrAgent").removeNode(); // clean
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/ConflictInFlush.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 4703132
+ * @summary flush() throws an IllegalStateException on a removed node
+ * @author Sucheta Dambalkar
+ */
+
+import java.util.prefs.*;
+
+public final class ConflictInFlush{
+
+ public static void main(String args[]) {
+ Preferences root = Preferences.userRoot();
+ try {
+ Preferences node = root.node("1/2/3");
+ node.flush();
+ System.out.println("Node "+node+" has been created");
+ System.out.println("Removing node "+node);
+ node.removeNode();
+ node.flush();
+ }catch (BackingStoreException bse){
+ bse.printStackTrace();
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/ExportNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 4387136 4947349
+ * @summary Due to a bug in XMLSupport.putPreferencesInXml(...),
+ * node's keys would not get exported.
+ * @author Konstantin Kladko
+ */
+import java.util.prefs.*;
+import java.io.*;
+
+public class ExportNode {
+ public static void main(String[] args) throws
+ BackingStoreException, IOException {
+ Preferences N1 = Preferences.userRoot().node("ExportNodeTest1");
+ N1.put("ExportNodeTestName1","ExportNodeTestValue1");
+ Preferences N2 = N1.node("ExportNodeTest2");
+ N2.put("ExportNodeTestName2","ExportNodeTestValue2");
+ ByteArrayOutputStream exportStream = new ByteArrayOutputStream();
+ N2.exportNode(exportStream);
+
+ // Removal of preference node should always succeed on Solaris/Linux
+ // by successfully acquiring the appropriate file lock (4947349)
+ N1.removeNode();
+
+ if (((exportStream.toString()).lastIndexOf("ExportNodeTestName2")== -1) ||
+ ((exportStream.toString()).lastIndexOf("ExportNodeTestName1")!= -1)) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/ExportSubtree.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/* @test
+ @bug 6203576 4700020
+ @summary checks if the output of exportSubtree() is identical to
+ the output from previous release.
+ */
+
+import java.io.*;
+import java.util.prefs.*;
+
+public class ExportSubtree {
+ public static void main(String[] args) throws Exception {
+ try
+ {
+ //File f = new File(System.getProperty("test.src", "."), "TestPrefs.xml");
+ ByteArrayInputStream bais = new ByteArrayInputStream(importPrefs.getBytes("utf-8"));
+ Preferences.importPreferences(bais);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Preferences.userRoot().node("testExportSubtree").exportSubtree(baos);
+ Preferences.userRoot().node("testExportSubtree").removeNode();
+ if (!expectedResult.equals(baos.toString())) {
+ //System.out.print(baos.toString());
+ //System.out.print(expectedResult);
+ throw new IOException("exportSubtree does not output expected result");
+ }
+ }
+ catch( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+
+ static String ls = System.getProperty("line.separator");
+ static String importPrefs =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<!DOCTYPE preferences SYSTEM \"http://java.sun.com/dtd/preferences.dtd\">"
+ + "<preferences EXTERNAL_XML_VERSION=\"1.0\">"
+ + " <root type=\"user\">"
+ + " <map>"
+ + " <entry key=\"key1\" value=\"value1\"/>"
+ + " </map>"
+ + " <node name=\"testExportSubtree\">"
+ + " <map>"
+ + " <entry key=\"key2\" value=\"value2\"/>"
+ + " </map>"
+ + " <node name=\"test\">"
+ + " <map>"
+ + " <entry key=\"key3\" value=\"value3\"/>"
+ + " </map>"
+ + " </node>"
+ + " </node>"
+ + " </root>"
+ + "</preferences>";
+
+ static String expectedResult =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + ls + "<!DOCTYPE preferences SYSTEM \"http://java.sun.com/dtd/preferences.dtd\">"
+ + ls + "<preferences EXTERNAL_XML_VERSION=\"1.0\">"
+ + ls + " <root type=\"user\">"
+ + ls + " <map/>"
+ + ls + " <node name=\"testExportSubtree\">"
+ + ls + " <map>"
+ + ls + " <entry key=\"key2\" value=\"value2\"/>"
+ + ls + " </map>"
+ + ls + " <node name=\"test\">"
+ + ls + " <map>"
+ + ls + " <entry key=\"key3\" value=\"value3\"/>"
+ + ls + " </map>"
+ + ls + " </node>"
+ + ls + " </node>"
+ + ls + " </root>"
+ + ls + "</preferences>" + ls;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/PrefsSpi.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+import java.util.prefs.Preferences;
+
+/*
+ * main class used by regtest PrefsSpi.sh
+ */
+public class PrefsSpi {
+
+ public static void main (String[] args) throws Exception {
+ if (args.length != 1)
+ throw new Exception("Usage: java PrefsSpi REGEXP");
+
+ String className = Preferences.userRoot().getClass().getName();
+ System.out.printf("className=%s%n", className);
+
+ if (! className.matches(args[0]))
+ throw new Exception("Preferences class name \"" + className
+ + "\" does not match regular expression \""
+ + args[0] + "\".");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/PrefsSpi.sh Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 4991526 6514993
+# @summary Unit test for Preferences jar providers
+#
+# @build PrefsSpi
+# @run shell PrefsSpi.sh
+# @author Martin Buchholz
+
+# Command-line usage: sh PrefsSpi.sh /path/to/build
+
+if [ -z "$TESTJAVA" ]; then
+ if [ $# -lt 1 ]; then exit 1; fi
+ TESTJAVA="$1"; shift
+ TESTSRC="`pwd`"
+ TESTCLASSES="`pwd`"
+fi
+
+ java="$TESTJAVA/bin/java"
+javac="$TESTJAVA/bin/javac"
+ jar="$TESTJAVA/bin/jar"
+
+Die() { printf "%s\n" "$*"; exit 1; }
+
+Sys() {
+ printf "%s\n" "$*"; "$@"; rc="$?";
+ test "$rc" -eq 0 || Die "Command \"$*\" failed with exitValue $rc";
+}
+
+cat > StubPreferences.java <<'EOF'
+import java.util.prefs.*;
+
+public class StubPreferences extends AbstractPreferences {
+ public StubPreferences() { super(null, ""); }
+ public String getSpi(String x) { return null; }
+ public void putSpi(String x, String y) { }
+ public void removeSpi(String x) { }
+ public AbstractPreferences childSpi(String x) { return null; }
+ public void removeNodeSpi() { }
+ public String[] keysSpi() { return null; }
+ public String[] childrenNamesSpi() { return null; }
+ public void syncSpi() { }
+ public void flushSpi() { }
+}
+EOF
+
+cat > StubPreferencesFactory.java <<'EOF'
+import java.util.prefs.*;
+
+public class StubPreferencesFactory implements PreferencesFactory {
+ public Preferences userRoot() { return new StubPreferences(); }
+ public Preferences systemRoot() { return new StubPreferences(); }
+}
+EOF
+
+Sys rm -rf jarDir extDir
+Sys mkdir -p jarDir/META-INF/services extDir
+echo "StubPreferencesFactory" \
+ > "jarDir/META-INF/services/java.util.prefs.PreferencesFactory"
+Sys "$javac" -d jarDir StubPreferencesFactory.java StubPreferences.java
+
+(cd jarDir && "$jar" "cf" "../extDir/PrefsSpi.jar" ".")
+
+case "`uname`" in Windows*|CYGWIN* ) CPS=';';; *) CPS=':';; esac
+
+Sys "$java" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \
+ -Djava.util.prefs.PreferencesFactory=StubPreferencesFactory \
+ PrefsSpi "StubPreferences"
+Sys "$java" "-cp" "$TESTCLASSES" \
+ PrefsSpi "java.util.prefs.*"
+Sys "$java" "-cp" "$TESTCLASSES${CPS}extDir/PrefsSpi.jar" \
+ PrefsSpi "StubPreferences"
+Sys "$java" "-cp" "$TESTCLASSES" "-Djava.ext.dirs=extDir" \
+ PrefsSpi "StubPreferences"
+
+rm -rf jarDir extDir
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/RemoveReadOnlyNode.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/* @test
+ @bug 6178148
+ @summary check if wrong exception gets thrown if one of the child
+ nodes is readonly on underlying filesystem when node is
+ being removed.
+ */
+
+import java.io.*;
+import java.util.prefs.*;
+
+public class RemoveReadOnlyNode {
+ public static void main(String[] args) throws Exception {
+ String osName = System.getProperty("os.name");
+ if (osName.startsWith("Windows"))
+ return;
+ Preferences root = Preferences.userRoot();
+ Preferences node1 = root.node("node1");
+ Preferences node1A = node1.node("node1A");
+ Preferences node1B = node1.node("node1B");
+ node1B.put("mykey", "myvalue");
+ node1.flush();
+ String node1BDirName = System.getProperty("user.home")
+ + "/.java/.userPrefs"
+ + "/node1/node1B";
+ File node1BDir = new File(node1BDirName);
+ node1BDir.setReadOnly();
+ try {
+ node1.removeNode();
+ }
+ catch (BackingStoreException ex) {
+ //expected exception
+ } finally {
+ Runtime.getRuntime().exec("chmod 755 " + node1BDirName).waitFor();
+ try {
+ node1.removeNode();
+ } catch (Exception e) {}
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/RemoveUnregedListener.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/* @test
+ * @bug 4705094
+ * @summary Checks if correct exception gets thrown when removing an
+ * unregistered NodeChangeListener .
+ */
+
+import java.util.prefs.*;
+import java.util.*;
+
+public class RemoveUnregedListener {
+ public static void main(String[] args) throws Exception {
+ Preferences userRoot = null;
+ Preferences N1 = null;
+ NodeChangeListenerTestAdd ncl = new NodeChangeListenerTestAdd();
+ NodeChangeListenerTestAdd ncl2 = new NodeChangeListenerTestAdd();
+ NodeChangeListenerTestAdd ncl3 = new NodeChangeListenerTestAdd();
+ try {
+ userRoot = Preferences.userRoot();
+ N1 = userRoot.node("N1");
+ userRoot.flush();
+
+ //add ncl nc2
+ N1.addNodeChangeListener(ncl);
+ N1.addNodeChangeListener(ncl2);
+ N1.removeNodeChangeListener(ncl3);
+ throw new RuntimeException();
+ } catch (IllegalArgumentException iae) {
+ System.out.println("Test Passed!");
+ } catch (Exception e) {
+ System.out.println("Test Failed");
+ throw e;
+ }
+ }
+
+}
+class NodeChangeListenerTestAdd implements NodeChangeListener {
+ public void childAdded(NodeChangeEvent evt) {}
+ public void childRemoved(NodeChangeEvent evt) {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/prefs/SerializeExceptions.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 4811356
+ * @summary Prefs exceptions were unintentionally not serializable
+ * @author Josh Bloch
+ */
+
+import java.util.prefs.*;
+import java.io.*;
+
+public class SerializeExceptions {
+ public static void main(String args[]) throws Exception {
+ test(new BackingStoreException("Hi"));
+ test(new InvalidPreferencesFormatException("Mom!"));
+ }
+
+ static void test(Object o) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bos);
+ out.writeObject(o);
+ out.flush();
+ out.close();
+ }
+}
--- a/jdk/test/sun/nio/cs/FindCanEncodeBugs.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/sun/nio/cs/FindCanEncodeBugs.java Mon Aug 24 22:27:30 2009 -0700
@@ -22,7 +22,7 @@
*/
/* @test
- @bug 5066863 5066867 5066874 5066879 5066884 5066887 5065777
+ @bug 5066863 5066867 5066874 5066879 5066884 5066887 5065777 6730652
@summary canEncode() false iff encode() throws CharacterCodingException
@run main/timeout=1200 FindCanEncodeBugs
@author Martin Buchholz
@@ -52,9 +52,7 @@
String csn = e.getKey();
Charset cs = e.getValue();
- if (! cs.canEncode() ||
- csn.matches("x-COMPOUND_TEXT") ||
- csn.matches("x-ISO-2022-CN-CNS")) // ISO2022_CN_CNS supports less
+ if (! cs.canEncode() || csn.matches("x-COMPOUND_TEXT"))
continue;
//System.out.println(csn);
--- a/jdk/test/sun/security/ec/TestEC.java Thu Aug 20 11:20:21 2009 -0700
+++ b/jdk/test/sun/security/ec/TestEC.java Mon Aug 24 22:27:30 2009 -0700
@@ -53,7 +53,7 @@
long start = System.currentTimeMillis();
new TestECDH().main(p);
new TestECDSA().main(p);
- //new TestCurves().main(p);
+ new TestCurves().main(p);
new TestKeyFactory().main(p);
new TestECGenSpec().main(p);
new ReadPKCS12().main(p);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/ktab/HighestKvno.java Mon Aug 24 22:27:30 2009 -0700
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+/*
+ * @test
+ * @bug 6867665
+ * @bug 6875033
+ * @summary Problem with keytabs with multiple kvno's (key versions)
+ */
+
+import sun.security.krb5.internal.ktab.*;
+import sun.security.krb5.*;
+import java.io.File;
+import java.io.FileOutputStream;
+
+public class HighestKvno {
+
+ public static void main(String[] args) throws Exception {
+ // kt is a keytab including these entries:
+ //
+ // me@MAD.LOCAL: Type: 3, KVNO: 4
+ // me@MAD.LOCAL: Type: 23, KVNO: 4
+ // me@MAD.LOCAL: Type: 16, KVNO: 4
+ // me@MAD.LOCAL: Type: 1, KVNO: 5
+ // me@MAD.LOCAL: Type: 17, KVNO: 5
+ // me@MAD.LOCAL: Type: 18, KVNO: 5
+ // me@MAD.LOCAL: Type: 1, KVNO: 3
+ // me@MAD.LOCAL: Type: 17, KVNO: 3
+ // me@MAD.LOCAL: Type: 18, KVNO: 3
+ // he@MAD.LOCAL: Type: 1, KVNO: 1
+ // he@MAD.LOCAL: Type: 17, KVNO: 1
+ // he@MAD.LOCAL: Type: 18, KVNO: 1
+ //
+ // This file is created with these steps:
+ // 1. Modify JRE's Ktab.java so that adding new entries
+ // does not remove the old one.
+ // 2. Run the modified Ktab to create 4 sets of keys
+ // 3. Manually hex edit the KVNO as above
+
+ byte[] kt = {
+ (byte)0x05, (byte)0x02, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x26, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x6D, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x45, (byte)0xCD, (byte)0x04,
+ (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x08,
+ (byte)0xE6, (byte)0xB0, (byte)0x07, (byte)0xA8,
+ (byte)0x5B, (byte)0xF8, (byte)0x73, (byte)0xAD,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2E,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x6D,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x45,
+ (byte)0xCD, (byte)0x04, (byte)0x00, (byte)0x17,
+ (byte)0x00, (byte)0x10, (byte)0x50, (byte)0x92,
+ (byte)0x01, (byte)0x6B, (byte)0xCF, (byte)0x5A,
+ (byte)0x2A, (byte)0x7A, (byte)0x4F, (byte)0xE8,
+ (byte)0x39, (byte)0xD9, (byte)0x90, (byte)0xB5,
+ (byte)0x9C, (byte)0xEB, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x36, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x6D, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x45, (byte)0xCD, (byte)0x04,
+ (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x18,
+ (byte)0xDF, (byte)0xDF, (byte)0x62, (byte)0x86,
+ (byte)0x37, (byte)0xCE, (byte)0x29, (byte)0xBA,
+ (byte)0xBC, (byte)0x23, (byte)0x15, (byte)0xDC,
+ (byte)0x86, (byte)0x7C, (byte)0xB6, (byte)0x89,
+ (byte)0x25, (byte)0x25, (byte)0xCD, (byte)0x4A,
+ (byte)0x9B, (byte)0xCE, (byte)0xF4, (byte)0xAE,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x26,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x6D,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x4B,
+ (byte)0x5E, (byte)0x05, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x08, (byte)0xE6, (byte)0xB0,
+ (byte)0x07, (byte)0xA8, (byte)0x5B, (byte)0xF8,
+ (byte)0x73, (byte)0xAD, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x2E, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x6D, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x4B, (byte)0x5E, (byte)0x05,
+ (byte)0x00, (byte)0x11, (byte)0x00, (byte)0x10,
+ (byte)0xEA, (byte)0xF5, (byte)0xA8, (byte)0x36,
+ (byte)0xA5, (byte)0x3E, (byte)0x5F, (byte)0x5C,
+ (byte)0x26, (byte)0xE9, (byte)0xDD, (byte)0x8B,
+ (byte)0x8C, (byte)0xE8, (byte)0x92, (byte)0x9C,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x3E,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x6D,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x4B,
+ (byte)0x5E, (byte)0x05, (byte)0x00, (byte)0x12,
+ (byte)0x00, (byte)0x20, (byte)0x68, (byte)0xBE,
+ (byte)0xD4, (byte)0x17, (byte)0x3A, (byte)0x06,
+ (byte)0xE0, (byte)0x0C, (byte)0x62, (byte)0x11,
+ (byte)0xB7, (byte)0x53, (byte)0x1B, (byte)0x3E,
+ (byte)0xB2, (byte)0x6B, (byte)0x0D, (byte)0x48,
+ (byte)0xD8, (byte)0x52, (byte)0x5A, (byte)0x4C,
+ (byte)0xBE, (byte)0x24, (byte)0xBB, (byte)0x3D,
+ (byte)0xC1, (byte)0x74, (byte)0x69, (byte)0xDA,
+ (byte)0x34, (byte)0x98, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x26, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x6D, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x51, (byte)0x27, (byte)0x03,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x08,
+ (byte)0xE6, (byte)0xB0, (byte)0x07, (byte)0xA8,
+ (byte)0x5B, (byte)0xF8, (byte)0x73, (byte)0xAD,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2E,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x6D,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x51,
+ (byte)0x27, (byte)0x03, (byte)0x00, (byte)0x11,
+ (byte)0x00, (byte)0x10, (byte)0xEA, (byte)0xF5,
+ (byte)0xA8, (byte)0x36, (byte)0xA5, (byte)0x3E,
+ (byte)0x5F, (byte)0x5C, (byte)0x26, (byte)0xE9,
+ (byte)0xDD, (byte)0x8B, (byte)0x8C, (byte)0xE8,
+ (byte)0x92, (byte)0x9C, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x3E, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x6D, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x51, (byte)0x27, (byte)0x03,
+ (byte)0x00, (byte)0x12, (byte)0x00, (byte)0x20,
+ (byte)0x68, (byte)0xBE, (byte)0xD4, (byte)0x17,
+ (byte)0x3A, (byte)0x06, (byte)0xE0, (byte)0x0C,
+ (byte)0x62, (byte)0x11, (byte)0xB7, (byte)0x53,
+ (byte)0x1B, (byte)0x3E, (byte)0xB2, (byte)0x6B,
+ (byte)0x0D, (byte)0x48, (byte)0xD8, (byte)0x52,
+ (byte)0x5A, (byte)0x4C, (byte)0xBE, (byte)0x24,
+ (byte)0xBB, (byte)0x3D, (byte)0xC1, (byte)0x74,
+ (byte)0x69, (byte)0xDA, (byte)0x34, (byte)0x98,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x26,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x68,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x54,
+ (byte)0xC7, (byte)0x01, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x08, (byte)0x85, (byte)0x5B,
+ (byte)0xE3, (byte)0x13, (byte)0x3E, (byte)0xF8,
+ (byte)0x76, (byte)0xEC, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x2E, (byte)0x00, (byte)0x01,
+ (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41,
+ (byte)0x44, (byte)0x2E, (byte)0x4C, (byte)0x4F,
+ (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00,
+ (byte)0x02, (byte)0x68, (byte)0x65, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x4A,
+ (byte)0x79, (byte)0x54, (byte)0xC7, (byte)0x01,
+ (byte)0x00, (byte)0x11, (byte)0x00, (byte)0x10,
+ (byte)0xEC, (byte)0xCC, (byte)0x16, (byte)0xCD,
+ (byte)0xE8, (byte)0x51, (byte)0x46, (byte)0x4C,
+ (byte)0x1B, (byte)0x57, (byte)0xAE, (byte)0x19,
+ (byte)0xC3, (byte)0xD2, (byte)0x55, (byte)0x1B,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x3E,
+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+ (byte)0x4D, (byte)0x41, (byte)0x44, (byte)0x2E,
+ (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41,
+ (byte)0x4C, (byte)0x00, (byte)0x02, (byte)0x68,
+ (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x4A, (byte)0x79, (byte)0x54,
+ (byte)0xC7, (byte)0x01, (byte)0x00, (byte)0x12,
+ (byte)0x00, (byte)0x20, (byte)0xAE, (byte)0xBA,
+ (byte)0xCB, (byte)0xF5, (byte)0xA8, (byte)0x09,
+ (byte)0xC1, (byte)0xB0, (byte)0x2C, (byte)0x2A,
+ (byte)0x3D, (byte)0x96, (byte)0x2C, (byte)0x2D,
+ (byte)0xF5, (byte)0xFE, (byte)0x65, (byte)0xEC,
+ (byte)0x75, (byte)0x72, (byte)0x5B, (byte)0x46,
+ (byte)0x84, (byte)0xD7, (byte)0x49, (byte)0x3E,
+ (byte)0xF2, (byte)0x27, (byte)0x32, (byte)0x69,
+ (byte)0x75, (byte)0x9B,
+ };
+ System.setProperty("java.security.krb5.conf",
+ new File(System.getProperty("test.src"),
+ "../krb5.conf").getAbsolutePath());
+ FileOutputStream fout = new FileOutputStream("kt");
+ fout.write(kt);
+ fout.close();
+ KeyTab ktab = KeyTab.getInstance("kt");
+ PrincipalName pn = new PrincipalName("me@MAD.LOCAL");
+ EncryptionKey[] keys = ktab.readServiceKeys(pn);
+ if (keys[0].getKeyVersionNumber() != 5) {
+ throw new Exception("Highest not first");
+ }
+ if (ktab.readServiceKey(pn).getKeyVersionNumber() != 5) {
+ throw new Exception("Highest not chosen");
+ }
+ new File("kt").delete();
+ }
+}