Merge
This commit is contained in:
commit
a0f91a8f7e
@ -1,3 +1,6 @@
|
||||
^build/
|
||||
^dist/
|
||||
^nbproject/private/
|
||||
^make/netbeans/.*/nbproject/private/
|
||||
^make/netbeans/.*/build/
|
||||
^make/netbeans/.*/dist/
|
||||
|
@ -160,7 +160,6 @@ FILES_src = \
|
||||
\
|
||||
sun/nio/ByteBuffered.java \
|
||||
\
|
||||
sun/nio/ch/AbstractFuture.java \
|
||||
sun/nio/ch/AbstractPollArrayWrapper.java \
|
||||
sun/nio/ch/AllocatedNativeObject.java \
|
||||
sun/nio/ch/AsynchronousChannelGroupImpl.java \
|
||||
|
74
jdk/make/netbeans/jdwpgen/build.xml
Normal file
74
jdk/make/netbeans/jdwpgen/build.xml
Normal file
@ -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>
|
642
jdk/make/netbeans/jdwpgen/nbproject/build-impl.xml
Normal file
642
jdk/make/netbeans/jdwpgen/nbproject/build-impl.xml
Normal file
@ -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>
|
72
jdk/make/netbeans/jdwpgen/nbproject/findbugs.settings
Normal file
72
jdk/make/netbeans/jdwpgen/nbproject/findbugs.settings
Normal file
@ -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=|
|
8
jdk/make/netbeans/jdwpgen/nbproject/genfiles.properties
Normal file
8
jdk/make/netbeans/jdwpgen/nbproject/genfiles.properties
Normal file
@ -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
|
65
jdk/make/netbeans/jdwpgen/nbproject/project.properties
Normal file
65
jdk/make/netbeans/jdwpgen/nbproject/project.properties
Normal file
@ -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
|
16
jdk/make/netbeans/jdwpgen/nbproject/project.xml
Normal file
16
jdk/make/netbeans/jdwpgen/nbproject/project.xml
Normal file
@ -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>
|
2
jdk/make/netbeans/jdwpgen/nbproject/sqe.properties
Normal file
2
jdk/make/netbeans/jdwpgen/nbproject/sqe.properties
Normal file
@ -0,0 +1,2 @@
|
||||
#Path to FindbugsSettingsFile (relative)
|
||||
findbugs.settings.file=findbugs.settings
|
@ -30,7 +30,7 @@ import java.io.*;
|
||||
|
||||
abstract class AbstractNamedNode extends Node {
|
||||
|
||||
NameNode nameNode;
|
||||
NameNode nameNode = null;
|
||||
String name;
|
||||
|
||||
public String name() {
|
||||
|
@ -30,7 +30,7 @@ import java.io.*;
|
||||
|
||||
class AltNode extends AbstractGroupNode implements TypeNode {
|
||||
|
||||
SelectNode select;
|
||||
SelectNode select = null;
|
||||
|
||||
void constrain(Context ctx) {
|
||||
super.constrain(ctx);
|
||||
|
@ -33,13 +33,7 @@ class ConstantSetNode extends AbstractNamedNode {
|
||||
/**
|
||||
* 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 @@ class ConstantSetNode extends AbstractNamedNode {
|
||||
}
|
||||
|
||||
public static String getConstant(String key){
|
||||
if (constantMap == null) {
|
||||
return "";
|
||||
}
|
||||
String com = constantMap.get(key);
|
||||
if(com == null){
|
||||
return "";
|
||||
|
@ -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 @@ class Main {
|
||||
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 @@ class Main {
|
||||
} else {
|
||||
System.err.println("Invalid option: " + arg);
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
specSource = arg;
|
||||
@ -75,6 +73,7 @@ class Main {
|
||||
if (reader == null) {
|
||||
System.err.println("<spec_input> must be specified");
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
|
||||
Parse parse = new Parse(reader);
|
||||
|
@ -36,7 +36,7 @@ abstract class Node {
|
||||
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 @@ abstract class Node {
|
||||
}
|
||||
|
||||
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 @@ abstract class Node {
|
||||
System.err.println(Main.specSource + ":" + lineno + ": " +
|
||||
kind + " - " + errmsg);
|
||||
System.err.println();
|
||||
System.exit(1);
|
||||
throw new RuntimeException("Error: " + errmsg);
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +146,12 @@ class Parse {
|
||||
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 @@ class Parse {
|
||||
void error(String errmsg) {
|
||||
System.err.println(Main.specSource + ":" + izer.lineno() +
|
||||
": " + errmsg);
|
||||
System.exit(1);
|
||||
throw new RuntimeException("Error: " + errmsg);
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import java.io.*;
|
||||
|
||||
class RepeatNode extends AbstractTypeNode {
|
||||
|
||||
Node member;
|
||||
Node member = null;
|
||||
|
||||
void constrain(Context ctx) {
|
||||
super.constrain(ctx);
|
||||
|
@ -30,7 +30,7 @@ import java.io.*;
|
||||
|
||||
class SelectNode extends AbstractGroupNode implements TypeNode {
|
||||
|
||||
AbstractSimpleTypeNode typeNode;
|
||||
AbstractSimpleTypeNode typeNode = null;
|
||||
|
||||
void prune() {
|
||||
super.prune();
|
||||
|
@ -129,7 +129,7 @@ public class TextCallbackHandler implements CallbackHandler {
|
||||
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];
|
||||
|
@ -51,7 +51,7 @@ public final class Provider extends java.security.Provider {
|
||||
" 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() {
|
||||
|
@ -28,8 +28,12 @@ package java.lang;
|
||||
/**
|
||||
* 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 {
|
||||
|
@ -2301,6 +2301,54 @@ public final class String
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,12 @@ package java.lang;
|
||||
* <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 {
|
||||
|
@ -28,8 +28,12 @@ package java.lang.annotation;
|
||||
/**
|
||||
* 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 {
|
||||
|
@ -30,8 +30,12 @@ import java.lang.reflect.Method;
|
||||
* 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 {
|
||||
|
@ -30,8 +30,12 @@ package java.lang.annotation;
|
||||
* 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 {
|
||||
|
@ -50,6 +50,11 @@ import java.lang.annotation.Annotation;
|
||||
* 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
|
||||
*/
|
||||
|
@ -56,18 +56,18 @@ public interface AsynchronousByteChannel
|
||||
/**
|
||||
* 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 @@ public interface AsynchronousByteChannel
|
||||
* <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 @@ public interface AsynchronousByteChannel
|
||||
/**
|
||||
* 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 @@ public interface AsynchronousByteChannel
|
||||
* <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
|
||||
|
@ -34,7 +34,8 @@ import java.util.concurrent.Future; // javadoc
|
||||
*
|
||||
* <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 @@ import java.util.concurrent.Future; // javadoc
|
||||
* 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 @@ import java.util.concurrent.Future; // javadoc
|
||||
* <h4>Cancellation</h4>
|
||||
*
|
||||
* <p> The {@code Future} interface defines the {@link Future#cancel cancel}
|
||||
* method to cancel execution of a task.
|
||||
* 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> Where the {@code cancel} method is invoked with the {@code
|
||||
* <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. This will cause any other I/O
|
||||
* operations outstanding on the channel to complete with the exception {@link
|
||||
* AsynchronousCloseException}.
|
||||
*
|
||||
* <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.
|
||||
* 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 @@ public interface AsynchronousChannel
|
||||
*
|
||||
* <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
|
||||
|
@ -109,19 +109,13 @@ import java.nio.ByteBuffer;
|
||||
* // 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 @@ public abstract class AsynchronousDatagramChannel
|
||||
/**
|
||||
* 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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* @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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* @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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* @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> 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.
|
||||
*
|
||||
* <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}
|
||||
*
|
||||
* @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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* @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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* 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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* 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 @@ public abstract class AsynchronousDatagramChannel
|
||||
* @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);
|
||||
}
|
||||
|
@ -48,7 +48,12 @@ import java.util.Collections;
|
||||
*
|
||||
* <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 @@ import java.util.Collections;
|
||||
* 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
|
||||
@ -122,22 +120,6 @@ public abstract class AsynchronousFileChannel
|
||||
protected AsynchronousFileChannel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* <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 @@ public abstract class AsynchronousFileChannel
|
||||
/**
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* 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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* <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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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 @@ public abstract class AsynchronousFileChannel
|
||||
* @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);
|
||||
}
|
||||
|
@ -85,9 +85,6 @@ import java.io.IOException;
|
||||
* public void failed(Throwable exc, Void att) {
|
||||
* ...
|
||||
* }
|
||||
* public void cancelled(Void att) {
|
||||
* ...
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
@ -240,11 +237,11 @@ public abstract class AsynchronousServerSocketChannel
|
||||
/**
|
||||
* 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 @@ public abstract class AsynchronousServerSocketChannel
|
||||
* @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();
|
||||
}
|
||||
|
@ -274,14 +274,11 @@ public abstract class AsynchronousSocketChannel
|
||||
/**
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* 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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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 @@ public abstract class AsynchronousSocketChannel
|
||||
* @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);
|
||||
}
|
||||
|
@ -182,7 +182,6 @@ public final class Channels {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 @@ public final class Channels {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
|
@ -32,11 +32,9 @@ package java.nio.channels;
|
||||
* 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 @@ public interface CompletionHandler<V,A> {
|
||||
* 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);
|
||||
}
|
||||
|
@ -39,8 +39,7 @@ import java.util.Collections;
|
||||
/**
|
||||
* 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 @@ import java.util.Collections;
|
||||
* @author Mike McCloskey
|
||||
* @author JSR-51 Expert Group
|
||||
* @since 1.4
|
||||
* @updated 1.7
|
||||
*/
|
||||
|
||||
public abstract class FileChannel
|
||||
@ -164,7 +162,6 @@ public abstract class FileChannel
|
||||
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 @@ public abstract class FileChannel
|
||||
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
|
||||
|
@ -114,7 +114,6 @@ import java.io.IOException;
|
||||
* @author Mark Reinhold
|
||||
* @author JSR-51 Expert Group
|
||||
* @since 1.4
|
||||
* @updated 1.7
|
||||
*/
|
||||
|
||||
public abstract class FileLock {
|
||||
@ -161,7 +160,7 @@ public abstract class FileLock {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 @@ public abstract class FileLock {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 @@ public abstract class FileLock {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@note new}
|
||||
* Returns the channel upon whose file this lock was acquired.
|
||||
*
|
||||
* @return The channel upon whose file this lock was acquired.
|
||||
|
@ -190,5 +190,5 @@ gen WritePendingException "
|
||||
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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -39,8 +39,6 @@ import java.io.IOException;
|
||||
* 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
|
||||
*/
|
||||
|
@ -674,7 +674,6 @@ public final class Scanner implements Iterator<String> {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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 @@ public final class Scanner implements Iterator<String> {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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.
|
||||
|
@ -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();
|
||||
}
|
@ -32,8 +32,8 @@ import java.io.IOException;
|
||||
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 @@ abstract class AsynchronousChannelGroupImpl
|
||||
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 @@ abstract class AsynchronousChannelGroupImpl
|
||||
|
||||
@Override
|
||||
public final boolean isShutdown() {
|
||||
return shutdown;
|
||||
return shutdown.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -260,17 +257,10 @@ abstract class AsynchronousChannelGroupImpl
|
||||
|
||||
@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 @@ abstract class AsynchronousChannelGroupImpl
|
||||
|
||||
@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 @@ abstract class AsynchronousChannelGroupImpl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -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 @@ abstract class AsynchronousFileChannelImpl
|
||||
|
||||
// -- 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 @@ abstract class AsynchronousFileChannelImpl
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import java.io.IOException;
|
||||
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 @@ abstract class AsynchronousServerSocketChannelImpl
|
||||
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;
|
||||
}
|
||||
|
@ -183,29 +183,54 @@ abstract class AsynchronousSocketChannelImpl
|
||||
killWriting();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
// 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 <A> Future<Integer> read(ByteBuffer dst,
|
||||
long timeout,
|
||||
TimeUnit unit,
|
||||
A attachment,
|
||||
CompletionHandler<Integer,? super A> handler)
|
||||
{
|
||||
public final Future<Integer> read(ByteBuffer dst) {
|
||||
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);
|
||||
return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
|
||||
}
|
||||
|
||||
@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 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");
|
||||
read(false, dst, null, timeout, unit, attachment, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
|
||||
// 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 <A> Future<Integer> 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);
|
||||
public final Future<Integer> write(ByteBuffer src) {
|
||||
return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
|
||||
}
|
||||
|
||||
@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 src,
|
||||
long timeout,
|
||||
TimeUnit unit,
|
||||
A attachment,
|
||||
CompletionHandler<Integer,? super A> handler)
|
||||
{
|
||||
if (handler == null)
|
||||
throw new NullPointerException("'handler' is null");
|
||||
write(false, src, null, timeout, unit, attachment, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 @@ abstract class AsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final SocketAddress getRemoteAddress() throws IOException {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
@ -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 @@ import java.io.IOException;
|
||||
* 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 @@ final class CompletedFuture<V,A>
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
Throwable exception() {
|
||||
return exc;
|
||||
}
|
||||
|
||||
@Override
|
||||
V value() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -117,33 +117,32 @@ class Invoker {
|
||||
* 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());
|
||||
}
|
||||
|
||||
// clear interrupt
|
||||
Thread.interrupted();
|
||||
if (exc == null) {
|
||||
handler.completed(value, attachment);
|
||||
} else {
|
||||
handler.failed(exc, attachment);
|
||||
}
|
||||
|
||||
// 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 @@ class Invoker {
|
||||
* 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 @@ class Invoker {
|
||||
* 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 @@ class Invoker {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ import java.io.IOException;
|
||||
* 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 @@ final class PendingFuture<V,A>
|
||||
// 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 @@ final class PendingFuture<V,A>
|
||||
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 @@ final class PendingFuture<V,A>
|
||||
/**
|
||||
* 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 @@ final class PendingFuture<V,A>
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
Throwable exception() {
|
||||
return (exc != CANCELLED) ? exc : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
V value() {
|
||||
return result;
|
||||
}
|
||||
@ -204,33 +228,6 @@ final class PendingFuture<V,A>
|
||||
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 @@ final class PendingFuture<V,A>
|
||||
} catch (IOException ignore) { }
|
||||
}
|
||||
|
||||
// release waiters (this also releases the invoker)
|
||||
// release waiters
|
||||
if (latch != null)
|
||||
latch.countDown();
|
||||
return true;
|
||||
|
@ -317,51 +317,71 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
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 <A> Future<Integer> write(ByteBuffer src,
|
||||
long timeout,
|
||||
TimeUnit unit,
|
||||
A attachment,
|
||||
CompletionHandler<Integer,? super A> handler)
|
||||
{
|
||||
if (timeout < 0L)
|
||||
throw new IllegalArgumentException("Negative timeout");
|
||||
if (unit == null)
|
||||
throw new NullPointerException();
|
||||
public Future<Integer> send(ByteBuffer src, SocketAddress target) {
|
||||
return implSend(src, target, null, null);
|
||||
}
|
||||
|
||||
CompletedFuture<Integer,A> result;
|
||||
@Override
|
||||
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)
|
||||
{
|
||||
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 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
@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 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
|
||||
// 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 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
x = new AsynchronousCloseException();
|
||||
result.setFailure(x);
|
||||
}
|
||||
Invoker.invokeUnchecked(handler, result);
|
||||
Invoker.invokeUnchecked(result);
|
||||
}
|
||||
};
|
||||
try {
|
||||
@ -483,11 +503,27 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
}
|
||||
|
||||
@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 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
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 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
x = new AsynchronousCloseException();
|
||||
result.setFailure(x);
|
||||
}
|
||||
Invoker.invokeUnchecked(handler, result);
|
||||
Invoker.invokeUnchecked(result);
|
||||
}
|
||||
};
|
||||
try {
|
||||
@ -574,6 +612,23 @@ class SimpleAsynchronousDatagramChannelImpl
|
||||
return result;
|
||||
}
|
||||
|
||||
@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
|
||||
|
@ -50,9 +50,6 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
// 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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
@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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
// 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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
@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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class SimpleAsynchronousFileChannelImpl
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -388,9 +388,9 @@ abstract class ISO2022
|
||||
|
||||
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;
|
||||
|
@ -76,6 +76,15 @@ public class ISO2022_CN_CNS extends ISO2022 implements HistoricallyNamedCharset
|
||||
} 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
|
||||
|
@ -62,7 +62,7 @@ public final class SunProvider extends Provider {
|
||||
|
||||
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>() {
|
||||
|
@ -41,6 +41,7 @@ import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.File;
|
||||
import java.util.Comparator;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants {
|
||||
/**
|
||||
* 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 @@ public class KeyTab implements KeyTabConstants {
|
||||
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 @@ public class KeyTab implements KeyTabConstants {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ public class KeyTab implements KeyTabConstants {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public final class Sun extends Provider {
|
||||
|
||||
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
|
||||
|
@ -40,7 +40,7 @@ public final class SunPCSC extends Provider {
|
||||
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");
|
||||
|
@ -103,7 +103,7 @@ public abstract class SunJSSE extends java.security.Provider {
|
||||
|
||||
// standard constructor
|
||||
protected SunJSSE() {
|
||||
super("SunJSSE", 1.6d, info);
|
||||
super("SunJSSE", 1.7d, info);
|
||||
subclassCheck();
|
||||
if (Boolean.TRUE.equals(fips)) {
|
||||
throw new ProviderException
|
||||
|
@ -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 @@ import java.util.Arrays;
|
||||
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 @@ public class Password {
|
||||
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
|
||||
|
@ -422,7 +422,7 @@ ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
|
||||
*/
|
||||
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) );*/
|
||||
|
@ -248,12 +248,13 @@ final class EPollPort
|
||||
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 @@ final class EPollPort
|
||||
|
||||
// process event
|
||||
try {
|
||||
ev.channel().onEvent(ev.events());
|
||||
ev.channel().onEvent(ev.events(), isPooledThread);
|
||||
} catch (Error x) {
|
||||
replaceMe = true; throw x;
|
||||
} catch (RuntimeException x) {
|
||||
|
@ -49,7 +49,7 @@ abstract class Port extends AsynchronousChannelGroupImpl {
|
||||
* 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 @@ abstract class Port extends AsynchronousChannelGroupImpl {
|
||||
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();
|
||||
}
|
||||
|
@ -151,12 +151,13 @@ class SolarisEventPort
|
||||
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 @@ class SolarisEventPort
|
||||
if (ch != null) {
|
||||
replaceMe = true;
|
||||
// no need to translate events
|
||||
ch.onEvent(events);
|
||||
ch.onEvent(events, isPooledThread);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -59,10 +59,13 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
* 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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
// 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;
|
||||
|
||||
// invoke the handler
|
||||
Invoker.invoke(result.handler(), result);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -234,16 +243,18 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
}
|
||||
|
||||
@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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousServerSocketChannelImpl
|
||||
// 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 --
|
||||
|
@ -61,20 +61,33 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// returns and clears the result of a pending write
|
||||
PendingFuture<Number,Object> grabPendingWrite() {
|
||||
synchronized (updateLock) {
|
||||
PendingFuture<Number,Object> result = pendingWrite;
|
||||
pendingWrite = 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;
|
||||
}
|
||||
finish(mayInvokeDirect, readable, writable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -213,26 +215,7 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
notifyBeforeTcpConnect = (localAddress == null);
|
||||
}
|
||||
|
||||
AbstractFuture<Void,A> result = null;
|
||||
Throwable e = null;
|
||||
try {
|
||||
begin();
|
||||
@ -327,15 +318,21 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
*/
|
||||
@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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
*/
|
||||
@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 @@ class UnixAsynchronousSocketChannelImpl
|
||||
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
|
||||
|
||||
int n = IOStatus.UNAVAILABLE;
|
||||
Throwable exc = null;
|
||||
boolean pending = false;
|
||||
|
||||
AbstractFuture<V,A> result;
|
||||
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 --
|
||||
|
@ -65,9 +65,6 @@ class UnixPath
|
||||
// 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 @@ class UnixPath
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -34,6 +34,8 @@ import java.util.*;
|
||||
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 @@ import sun.misc.Unsafe;
|
||||
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 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
<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 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
} 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 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
/**
|
||||
* 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 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
public void run() {
|
||||
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
|
||||
Invoker.getGroupAndInvokeCount();
|
||||
boolean canInvokeDirect = (myGroupAndInvokeCount != null);
|
||||
CompletionStatus ioResult = new CompletionStatus();
|
||||
boolean replaceMe = false;
|
||||
|
||||
@ -382,7 +394,7 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
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 @@ class Iocp extends AsynchronousChannelGroupImpl {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -146,10 +146,12 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
} 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
} 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
} 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
|
||||
// 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 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -113,14 +113,14 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
/**
|
||||
* 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 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
}
|
||||
|
||||
// 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 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
}
|
||||
|
||||
// invoke handler (but not directly)
|
||||
Invoker.invokeIndirectly(result.handler(), result);
|
||||
Invoker.invokeIndirectly(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -283,19 +283,20 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
} 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 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousServerSocketChannelImpl
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -250,14 +250,14 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
result.setFailure(toIOException(exc));
|
||||
}
|
||||
|
||||
Invoker.invoke(result.handler(), result);
|
||||
if (canInvokeDirect) {
|
||||
Invoker.invokeUnchecked(result);
|
||||
} else {
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,20 +294,21 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
} 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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
// invoke completion handler
|
||||
Invoker.invoke(result.handler(), result);
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -522,7 +531,7 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
*/
|
||||
@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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
enableReading();
|
||||
result.setFailure(x);
|
||||
}
|
||||
Invoker.invoke(result.handler(), result);
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -579,13 +592,14 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
// 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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
// 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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
//@SuppressWarnings("unchecked")
|
||||
public void run() {
|
||||
long overlapped = 0L;
|
||||
boolean prepared = false;
|
||||
@ -759,7 +784,7 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
// invoke completion handler
|
||||
Invoker.invoke(result.handler(), result);
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -767,7 +792,7 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
*/
|
||||
@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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
enableWriting();
|
||||
result.setFailure(x);
|
||||
}
|
||||
Invoker.invoke(result.handler(), result);
|
||||
Invoker.invoke(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -820,13 +849,14 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
// 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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
// 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 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ class WindowsFileAttributeViews {
|
||||
|
||||
@Override
|
||||
public WindowsFileAttributes readAttributes() throws IOException {
|
||||
file.checkRead();
|
||||
try {
|
||||
return WindowsFileAttributes.get(file, followLinks);
|
||||
} catch (WindowsException x) {
|
||||
|
@ -246,8 +246,8 @@ class WindowsFileAttributes
|
||||
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 @@ class WindowsFileAttributes
|
||||
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 @@ class WindowsFileAttributes
|
||||
// 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 @@ class WindowsFileAttributes
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class WindowsFileAttributes
|
||||
(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 @@ class WindowsFileAttributes
|
||||
|
||||
// package private
|
||||
boolean isReparsePoint() {
|
||||
return (fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
|
||||
return isReparsePoint(fileAttrs);
|
||||
}
|
||||
|
||||
boolean isDirectoryLink() {
|
||||
|
@ -283,25 +283,15 @@ class WindowsFileSystem
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -62,6 +62,30 @@ class WindowsLinkSupport {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class WindowsLinkSupport {
|
||||
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 @@ class WindowsLinkSupport {
|
||||
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 @@ class WindowsLinkSupport {
|
||||
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 @@ class WindowsLinkSupport {
|
||||
}
|
||||
|
||||
// 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 @@ class WindowsLinkSupport {
|
||||
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 @@ class WindowsLinkSupport {
|
||||
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 @@ class WindowsLinkSupport {
|
||||
/**
|
||||
* 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 @@ class WindowsLinkSupport {
|
||||
}
|
||||
}
|
||||
|
||||
return path.toString();
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,10 +180,12 @@ class WindowsNativeDispatcher {
|
||||
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;
|
||||
|
@ -51,13 +51,25 @@ static struct {
|
||||
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 @@ Java_java_io_WinNTFileSystem_initIDs(JNIEnv *env, jclass cls)
|
||||
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 @@ Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
|
||||
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 @@ JNICALL Java_java_io_WinNTFileSystem_checkAccess(JNIEnv *env, jobject this,
|
||||
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 @@ Java_java_io_WinNTFileSystem_setPermission(JNIEnv *env, jobject this,
|
||||
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 @@ Java_java_io_WinNTFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
|
||||
/* 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 @@ Java_java_io_WinNTFileSystem_getLength(JNIEnv *env, jobject this, jobject file)
|
||||
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 @@ Java_java_io_WinNTFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
|
||||
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 @@ removeFileOrDirectory(const jchar *path)
|
||||
/* 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 @@ Java_java_io_WinNTFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
|
||||
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 @@ Java_java_io_WinNTFileSystem_setReadOnly(JNIEnv *env, jobject this,
|
||||
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;
|
||||
|
@ -58,6 +58,16 @@ Java_sun_nio_ch_Iocp_initIDs(JNIEnv* env, jclass this)
|
||||
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)
|
||||
|
@ -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 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
||||
}
|
||||
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 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this,
|
||||
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 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile1(JNIEnv* env, jclass this,
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
throwWindowsException(env, GetLastError());
|
||||
}
|
||||
return ptr_to_jlong(handle);
|
||||
return ptr_to_jlong(handle);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
380
jdk/test/java/io/File/SymLinks.java
Normal file
380
jdk/test/java/io/File/SymLinks.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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 @@ public class Split {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4607272
|
||||
* @bug 4607272 6842687
|
||||
* @summary Unit test for AsynchronousChannelGroup
|
||||
*/
|
||||
|
||||
@ -50,8 +50,6 @@ public class GroupOfOne {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
|
||||
@ -97,9 +95,6 @@ public class GroupOfOne {
|
||||
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 class GroupOfOne {
|
||||
public void failed(Throwable exc, Void att) {
|
||||
throw new RuntimeException(exc);
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
});
|
||||
|
||||
latch.await();
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4607272
|
||||
* @bug 4607272 6842687
|
||||
* @summary Unit test for AsynchronousChannelGroup
|
||||
*/
|
||||
|
||||
@ -90,14 +90,10 @@ public class Identity {
|
||||
}
|
||||
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 class Identity {
|
||||
public void failed(Throwable exc, Integer groupId) {
|
||||
fail(exc.getMessage());
|
||||
}
|
||||
public void cancelled(Integer groupId) {
|
||||
fail("I/O operation was cancelled");
|
||||
}
|
||||
});
|
||||
|
||||
// wait until
|
||||
|
@ -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 class Restart {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// establish loopback connection which should cause completion
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4607272
|
||||
* @bug 4607272 6842687
|
||||
* @summary Unit test for AsynchronousChannelGroup
|
||||
*/
|
||||
|
||||
@ -52,8 +52,6 @@ public class Unbounded {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
System.out.println("Listener created.");
|
||||
|
||||
@ -97,8 +95,6 @@ public class Unbounded {
|
||||
}
|
||||
public void failed(Throwable exc, AsynchronousSocketChannel ch) {
|
||||
}
|
||||
public void cancelled(AsynchronousSocketChannel ch) {
|
||||
}
|
||||
});
|
||||
}
|
||||
System.out.println("All read operations outstanding.");
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4527345
|
||||
* @bug 4527345 6842687
|
||||
* @summary Unit test for AsynchronousDatagramChannel
|
||||
*/
|
||||
|
||||
@ -72,8 +72,6 @@ public class Basic {
|
||||
}
|
||||
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 class Basic {
|
||||
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 class Basic {
|
||||
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 class Basic {
|
||||
}
|
||||
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 class Basic {
|
||||
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 class Basic {
|
||||
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 class Basic {
|
||||
}
|
||||
public void failed (Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
l2.await(5, TimeUnit.SECONDS);
|
||||
|
||||
@ -272,8 +258,6 @@ public class Basic {
|
||||
throw new RuntimeException(exc);
|
||||
}
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
l3.await(5, TimeUnit.SECONDS);
|
||||
|
||||
@ -323,8 +307,6 @@ public class Basic {
|
||||
}
|
||||
public void failed (Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
l2.await(5, TimeUnit.SECONDS);
|
||||
|
||||
@ -340,7 +322,7 @@ public class Basic {
|
||||
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 @@ public class Basic {
|
||||
} 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 @@ public class Basic {
|
||||
((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();
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4607272 6822643 6830721
|
||||
* @bug 4607272 6822643 6830721 6842687
|
||||
* @summary Unit test for AsynchronousFileChannel
|
||||
*/
|
||||
|
||||
@ -195,8 +195,6 @@ public class Basic {
|
||||
}
|
||||
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 class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// wait for handler to complete
|
||||
@ -318,8 +314,6 @@ public class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
await(latch);
|
||||
|
||||
@ -338,8 +332,41 @@ public class Basic {
|
||||
}
|
||||
} 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 @@ public class Basic {
|
||||
.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 @@ public class Basic {
|
||||
throw new RuntimeException(x);
|
||||
}
|
||||
|
||||
// check that cancelled method is invoked
|
||||
if (cancelled)
|
||||
await(latch);
|
||||
|
||||
ch.close();
|
||||
}
|
||||
}
|
||||
@ -547,8 +560,6 @@ public class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Long position) {
|
||||
}
|
||||
public void cancelled(Long position) {
|
||||
}
|
||||
});
|
||||
|
||||
// wait for writes to complete
|
||||
@ -574,8 +585,6 @@ public class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Long position) {
|
||||
}
|
||||
public void cancelled(Long position) {
|
||||
}
|
||||
});
|
||||
|
||||
// wait for reads to complete
|
||||
|
@ -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 class CustomThreadPool {
|
||||
}
|
||||
public void failed(Throwable exc, AtomicReference<Thread> invoker) {
|
||||
}
|
||||
public void cancelled(AtomicReference<Thread> invoker) {
|
||||
}
|
||||
});
|
||||
Thread t;
|
||||
while ((t = invoker.get()) == null) {
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
|
||||
/* @test
|
||||
* @bug 4607272 6814948
|
||||
* @bug 4607272 6814948 6842687
|
||||
* @summary Unit test for AsynchronousFileChannel#lock method
|
||||
*/
|
||||
|
||||
@ -97,7 +97,7 @@ public class Lock {
|
||||
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
|
||||
|
@ -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 class Basic {
|
||||
public void failed(Throwable exc, Void att) {
|
||||
exception.set(exc);
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// check AcceptPendingException
|
||||
|
@ -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 class Basic {
|
||||
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 class Basic {
|
||||
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 @@ public class Basic {
|
||||
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 @@ public class Basic {
|
||||
} 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 class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
latch.await();
|
||||
@ -460,8 +447,6 @@ public class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// trickle the writing
|
||||
@ -507,26 +492,24 @@ public class Basic {
|
||||
}
|
||||
|
||||
// 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 @@ public class Basic {
|
||||
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 class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// read to EOF or buffer full
|
||||
@ -613,19 +604,29 @@ public class Basic {
|
||||
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 class Basic {
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
|
||||
// give time for socket buffer to fill up.
|
||||
@ -658,7 +657,7 @@ public class Basic {
|
||||
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 @@ public class Basic {
|
||||
|
||||
System.out.println("-- timeout when reading --");
|
||||
|
||||
// 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");
|
||||
|
||||
final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
|
||||
|
||||
// this read should timeout
|
||||
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 class Basic {
|
||||
public void failed(Throwable exc, AsynchronousSocketChannel ch) {
|
||||
writeException.set(exc);
|
||||
}
|
||||
public void cancelled(AsynchronousSocketChannel ch) {
|
||||
}
|
||||
});
|
||||
|
||||
// wait for exception
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 6834246
|
||||
* @bug 6834246 6842687
|
||||
* @summary Stress test connections through the loopback interface
|
||||
*/
|
||||
|
||||
@ -114,8 +114,6 @@ public class StressLoopback {
|
||||
exc.printStackTrace();
|
||||
closeUnchecked(channel);
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -156,8 +154,6 @@ public class StressLoopback {
|
||||
exc.printStackTrace();
|
||||
closeUnchecked(channel);
|
||||
}
|
||||
public void cancelled(Void att) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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 @@ public class ReleaseOnCloseDeadlock {
|
||||
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) {
|
||||
|
695
jdk/test/java/nio/file/Path/CheckPermissions.java
Normal file
695
jdk/test/java/nio/file/Path/CheckPermissions.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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 ..
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4313887
|
||||
* @bug 4313887 6866397
|
||||
* @summary Unit test for java.nio.file.PathMatcher
|
||||
*/
|
||||
|
||||
@ -68,6 +68,20 @@ public class Basic {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class Basic {
|
||||
assertMatch("one*two", "one\\*two");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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++;
|
||||
}
|
||||
assertRegExMatch("foo.html", ".*\\.html");
|
||||
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
assertRegExMatch("foo012", "foo\\d+");
|
||||
assertRegExMatch("fo o", "fo\\so");
|
||||
assertRegExMatch("foo", "\\w+");
|
||||
}
|
||||
|
||||
// unknown syntax
|
||||
|
60
jdk/test/java/util/prefs/CommentsInXml.java
Normal file
60
jdk/test/java/util/prefs/CommentsInXml.java
Normal file
@ -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
|
||||
}
|
||||
}
|
49
jdk/test/java/util/prefs/ConflictInFlush.java
Normal file
49
jdk/test/java/util/prefs/ConflictInFlush.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
53
jdk/test/java/util/prefs/ExportNode.java
Normal file
53
jdk/test/java/util/prefs/ExportNode.java
Normal file
@ -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)) {
|
||||
}
|
||||
}
|
||||
}
|
95
jdk/test/java/util/prefs/ExportSubtree.java
Normal file
95
jdk/test/java/util/prefs/ExportSubtree.java
Normal file
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user