提交 4dde5214 编写于 作者: A asaha

Merge

^build/ ^build/
^dist/ ^dist/
^nbproject/private/ ^nbproject/private/
^make/netbeans/.*/nbproject/private/
^make/netbeans/.*/build/
^make/netbeans/.*/dist/
...@@ -43,3 +43,4 @@ a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64 ...@@ -43,3 +43,4 @@ a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64
bd31b30a5b21f20e42965b1633f18a5c7946d398 jdk7-b66 bd31b30a5b21f20e42965b1633f18a5c7946d398 jdk7-b66
a952aafd5181af953b0ef3010dbd2fcc28460e8a jdk7-b67 a952aafd5181af953b0ef3010dbd2fcc28460e8a jdk7-b67
b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68 b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68
226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69
...@@ -67,15 +67,14 @@ ifeq ($(STANDALONE),true) ...@@ -67,15 +67,14 @@ ifeq ($(STANDALONE),true)
$(ZIPOBJDIR)/deflate.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/deflate.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/trees.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/trees.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/zadler32.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/zadler32.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/compress.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/zutil.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/zutil.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inflate.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/inflate.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infblock.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/infback.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infcodes.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inftrees.$(OBJECT_SUFFIX) \ $(ZIPOBJDIR)/inftrees.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infutil.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inffast.$(OBJECT_SUFFIX) $(ZIPOBJDIR)/inffast.$(OBJECT_SUFFIX)
ZINCLUDE=-I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3 ZINCLUDE=-I$(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
OTHER_CXXFLAGS += $(ZINCLUDE) OTHER_CXXFLAGS += $(ZINCLUDE)
LDDFLAGS += $(ZIPOBJS) LDDFLAGS += $(ZIPOBJS)
else else
......
...@@ -242,6 +242,12 @@ DEVTOOLS_FT_DIR_EXISTS = $(shell \ ...@@ -242,6 +242,12 @@ DEVTOOLS_FT_DIR_EXISTS = $(shell \
endif endif
endif endif
#
# zlib version
#
ZLIB_VERSION = 1.2.3
# #
# Localizations for the different parts of the product beyond English # Localizations for the different parts of the product beyond English
# #
......
...@@ -44,7 +44,6 @@ MS_RUNTIME_STATIC = true ...@@ -44,7 +44,6 @@ MS_RUNTIME_STATIC = true
include $(BUILDDIR)/common/Defs.gmk include $(BUILDDIR)/common/Defs.gmk
ZLIB_VERSION = 1.1.3
ZIP_SRC = $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION) ZIP_SRC = $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
...@@ -68,12 +67,10 @@ FILES_c = \ ...@@ -68,12 +67,10 @@ FILES_c = \
wildcard.c \ wildcard.c \
jli_util.c \ jli_util.c \
inflate.c \ inflate.c \
infblock.c \
inftrees.c \ inftrees.c \
infcodes.c \
inffast.c \ inffast.c \
infutil.c \
zadler32.c \ zadler32.c \
zcrc32.c \
zutil.c zutil.c
ifneq ($(PLATFORM), windows) ifneq ($(PLATFORM), windows)
......
...@@ -160,7 +160,6 @@ FILES_src = \ ...@@ -160,7 +160,6 @@ FILES_src = \
\ \
sun/nio/ByteBuffered.java \ sun/nio/ByteBuffered.java \
\ \
sun/nio/ch/AbstractFuture.java \
sun/nio/ch/AbstractPollArrayWrapper.java \ sun/nio/ch/AbstractPollArrayWrapper.java \
sun/nio/ch/AllocatedNativeObject.java \ sun/nio/ch/AllocatedNativeObject.java \
sun/nio/ch/AsynchronousChannelGroupImpl.java \ sun/nio/ch/AsynchronousChannelGroupImpl.java \
......
...@@ -29,15 +29,16 @@ FILES_c = \ ...@@ -29,15 +29,16 @@ FILES_c = \
Deflater.c \ Deflater.c \
Inflater.c \ Inflater.c \
ZipFile.c \ ZipFile.c \
zadler32.c \ zip_util.c \
zcrc32.c \ compress.c \
deflate.c \ deflate.c \
trees.c \ gzio.c \
zutil.c \ infback.c \
inffast.c \
inflate.c \ inflate.c \
infblock.c \
inftrees.c \ inftrees.c \
infcodes.c \ trees.c \
infutil.c \ uncompr.c \
inffast.c \ zadler32.c \
zip_util.c zcrc32.c \
zutil.c
...@@ -30,7 +30,9 @@ LIBRARY = zip ...@@ -30,7 +30,9 @@ LIBRARY = zip
PRODUCT = sun PRODUCT = sun
include $(BUILDDIR)/common/Defs.gmk include $(BUILDDIR)/common/Defs.gmk
ZLIB_VERSION = 1.1.3 #
# ZLIB_VERSION is defined in make/common/Defs.gmk
#
# #
# Files to compile. # Files to compile.
......
...@@ -32,38 +32,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs; ...@@ -32,38 +32,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;
text: .text%zcalloc; text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset; text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes; text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate; text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read; text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read; text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj/inftrees.o; text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj/inftrees.o;
text: .text%zcfree; text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%ZIP_ReadEntry; text: .text%ZIP_ReadEntry;
text: .text%InflateFully; text: .text%InflateFully;
text: .text%inflateEnd; text: .text%inflateEnd;
text: .text%inflate_blocks_free;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset; text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_ZipFile_close; text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close; text: .text%ZIP_Close;
......
...@@ -31,37 +31,13 @@ text: .text%Java_java_util_zip_Inflater_initIDs; ...@@ -31,37 +31,13 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;
text: .text%zcalloc; text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes; text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read; text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read; text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj/inftrees.o;
text: .text%zcfree; text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset; text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_Inflater_end; text: .text%Java_java_util_zip_Inflater_end;
text: .text%inflateEnd; text: .text%inflateEnd;
text: .text%inflate_blocks_free;
text: .text%Java_java_util_zip_ZipFile_close; text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close; text: .text%ZIP_Close;
data = R0x2000; data = R0x2000;
text = LOAD ?RXO; text = LOAD ?RXO;
# Test Null
text: .text%ZIP_Open; text: .text%ZIP_Open;
text: .text%ZIP_Open_Generic; text: .text%ZIP_Open_Generic;
text: .text%InitializeZip; text: .text%InitializeZip;
...@@ -32,38 +31,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs; ...@@ -32,38 +31,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;
text: .text%zcalloc; text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset; text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes; text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate; text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read; text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read; text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj64/inftrees.o; text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj64/inftrees.o;
text: .text%zcfree; text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%ZIP_ReadEntry; text: .text%ZIP_ReadEntry;
text: .text%InflateFully; text: .text%InflateFully;
text: .text%inflateEnd; text: .text%inflateEnd;
text: .text%inflate_blocks_free;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset; text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_ZipFile_close; text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close; text: .text%ZIP_Close;
......
<?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>
此差异已折叠。
#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=|
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
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
<?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>
#Path to FindbugsSettingsFile (relative)
findbugs.settings.file=findbugs.settings
...@@ -52,12 +52,10 @@ FILES_c = \ ...@@ -52,12 +52,10 @@ FILES_c = \
compress.c \ compress.c \
deflate.c \ deflate.c \
gzio.c \ gzio.c \
infblock.c \ infback.c \
infcodes.c \
inffast.c \ inffast.c \
inflate.c \ inflate.c \
inftrees.c \ inftrees.c \
infutil.c \
trees.c \ trees.c \
uncompr.c \ uncompr.c \
zadler32.c \ zadler32.c \
......
...@@ -77,13 +77,13 @@ endif # PLATFORM ...@@ -77,13 +77,13 @@ endif # PLATFORM
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/splashscreen vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/splashscreen
vpath %.c $(SHARE_SRC)/native/$(PKGDIR) vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/giflib vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/giflib
vpath %.c $(SHARE_SRC)/native/java/util/zip/zlib-1.1.3 vpath %.c $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/libpng vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/libpng
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3 CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
# Shun the less than portable MMX assembly code in pnggccrd.c, # Shun the less than portable MMX assembly code in pnggccrd.c,
# and use alternative implementations in C. # and use alternative implementations in C.
......
...@@ -30,7 +30,7 @@ import java.io.*; ...@@ -30,7 +30,7 @@ import java.io.*;
abstract class AbstractNamedNode extends Node { abstract class AbstractNamedNode extends Node {
NameNode nameNode; NameNode nameNode = null;
String name; String name;
public String name() { public String name() {
......
...@@ -30,7 +30,7 @@ import java.io.*; ...@@ -30,7 +30,7 @@ import java.io.*;
class AltNode extends AbstractGroupNode implements TypeNode { class AltNode extends AbstractGroupNode implements TypeNode {
SelectNode select; SelectNode select = null;
void constrain(Context ctx) { void constrain(Context ctx) {
super.constrain(ctx); super.constrain(ctx);
......
...@@ -33,13 +33,7 @@ class ConstantSetNode extends AbstractNamedNode { ...@@ -33,13 +33,7 @@ class ConstantSetNode extends AbstractNamedNode {
/** /**
* The mapping between a constant and its value. * The mapping between a constant and its value.
*/ */
protected static Map<String, String> constantMap; protected static final Map<String, String> constantMap = new HashMap<String, String>();
ConstantSetNode(){
if (constantMap == null) {
constantMap = new HashMap<String, String>();
}
}
void prune() { void prune() {
List<Node> addons = new ArrayList<Node>(); List<Node> addons = new ArrayList<Node>();
...@@ -95,9 +89,6 @@ class ConstantSetNode extends AbstractNamedNode { ...@@ -95,9 +89,6 @@ class ConstantSetNode extends AbstractNamedNode {
} }
public static String getConstant(String key){ public static String getConstant(String key){
if (constantMap == null) {
return "";
}
String com = constantMap.get(key); String com = constantMap.get(key);
if(com == null){ if(com == null){
return ""; return "";
......
...@@ -25,13 +25,11 @@ ...@@ -25,13 +25,11 @@
package build.tools.jdwpgen; package build.tools.jdwpgen;
import java.util.*;
import java.io.*; import java.io.*;
class Main { class Main {
static String specSource; static String specSource;
static Map nameMap = new HashMap();
static boolean genDebug = true; static boolean genDebug = true;
static void usage() { static void usage() {
...@@ -43,7 +41,6 @@ class Main { ...@@ -43,7 +41,6 @@ class Main {
System.err.println("-doc <doc_output>"); System.err.println("-doc <doc_output>");
System.err.println("-jdi <java_output>"); System.err.println("-jdi <java_output>");
System.err.println("-include <include_file_output>"); System.err.println("-include <include_file_output>");
System.exit(1);
} }
public static void main(String args[]) throws IOException { public static void main(String args[]) throws IOException {
...@@ -66,6 +63,7 @@ class Main { ...@@ -66,6 +63,7 @@ class Main {
} else { } else {
System.err.println("Invalid option: " + arg); System.err.println("Invalid option: " + arg);
usage(); usage();
return;
} }
} else { } else {
specSource = arg; specSource = arg;
...@@ -75,6 +73,7 @@ class Main { ...@@ -75,6 +73,7 @@ class Main {
if (reader == null) { if (reader == null) {
System.err.println("<spec_input> must be specified"); System.err.println("<spec_input> must be specified");
usage(); usage();
return;
} }
Parse parse = new Parse(reader); Parse parse = new Parse(reader);
......
...@@ -36,7 +36,7 @@ abstract class Node { ...@@ -36,7 +36,7 @@ abstract class Node {
int lineno; int lineno;
List<String> commentList = new ArrayList<String>(); List<String> commentList = new ArrayList<String>();
Node parent = null; Node parent = null;
Context context; Context context = null;
static final int maxStructIndent = 5; static final int maxStructIndent = 5;
static int structIndent = 0; // horrible hack static int structIndent = 0; // horrible hack
...@@ -82,7 +82,7 @@ abstract class Node { ...@@ -82,7 +82,7 @@ abstract class Node {
} }
void indent(PrintWriter writer, int depth) { void indent(PrintWriter writer, int depth) {
for (int i = depth; i > 0; --i) { for (int i = 0; i < depth; i++) {
writer.print(" "); writer.print(" ");
} }
} }
...@@ -195,6 +195,6 @@ abstract class Node { ...@@ -195,6 +195,6 @@ abstract class Node {
System.err.println(Main.specSource + ":" + lineno + ": " + System.err.println(Main.specSource + ":" + lineno + ": " +
kind + " - " + errmsg); kind + " - " + errmsg);
System.err.println(); System.err.println();
System.exit(1); throw new RuntimeException("Error: " + errmsg);
} }
} }
...@@ -146,8 +146,12 @@ class Parse { ...@@ -146,8 +146,12 @@ class Parse {
Node node = (Node)proto.getClass().newInstance(); Node node = (Node)proto.getClass().newInstance();
node.set(kind, list, izer.lineno()); node.set(kind, list, izer.lineno());
return node; return node;
} catch (Exception exc) { } catch (InstantiationException exc) {
error(exc.toString()); error(exc.toString());
return null;
} catch (IllegalAccessException exc) {
error(exc.toString());
return null;
} }
} }
} else { } else {
...@@ -166,6 +170,6 @@ class Parse { ...@@ -166,6 +170,6 @@ class Parse {
void error(String errmsg) { void error(String errmsg) {
System.err.println(Main.specSource + ":" + izer.lineno() + System.err.println(Main.specSource + ":" + izer.lineno() +
": " + errmsg); ": " + errmsg);
System.exit(1); throw new RuntimeException("Error: " + errmsg);
} }
} }
...@@ -30,7 +30,7 @@ import java.io.*; ...@@ -30,7 +30,7 @@ import java.io.*;
class RepeatNode extends AbstractTypeNode { class RepeatNode extends AbstractTypeNode {
Node member; Node member = null;
void constrain(Context ctx) { void constrain(Context ctx) {
super.constrain(ctx); super.constrain(ctx);
......
...@@ -30,7 +30,7 @@ import java.io.*; ...@@ -30,7 +30,7 @@ import java.io.*;
class SelectNode extends AbstractGroupNode implements TypeNode { class SelectNode extends AbstractGroupNode implements TypeNode {
AbstractSimpleTypeNode typeNode; AbstractSimpleTypeNode typeNode = null;
void prune() { void prune() {
super.prune(); super.prune();
......
...@@ -28,8 +28,12 @@ package java.lang; ...@@ -28,8 +28,12 @@ package java.lang;
/** /**
* Thrown when an application tries to access an enum constant by name * Thrown when an application tries to access an enum constant by name
* and the enum type contains no constant with the specified 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 * @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5 * @since 1.5
*/ */
public class EnumConstantNotPresentException extends RuntimeException { public class EnumConstantNotPresentException extends RuntimeException {
......
...@@ -35,8 +35,12 @@ package java.lang; ...@@ -35,8 +35,12 @@ package java.lang;
* <p>Note that this exception may be used when undefined type variables * <p>Note that this exception may be used when undefined type variables
* are accessed as well as when types (e.g., classes, interfaces or * are accessed as well as when types (e.g., classes, interfaces or
* annotation types) are loaded. * 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 * @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5 * @since 1.5
*/ */
public class TypeNotPresentException extends RuntimeException { public class TypeNotPresentException extends RuntimeException {
......
...@@ -28,8 +28,12 @@ package java.lang.annotation; ...@@ -28,8 +28,12 @@ package java.lang.annotation;
/** /**
* Thrown when the annotation parser attempts to read an annotation * Thrown when the annotation parser attempts to read an annotation
* from a class file and determines that the annotation is malformed. * 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 * @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5 * @since 1.5
*/ */
public class AnnotationFormatError extends Error { public class AnnotationFormatError extends Error {
......
...@@ -30,8 +30,12 @@ import java.lang.reflect.Method; ...@@ -30,8 +30,12 @@ import java.lang.reflect.Method;
* Thrown to indicate that a program has attempted to access an element of * Thrown to indicate that a program has attempted to access an element of
* an annotation whose type has changed after the annotation was compiled * an annotation whose type has changed after the annotation was compiled
* (or serialized). * (or serialized).
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
* *
* @author Josh Bloch * @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5 * @since 1.5
*/ */
public class AnnotationTypeMismatchException extends RuntimeException { public class AnnotationTypeMismatchException extends RuntimeException {
......
...@@ -30,8 +30,12 @@ package java.lang.annotation; ...@@ -30,8 +30,12 @@ package java.lang.annotation;
* an annotation type that was added to the annotation type definition after * an annotation type that was added to the annotation type definition after
* the annotation was compiled (or serialized). This exception will not be * the annotation was compiled (or serialized). This exception will not be
* thrown if the new element has a default value. * 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 * @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5 * @since 1.5
*/ */
public class IncompleteAnnotationException extends RuntimeException { public class IncompleteAnnotationException extends RuntimeException {
......
...@@ -50,6 +50,11 @@ import java.lang.annotation.Annotation; ...@@ -50,6 +50,11 @@ import java.lang.annotation.Annotation;
* java.lang.annotation.AnnotationTypeMismatchException} or an * java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}. * {@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 * @since 1.5
* @author Josh Bloch * @author Josh Bloch
*/ */
......
...@@ -56,18 +56,18 @@ public interface AsynchronousByteChannel ...@@ -56,18 +56,18 @@ public interface AsynchronousByteChannel
/** /**
* Reads a sequence of bytes from this channel into the given buffer. * 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 * <p> This method initiates an asynchronous read operation to read a
* this channel into the given buffer. The method returns a {@link Future} * sequence of bytes from this channel into the given buffer. The {@code
* representing the pending result of the operation. The result of the * handler} parameter is a completion handler that is invoked when the read
* operation, obtained by invoking the {@code Future} 's {@link * operation completes (or fails). The result passed to the completion
* Future#get() get} method, is the number of bytes read or {@code -1} if * handler is the number of bytes read or {@code -1} if no bytes could be
* all bytes have been read and the channel has reached end-of-stream. * read because the channel has reached end-of-stream.
* *
* <p> This method initiates a read operation to read up to <i>r</i> bytes * <p> The read operation may read up to <i>r</i> bytes from the channel,
* from the channel, where <i>r</i> is the number of bytes remaining in the * where <i>r</i> is the number of bytes remaining in the buffer, that is,
* buffer, that is, {@code dst.remaining()} at the time that the read is * {@code dst.remaining()} at the time that the read is attempted. Where
* attempted. Where <i>r</i> is 0, the read operation completes immediately * <i>r</i> is 0, the read operation completes immediately with a result of
* with a result of {@code 0} without initiating an I/O operation. * {@code 0} without initiating an I/O operation.
* *
* <p> Suppose that a byte sequence of length <i>n</i> is read, where * <p> Suppose that a byte sequence of length <i>n</i> is read, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>. * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
...@@ -79,44 +79,46 @@ public interface AsynchronousByteChannel ...@@ -79,44 +79,46 @@ public interface AsynchronousByteChannel
* <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed. * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
* *
* <p> Buffers are not safe for use by multiple concurrent threads so care * <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 * <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 * 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 * initiates a read operation before a previous read operation has
* completed then a {@link ReadPendingException} will be thrown. * 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 * @param dst
* The buffer into which bytes are to be transferred * The buffer into which bytes are to be transferred
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The completion handler object; can be {@code null} * The completion handler
*
* @return A Future representing the result of the operation
* *
* @throws IllegalArgumentException * @throws IllegalArgumentException
* If the buffer is read-only * If the buffer is read-only
* @throws ReadPendingException * @throws ReadPendingException
* If the channel does not allow more than one read to be outstanding * If the channel does not allow more than one read to be outstanding
* and a previous read has not completed * 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> void read(ByteBuffer dst,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler); CompletionHandler<Integer,? super A> handler);
/** /**
* Reads a sequence of bytes from this channel into the given buffer. * 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> * <p> This method initiates an asynchronous read operation to read a
* behaves in exactly the same manner as the invocation * sequence of bytes from this channel into the given buffer. The method
* <blockquote><pre> * behaves in exactly the same manner as the {@link
* c.read(dst, null, null);</pre></blockquote> * #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 * @param dst
* The buffer into which bytes are to be transferred * The buffer into which bytes are to be transferred
...@@ -134,17 +136,17 @@ public interface AsynchronousByteChannel ...@@ -134,17 +136,17 @@ public interface AsynchronousByteChannel
/** /**
* Writes a sequence of bytes to this channel from the given buffer. * 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 * <p> This method initiates an asynchronous write operation to write a
* this channel from the given buffer. This method returns a {@link * sequence of bytes to this channel from the given buffer. The {@code
* Future} representing the pending result of the operation. The result * handler} parameter is a completion handler that is invoked when the write
* of the operation, obtained by invoking the <tt>Future</tt>'s {@link * operation completes (or fails). The result passed to the completion
* Future#get() get} method, is the number of bytes written, possibly zero. * handler is the number of bytes written.
* *
* <p> This method initiates a write operation to write up to <i>r</i> bytes * <p> The write operation may write up to <i>r</i> bytes to the channel,
* to the channel, where <i>r</i> is the number of bytes remaining in the * where <i>r</i> is the number of bytes remaining in the buffer, that is,
* buffer, that is, {@code src.remaining()} at the moment the write is * {@code src.remaining()} at the time that the write is attempted. Where
* attempted. Where <i>r</i> is 0, the write operation completes immediately * <i>r</i> is 0, the write operation completes immediately with a result of
* with a result of {@code 0} without initiating an I/O operation. * {@code 0} without initiating an I/O operation.
* *
* <p> Suppose that a byte sequence of length <i>n</i> is written, where * <p> Suppose that a byte sequence of length <i>n</i> is written, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>. * <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
...@@ -156,41 +158,43 @@ public interface AsynchronousByteChannel ...@@ -156,41 +158,43 @@ public interface AsynchronousByteChannel
* <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed. * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
* *
* <p> Buffers are not safe for use by multiple concurrent threads so care * <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 * <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 * 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 * initiates a write operation before a previous write operation has
* completed then a {@link WritePendingException} will be thrown. * 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 * @param src
* The buffer from which bytes are to be retrieved * The buffer from which bytes are to be retrieved
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The completion handler object; can be {@code null} * The completion handler object
*
* @return A Future representing the result of the operation
* *
* @throws WritePendingException * @throws WritePendingException
* If the channel does not allow more than one write to be outstanding * If the channel does not allow more than one write to be outstanding
* and a previous write has not completed * 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> void write(ByteBuffer src,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler); CompletionHandler<Integer,? super A> handler);
/** /**
* Writes a sequence of bytes to this channel from the given buffer. * 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> * <p> This method initiates an asynchronous write operation to write a
* behaves in exactly the same manner as the invocation * sequence of bytes to this channel from the given buffer. The method
* <blockquote><pre> * behaves in exactly the same manner as the {@link
* c.write(src, null, null);</pre></blockquote> * #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 * @param src
* The buffer from which bytes are to be retrieved * The buffer from which bytes are to be retrieved
......
...@@ -34,7 +34,8 @@ import java.util.concurrent.Future; // javadoc ...@@ -34,7 +34,8 @@ import java.util.concurrent.Future; // javadoc
* *
* <ol> * <ol>
* <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li> * <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li>
* <li><pre>Future&lt;V&gt; <em>operation</em>(<em>...</em> A attachment, {@link CompletionHandler}&lt;V,? super A&gt handler)</pre></li> * <li><pre>void <em>operation</em>(<em>...</em> A attachment, {@link
* CompletionHandler}&lt;V,? super A&gt; handler)</pre></li>
* </ol> * </ol>
* *
* where <i>operation</i> is the name of the I/O operation (read or write for * 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 ...@@ -48,7 +49,7 @@ import java.util.concurrent.Future; // javadoc
* interface may be used to check if the operation has completed, wait for its * 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 * 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 * 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 * <p> A channel that implements this interface is <em>asynchronously
* closeable</em>: If an I/O operation is outstanding on the channel and the * closeable</em>: If an I/O operation is outstanding on the channel and the
...@@ -63,33 +64,33 @@ import java.util.concurrent.Future; // javadoc ...@@ -63,33 +64,33 @@ import java.util.concurrent.Future; // javadoc
* <h4>Cancellation</h4> * <h4>Cancellation</h4>
* *
* <p> The {@code Future} interface defines the {@link Future#cancel cancel} * <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}.
* <p> Where the {@code cancel} method is invoked with the {@code * 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 {@link Future#cancel cancel} method is invoked with the {@code
* mayInterruptIfRunning} parameter set to {@code true} then the I/O operation * 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 * may be interrupted by closing the channel. In that case all threads waiting
* operations outstanding on the channel to complete with the exception {@link * on the result of the I/O operation throw {@code CancellationException} and
* AsynchronousCloseException}. * any other I/O operations outstanding on the channel 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.
* *
* <p> Where the {@code cancel} method is invoked to cancel read or write * <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 * operations then it is recommended that all buffers used in the I/O operations
* discarded or care taken to ensure that the buffers are not accessed while the * be discarded or care taken to ensure that the buffers are not accessed while
* channel remains open. * the channel remains open.
* *
* @since 1.7 * @since 1.7
*/ */
...@@ -102,7 +103,7 @@ public interface AsynchronousChannel ...@@ -102,7 +103,7 @@ public interface AsynchronousChannel
* *
* <p> Any outstanding asynchronous operations upon this channel will * <p> Any outstanding asynchronous operations upon this channel will
* complete with the exception {@link AsynchronousCloseException}. After a * 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}. * operations complete immediately with cause {@link ClosedChannelException}.
* *
* <p> This method otherwise behaves exactly as specified by the {@link * <p> This method otherwise behaves exactly as specified by the {@link
......
...@@ -85,9 +85,6 @@ import java.io.IOException; ...@@ -85,9 +85,6 @@ import java.io.IOException;
* public void failed(Throwable exc, Void att) { * public void failed(Throwable exc, Void att) {
* ... * ...
* } * }
* public void cancelled(Void att) {
* ...
* }
* }); * });
* </pre> * </pre>
* *
...@@ -240,11 +237,11 @@ public abstract class AsynchronousServerSocketChannel ...@@ -240,11 +237,11 @@ public abstract class AsynchronousServerSocketChannel
/** /**
* Accepts a connection. * Accepts a connection.
* *
* <p> This method initiates accepting a connection made to this channel's * <p> This method initiates an asynchronous operation to accept a
* socket, returning a {@link Future} representing the pending result * connection made to this channel's socket. The {@code handler} parameter is
* of the operation. The {@code Future}'s {@link Future#get() get} * a completion handler that is invoked when a connection is accepted (or
* method will return the {@link AsynchronousSocketChannel} for the new * the operation fails). The result passed to the completion handler is
* connection on successful completion. * the {@link AsynchronousSocketChannel} to the new connection.
* *
* <p> When a new connection is accepted then the resulting {@code * <p> When a new connection is accepted then the resulting {@code
* AsynchronousSocketChannel} will be bound to the same {@link * AsynchronousSocketChannel} will be bound to the same {@link
...@@ -269,35 +266,35 @@ public abstract class AsynchronousServerSocketChannel ...@@ -269,35 +266,35 @@ public abstract class AsynchronousServerSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return an <tt>Future</tt> object representing the pending result
* *
* @throws AcceptPendingException * @throws AcceptPendingException
* If an accept operation is already in progress on this channel * If an accept operation is already in progress on this channel
* @throws NotYetBoundException * @throws NotYetBoundException
* If this channel's socket has not yet been bound * If this channel's socket has not yet been bound
* @throws ShutdownChannelGroupException * @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown * If the channel group has terminated
*/ */
public abstract <A> Future<AsynchronousSocketChannel> public abstract <A> void accept(A attachment,
accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler); CompletionHandler<AsynchronousSocketChannel,? super A> handler);
/** /**
* Accepts a connection. * Accepts a connection.
* *
* <p> This method is equivalent to invoking {@link * <p> This method initiates an asynchronous operation to accept a
* #accept(Object,CompletionHandler)} with the {@code attachment} * connection made to this channel's socket. The method behaves in exactly
* and {@code handler} parameters set to {@code null}. * 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 * @throws AcceptPendingException
* If an accept operation is already in progress on this channel * If an accept operation is already in progress on this channel
* @throws NotYetBoundException * @throws NotYetBoundException
* If this channel's socket has not yet been bound * If this channel's socket has not yet been bound
*/ */
public final Future<AsynchronousSocketChannel> accept() { public abstract Future<AsynchronousSocketChannel> accept();
return accept(null, null);
}
} }
...@@ -274,14 +274,11 @@ public abstract class AsynchronousSocketChannel ...@@ -274,14 +274,11 @@ public abstract class AsynchronousSocketChannel
/** /**
* Connects this channel. * Connects this channel.
* *
* <p> This method initiates an operation to connect this channel, returning * <p> This method initiates an operation to connect this channel. The
* a {@code Future} representing the pending result of the operation. If * {@code handler} parameter is a completion handler that is invoked when
* the connection is successfully established then the {@code Future}'s * the connection is successfully established or connection cannot be
* {@link Future#get() get} method will return {@code null}. If the * established. If the connection cannot be established then the channel is
* connection cannot be established then the channel is closed. In that case, * closed.
* invoking the {@code get} method throws {@link
* java.util.concurrent.ExecutionException} with an {@code IOException} as
* the cause.
* *
* <p> This method performs exactly the same security checks as the {@link * <p> This method performs exactly the same security checks as the {@link
* java.net.Socket} class. That is, if a security manager has been * java.net.Socket} class. That is, if a security manager has been
...@@ -294,9 +291,7 @@ public abstract class AsynchronousSocketChannel ...@@ -294,9 +291,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return A {@code Future} object representing the pending result
* *
* @throws UnresolvedAddressException * @throws UnresolvedAddressException
* If the given remote address is not fully resolved * If the given remote address is not fully resolved
...@@ -307,23 +302,26 @@ public abstract class AsynchronousSocketChannel ...@@ -307,23 +302,26 @@ public abstract class AsynchronousSocketChannel
* @throws ConnectionPendingException * @throws ConnectionPendingException
* If a connection operation is already in progress on this channel * If a connection operation is already in progress on this channel
* @throws ShutdownChannelGroupException * @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown * If the channel group has terminated
* @throws SecurityException * @throws SecurityException
* If a security manager has been installed * If a security manager has been installed
* and it does not permit access to the given remote endpoint * and it does not permit access to the given remote endpoint
* *
* @see #getRemoteAddress * @see #getRemoteAddress
*/ */
public abstract <A> Future<Void> connect(SocketAddress remote, public abstract <A> void connect(SocketAddress remote,
A attachment, A attachment,
CompletionHandler<Void,? super A> handler); CompletionHandler<Void,? super A> handler);
/** /**
* Connects this channel. * Connects this channel.
* *
* <p> This method is equivalent to invoking {@link * <p> This method initiates an operation to connect this channel. This
* #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment} * method behaves in exactly the same manner as the {@link
* and handler parameters set to {@code null}. * #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 * @param remote
* The remote address to which this channel is to be connected * The remote address to which this channel is to be connected
...@@ -342,18 +340,17 @@ public abstract class AsynchronousSocketChannel ...@@ -342,18 +340,17 @@ public abstract class AsynchronousSocketChannel
* If a security manager has been installed * If a security manager has been installed
* and it does not permit access to the given remote endpoint * and it does not permit access to the given remote endpoint
*/ */
public final Future<Void> connect(SocketAddress remote) { public abstract Future<Void> connect(SocketAddress remote);
return connect(remote, null, null);
}
/** /**
* Reads a sequence of bytes from this channel into the given buffer. * 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 * <p> This method initiates an asynchronous read operation to read a
* channel into the given buffer, returning a {@code Future} representing * sequence of bytes from this channel into the given buffer. The {@code
* the pending result of the operation. The {@code Future}'s {@link * handler} parameter is a completion handler that is invoked when the read
* Future#get() get} method returns the number of bytes read or {@code -1} * operation completes (or fails). The result passed to the completion
* if all bytes have been read and channel has reached end-of-stream. * 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 * <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link * completes then the operation completes with the exception {@link
...@@ -376,9 +373,7 @@ public abstract class AsynchronousSocketChannel ...@@ -376,9 +373,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return A {@code Future} object representing the pending result
* *
* @throws IllegalArgumentException * @throws IllegalArgumentException
* If the {@code timeout} parameter is negative or the buffer is * If the {@code timeout} parameter is negative or the buffer is
...@@ -388,13 +383,13 @@ public abstract class AsynchronousSocketChannel ...@@ -388,13 +383,13 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @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, public abstract <A> void read(ByteBuffer dst,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler); CompletionHandler<Integer,? super A> handler);
/** /**
* @throws IllegalArgumentException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc}
...@@ -402,14 +397,14 @@ public abstract class AsynchronousSocketChannel ...@@ -402,14 +397,14 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown * If the channel group has terminated
*/ */
@Override @Override
public final <A> Future<Integer> read(ByteBuffer dst, public final <A> void read(ByteBuffer dst,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler) 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 ...@@ -419,16 +414,18 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected * If this channel is not yet connected
*/ */
@Override @Override
public final Future<Integer> read(ByteBuffer dst) { public abstract Future<Integer> read(ByteBuffer dst);
return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
/** /**
* Reads a sequence of bytes from this channel into a subsequence of the * Reads a sequence of bytes from this channel into a subsequence of the
* given buffers. This operation, sometimes called a <em>scattering read</em>, * given buffers. This operation, sometimes called a <em>scattering read</em>,
* is often useful when implementing network protocols that group data into * is often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a * 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, * <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 * where <i>r</i> is the total number of bytes remaining in the specified
...@@ -456,11 +453,6 @@ public abstract class AsynchronousSocketChannel ...@@ -456,11 +453,6 @@ public abstract class AsynchronousSocketChannel
* I/O operation is performed with the maximum number of buffers allowed by * I/O operation is performed with the maximum number of buffers allowed by
* the operating system. * 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 * <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link * completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the * InterruptedByTimeoutException}. Where a timeout occurs, and the
...@@ -485,9 +477,7 @@ public abstract class AsynchronousSocketChannel ...@@ -485,9 +477,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return A {@code Future} object representing the pending result
* *
* @throws IndexOutOfBoundsException * @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length} * If the pre-conditions for the {@code offset} and {@code length}
...@@ -500,23 +490,24 @@ public abstract class AsynchronousSocketChannel ...@@ -500,23 +490,24 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @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, public abstract <A> void read(ByteBuffer[] dsts,
int offset, int offset,
int length, int length,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Long,? super A> handler); CompletionHandler<Long,? super A> handler);
/** /**
* Writes a sequence of bytes to this channel from the given buffer. * 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 * <p> This method initiates an asynchronous write operation to write a
* from the given buffer, returning a {@code Future} representing the * sequence of bytes to this channel from the given buffer. The {@code
* pending result of the operation. The {@code Future}'s {@link Future#get() * handler} parameter is a completion handler that is invoked when the write
* get} method will return the number of bytes written. * 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 * <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link * completes then it completes with the exception {@link
...@@ -539,9 +530,7 @@ public abstract class AsynchronousSocketChannel ...@@ -539,9 +530,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return A {@code Future} object representing the pending result
* *
* @throws IllegalArgumentException * @throws IllegalArgumentException
* If the {@code timeout} parameter is negative * If the {@code timeout} parameter is negative
...@@ -550,28 +539,28 @@ public abstract class AsynchronousSocketChannel ...@@ -550,28 +539,28 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @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, public abstract <A> void write(ByteBuffer src,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler); CompletionHandler<Integer,? super A> handler);
/** /**
* @throws WritePendingException {@inheritDoc} * @throws WritePendingException {@inheritDoc}
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown * If the channel group has terminated
*/ */
@Override @Override
public final <A> Future<Integer> write(ByteBuffer src, public final <A> void write(ByteBuffer src,
A attachment, A attachment,
CompletionHandler<Integer,? super A> handler) 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 ...@@ -580,16 +569,16 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected * If this channel is not yet connected
*/ */
@Override @Override
public final Future<Integer> write(ByteBuffer src) { public abstract Future<Integer> write(ByteBuffer src);
return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
}
/** /**
* Writes a sequence of bytes to this channel from a subsequence of the given * 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 * buffers. This operation, sometimes called a <em>gathering write</em>, is
* often useful when implementing network protocols that group data into * often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a * 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, * <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 * where <i>r</i> is the total number of bytes remaining in the specified
...@@ -616,10 +605,6 @@ public abstract class AsynchronousSocketChannel ...@@ -616,10 +605,6 @@ public abstract class AsynchronousSocketChannel
* remaining), exceeds this limit, then the I/O operation is performed with * remaining), exceeds this limit, then the I/O operation is performed with
* the maximum number of buffers allowed by the operating system. * 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 * <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link * completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the * InterruptedByTimeoutException}. Where a timeout occurs, and the
...@@ -644,9 +629,7 @@ public abstract class AsynchronousSocketChannel ...@@ -644,9 +629,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment * @param attachment
* The object to attach to the I/O operation; can be {@code null} * The object to attach to the I/O operation; can be {@code null}
* @param handler * @param handler
* The handler for consuming the result; can be {@code null} * The handler for consuming the result
*
* @return A {@code Future} object representing the pending result
* *
* @throws IndexOutOfBoundsException * @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length} * If the pre-conditions for the {@code offset} and {@code length}
...@@ -658,13 +641,13 @@ public abstract class AsynchronousSocketChannel ...@@ -658,13 +641,13 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException * @throws NotYetConnectedException
* If this channel is not yet connected * If this channel is not yet connected
* @throws ShutdownChannelGroupException * @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, public abstract <A> void write(ByteBuffer[] srcs,
int offset, int offset,
int length, int length,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Long,? super A> handler); CompletionHandler<Long,? super A> handler);
} }
...@@ -182,7 +182,6 @@ public final class Channels { ...@@ -182,7 +182,6 @@ public final class Channels {
} }
/** /**
* {@note new}
* Constructs a stream that reads bytes from the given channel. * Constructs a stream that reads bytes from the given channel.
* *
* <p> The stream will not be buffered, and it will not support the {@link * <p> The stream will not be buffered, and it will not support the {@link
...@@ -258,7 +257,6 @@ public final class Channels { ...@@ -258,7 +257,6 @@ public final class Channels {
} }
/** /**
* {@note new}
* Constructs a stream that writes bytes to the given channel. * Constructs a stream that writes bytes to the given channel.
* *
* <p> The stream will not be buffered. The stream will be safe for access * <p> The stream will not be buffered. The stream will be safe for access
......
...@@ -32,11 +32,9 @@ package java.nio.channels; ...@@ -32,11 +32,9 @@ package java.nio.channels;
* handler to be specified to consume the result of an asynchronous operation. * handler to be specified to consume the result of an asynchronous operation.
* The {@link #completed completed} method is invoked when the I/O operation * The {@link #completed completed} method is invoked when the I/O operation
* completes successfully. The {@link #failed failed} method is invoked if the * completes successfully. The {@link #failed failed} method is invoked if the
* I/O operations fails. The {@link #cancelled cancelled} method is invoked when * I/O operations fails. The implementations of these methods should complete
* the I/O operation is cancelled by invoking the {@link * in a timely manner so as to avoid keeping the invoking thread from dispatching
* java.util.concurrent.Future#cancel cancel} method. The implementations of * to other completion handlers.
* 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 <V> The result type of the I/O operation
* @param <A> The type of the object attached to 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> { ...@@ -65,13 +63,4 @@ public interface CompletionHandler<V,A> {
* The object attached to the I/O operation when it was initiated. * The object attached to the I/O operation when it was initiated.
*/ */
void failed(Throwable exc, A attachment); 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; ...@@ -39,8 +39,7 @@ import java.util.Collections;
/** /**
* A channel for reading, writing, mapping, and manipulating a file. * A channel for reading, writing, mapping, and manipulating a file.
* *
* <p> {@note revised} * <p> A file channel is a {@link SeekableByteChannel} that is connected to
* 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 * 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) * be both {@link #position() <i>queried</i>} and {@link #position(long)
* <i>modified</i>}. The file itself contains a variable-length sequence * <i>modified</i>}. The file itself contains a variable-length sequence
...@@ -151,7 +150,6 @@ import java.util.Collections; ...@@ -151,7 +150,6 @@ import java.util.Collections;
* @author Mike McCloskey * @author Mike McCloskey
* @author JSR-51 Expert Group * @author JSR-51 Expert Group
* @since 1.4 * @since 1.4
* @updated 1.7
*/ */
public abstract class FileChannel public abstract class FileChannel
...@@ -164,7 +162,6 @@ public abstract class FileChannel ...@@ -164,7 +162,6 @@ public abstract class FileChannel
protected FileChannel() { } protected FileChannel() { }
/** /**
* {@note new}
* Opens or creates a file, returning a file channel to access the file. * Opens or creates a file, returning a file channel to access the file.
* *
* <p> The {@code options} parameter determines how the file is opened. * <p> The {@code options} parameter determines how the file is opened.
...@@ -293,7 +290,6 @@ public abstract class FileChannel ...@@ -293,7 +290,6 @@ public abstract class FileChannel
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0]; private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
/** /**
* {@note new}
* Opens or creates a file, returning a file channel to access the file. * 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 * <p> An invocation of this method behaves in exactly the same way as the
......
...@@ -114,7 +114,6 @@ import java.io.IOException; ...@@ -114,7 +114,6 @@ import java.io.IOException;
* @author Mark Reinhold * @author Mark Reinhold
* @author JSR-51 Expert Group * @author JSR-51 Expert Group
* @since 1.4 * @since 1.4
* @updated 1.7
*/ */
public abstract class FileLock { public abstract class FileLock {
...@@ -161,7 +160,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 * @param channel
* The channel upon whose file this lock is held * The channel upon whose file this lock is held
...@@ -199,7 +198,6 @@ public abstract class FileLock { ...@@ -199,7 +198,6 @@ public abstract class FileLock {
} }
/** /**
* {@note revised}
* Returns the file channel upon whose file this lock was acquired. * Returns the file channel upon whose file this lock was acquired.
* *
* <p> This method has been superseded by the {@link #acquiredBy acquiredBy} * <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
...@@ -213,7 +211,6 @@ public abstract class FileLock { ...@@ -213,7 +211,6 @@ public abstract class FileLock {
} }
/** /**
* {@note new}
* Returns the channel upon whose file this lock was acquired. * Returns the channel upon whose file this lock was acquired.
* *
* @return 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 " ...@@ -190,5 +190,5 @@ gen WritePendingException "
gen ShutdownChannelGroupException " gen ShutdownChannelGroupException "
* Unchecked exception thrown when an attempt is made to construct a channel in * 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 * 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 -3903801676350154157L
...@@ -285,7 +285,6 @@ ...@@ -285,7 +285,6 @@
* java.lang.NullPointerException NullPointerException} to be thrown. * java.lang.NullPointerException NullPointerException} to be thrown.
* *
* @since 1.4 * @since 1.4
* @updated 1.7
* @author Mark Reinhold * @author Mark Reinhold
* @author JSR-51 Expert Group * @author JSR-51 Expert Group
*/ */
......
...@@ -39,8 +39,6 @@ import java.io.IOException; ...@@ -39,8 +39,6 @@ import java.io.IOException;
* metadata or file attributes. * metadata or file attributes.
* *
* @since 1.7 * @since 1.7
* @see java.io.Inputs
* @see java.io.Outputs
* @see java.nio.file.attribute.Attributes * @see java.nio.file.attribute.Attributes
* @see java.io.File#toPath * @see java.io.File#toPath
*/ */
......
...@@ -101,12 +101,12 @@ import java.io.BufferedWriter; ...@@ -101,12 +101,12 @@ import java.io.BufferedWriter;
* &lt;!ATTLIST entry key CDATA #REQUIRED&gt; * &lt;!ATTLIST entry key CDATA #REQUIRED&gt;
* </pre> * </pre>
* *
* @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
* @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
*
* <p>This class is thread-safe: multiple threads can share a single * <p>This class is thread-safe: multiple threads can share a single
* <tt>Properties</tt> object without the need for external synchronization. * <tt>Properties</tt> object without the need for external synchronization.
* *
* @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
* @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
*
* @author Arthur van Hoff * @author Arthur van Hoff
* @author Michael McCloskey * @author Michael McCloskey
* @author Xueming Shen * @author Xueming Shen
......
...@@ -674,7 +674,6 @@ public final class Scanner implements Iterator<String> { ...@@ -674,7 +674,6 @@ public final class Scanner implements Iterator<String> {
} }
/** /**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned * Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into * from the specified file. Bytes from the file are converted into
* characters using the underlying platform's * characters using the underlying platform's
...@@ -694,7 +693,6 @@ public final class Scanner implements Iterator<String> { ...@@ -694,7 +693,6 @@ public final class Scanner implements Iterator<String> {
} }
/** /**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned * Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into * from the specified file. Bytes from the file are converted into
* characters using the specified charset. * characters using the specified charset.
......
...@@ -766,19 +766,21 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E> ...@@ -766,19 +766,21 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
} }
/** /**
* Unlike other traversal methods, iterators need to handle: * Returns the next live successor of p, or null if no such.
*
* Unlike other traversal methods, iterators need to handle both:
* - dequeued nodes (p.next == p) * - dequeued nodes (p.next == p)
* - interior removed nodes (p.item == null) * - (possibly multiple) interior removed nodes (p.item == null)
*/ */
private Node<E> nextNode(Node<E> p) { private Node<E> nextNode(Node<E> p) {
Node<E> s = p.next; for (;;) {
if (p == s) Node<E> s = p.next;
return head.next; if (s == p)
// Skip over removed nodes. return head.next;
// May be necessary if multiple interior Nodes are removed. if (s == null || s.item != null)
while (s != null && s.item == null) return s;
s = s.next; p = s;
return s; }
} }
public E next() { public E next() {
......
/*
* 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; ...@@ -32,8 +32,8 @@ import java.io.IOException;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.AccessController; import java.security.AccessController;
import java.security.AccessControlContext; import java.security.AccessControlContext;
...@@ -65,11 +65,8 @@ abstract class AsynchronousChannelGroupImpl ...@@ -65,11 +65,8 @@ abstract class AsynchronousChannelGroupImpl
private final Queue<Runnable> taskQueue; private final Queue<Runnable> taskQueue;
// group shutdown // group shutdown
// shutdownLock is RW lock so as to allow for concurrent queuing of tasks private final AtomicBoolean shutdown = new AtomicBoolean();
// when using a fixed thread pool.
private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
private final Object shutdownNowLock = new Object(); private final Object shutdownNowLock = new Object();
private volatile boolean shutdown;
private volatile boolean terminateInitiated; private volatile boolean terminateInitiated;
AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider, AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
...@@ -214,7 +211,7 @@ abstract class AsynchronousChannelGroupImpl ...@@ -214,7 +211,7 @@ abstract class AsynchronousChannelGroupImpl
@Override @Override
public final boolean isShutdown() { public final boolean isShutdown() {
return shutdown; return shutdown.get();
} }
@Override @Override
...@@ -260,17 +257,10 @@ abstract class AsynchronousChannelGroupImpl ...@@ -260,17 +257,10 @@ abstract class AsynchronousChannelGroupImpl
@Override @Override
public final void shutdown() { public final void shutdown() {
shutdownLock.writeLock().lock(); if (shutdown.getAndSet(true)) {
try { // already shutdown
if (shutdown) { return;
// already shutdown
return;
}
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
} }
// if there are channels in the group then shutdown will continue // if there are channels in the group then shutdown will continue
// when the last channel is closed // when the last channel is closed
if (!isEmpty()) { if (!isEmpty()) {
...@@ -289,12 +279,7 @@ abstract class AsynchronousChannelGroupImpl ...@@ -289,12 +279,7 @@ abstract class AsynchronousChannelGroupImpl
@Override @Override
public final void shutdownNow() throws IOException { public final void shutdownNow() throws IOException {
shutdownLock.writeLock().lock(); shutdown.set(true);
try {
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
}
synchronized (shutdownNowLock) { synchronized (shutdownNowLock) {
if (!terminateInitiated) { if (!terminateInitiated) {
terminateInitiated = true; terminateInitiated = true;
...@@ -305,6 +290,18 @@ abstract class AsynchronousChannelGroupImpl ...@@ -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 @Override
public final boolean awaitTermination(long timeout, TimeUnit unit) public final boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException throws InterruptedException
......
...@@ -25,8 +25,10 @@ ...@@ -25,8 +25,10 @@
package sun.nio.ch; package sun.nio.ch;
import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
...@@ -101,6 +103,33 @@ abstract class AsynchronousFileChannelImpl ...@@ -101,6 +103,33 @@ abstract class AsynchronousFileChannelImpl
// -- file locking -- // -- 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; private volatile FileLockTable fileLockTable;
final void ensureFileLockTableInitialized() throws IOException { final void ensureFileLockTableInitialized() throws IOException {
...@@ -175,4 +204,50 @@ abstract class AsynchronousFileChannelImpl ...@@ -175,4 +204,50 @@ abstract class AsynchronousFileChannelImpl
end(); 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; ...@@ -35,6 +35,7 @@ import java.io.IOException;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.net.NetHooks; import sun.net.NetHooks;
...@@ -108,6 +109,29 @@ abstract class AsynchronousServerSocketChannelImpl ...@@ -108,6 +109,29 @@ abstract class AsynchronousServerSocketChannelImpl
implClose(); 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() { final boolean isAcceptKilled() {
return acceptKilled; return acceptKilled;
} }
......
...@@ -183,29 +183,54 @@ abstract class AsynchronousSocketChannelImpl ...@@ -183,29 +183,54 @@ abstract class AsynchronousSocketChannelImpl
killWriting(); 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. * Invoked by read to initiate the I/O operation.
*/ */
abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts, abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
boolean isScatteringRead, ByteBuffer dst,
ByteBuffer[] dsts,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<V,? super A> handler); CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> read(ByteBuffer[] dsts, private <V extends Number,A> Future<V> read(boolean isScatteringRead,
boolean isScatteringRead, ByteBuffer dst,
ByteBuffer[] dsts,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A att,
CompletionHandler<V,? super A> handler) CompletionHandler<V,? super A> handler)
{ {
if (!isOpen()) { if (!isOpen()) {
CompletedFuture<V,A> result = CompletedFuture Throwable e = new ClosedChannelException();
.withFailure(this, new ClosedChannelException(), attachment); if (handler == null)
Invoker.invoke(handler, result); return CompletedFuture.withFailure(e);
return result; Invoker.invoke(this, handler, att, null, e);
return null;
} }
if (remoteAddress == null) if (remoteAddress == null)
...@@ -213,13 +238,13 @@ abstract class AsynchronousSocketChannelImpl ...@@ -213,13 +238,13 @@ abstract class AsynchronousSocketChannelImpl
if (timeout < 0L) if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout"); throw new IllegalArgumentException("Negative timeout");
boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining(); boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
boolean shutdown = false; boolean shutdown = false;
// check and update state // check and update state
synchronized (readLock) { synchronized (readLock) {
if (readKilled) 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) if (reading)
throw new ReadPendingException(); throw new ReadPendingException();
if (readShutdown) { if (readShutdown) {
...@@ -234,44 +259,53 @@ abstract class AsynchronousSocketChannelImpl ...@@ -234,44 +259,53 @@ abstract class AsynchronousSocketChannelImpl
// immediately complete with -1 if shutdown for read // immediately complete with -1 if shutdown for read
// immediately complete with 0 if no space remaining // immediately complete with 0 if no space remaining
if (shutdown || !hasSpaceToRead) { if (shutdown || !hasSpaceToRead) {
CompletedFuture<V,A> result; Number result;
if (isScatteringRead) { if (isScatteringRead) {
Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L); result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
} else { } else {
int value = (shutdown) ? -1 : 0; result = (shutdown) ? -1 : 0;
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
} }
Invoker.invoke(handler, result); if (handler == null)
return result; 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 @Override
public final <A> Future<Integer> read(ByteBuffer dst, public final Future<Integer> read(ByteBuffer dst) {
long timeout, if (dst.isReadOnly())
TimeUnit unit, throw new IllegalArgumentException("Read-only buffer");
A attachment, return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
CompletionHandler<Integer,? super A> handler) }
@Override
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()) if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer"); throw new IllegalArgumentException("Read-only buffer");
ByteBuffer[] bufs = new ByteBuffer[1]; read(false, dst, null, timeout, unit, attachment, handler);
bufs[0] = dst;
return read(bufs, false, timeout, unit, attachment, handler);
} }
@Override @Override
public final <A> Future<Long> read(ByteBuffer[] dsts, public final <A> void read(ByteBuffer[] dsts,
int offset, int offset,
int length, int length,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Long,? super A> handler) CompletionHandler<Long,? super A> handler)
{ {
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
ByteBuffer[] bufs = Util.subsequence(dsts, offset, length); ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
...@@ -279,39 +313,41 @@ abstract class AsynchronousSocketChannelImpl ...@@ -279,39 +313,41 @@ abstract class AsynchronousSocketChannelImpl
if (bufs[i].isReadOnly()) if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer"); 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. * Invoked by write to initiate the I/O operation.
*/ */
abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs, abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
boolean isGatheringWrite, ByteBuffer src,
ByteBuffer[] srcs,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<V,? super A> handler); CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> write(ByteBuffer[] srcs, private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
boolean isGatheringWrite, ByteBuffer src,
ByteBuffer[] srcs,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A att,
CompletionHandler<V,? super A> handler) CompletionHandler<V,? super A> handler)
{ {
boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining(); boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
boolean closed = false; boolean closed = false;
if (isOpen()) { if (isOpen()) {
if (remoteAddress == null) if (remoteAddress == null)
throw new NotYetConnectedException(); throw new NotYetConnectedException();
if (timeout < 0L) if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout"); throw new IllegalArgumentException("Negative timeout");
// check and update state // check and update state
synchronized (writeLock) { synchronized (writeLock) {
if (writeKilled) 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) if (writing)
throw new WritePendingException(); throw new WritePendingException();
if (writeShutdown) { if (writeShutdown) {
...@@ -327,52 +363,57 @@ abstract class AsynchronousSocketChannelImpl ...@@ -327,52 +363,57 @@ abstract class AsynchronousSocketChannelImpl
// channel is closed or shutdown for write // channel is closed or shutdown for write
if (closed) { if (closed) {
CompletedFuture<V,A> result = CompletedFuture Throwable e = new ClosedChannelException();
.withFailure(this, new ClosedChannelException(), attachment); if (handler == null)
Invoker.invoke(handler, result); return CompletedFuture.withFailure(e);
return result; Invoker.invoke(this, handler, att, null, e);
return null;
} }
// nothing to write so complete immediately // nothing to write so complete immediately
if (!hasDataToWrite) { if (!hasDataToWrite) {
CompletedFuture<V,A> result; Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
if (isGatheringWrite) { if (handler == null)
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment); return CompletedFuture.withResult((V)result);
} else { Invoker.invoke(this, handler, att, (V)result, null);
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment); return null;
}
Invoker.invoke(handler, result);
return result;
} }
return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler); return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
} }
@Override @Override
public final <A> Future<Integer> write(ByteBuffer src, public final Future<Integer> write(ByteBuffer src) {
long timeout, return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
TimeUnit unit, }
A attachment,
CompletionHandler<Integer,? super A> handler) @Override
public final <A> void write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{ {
ByteBuffer[] bufs = new ByteBuffer[1]; if (handler == null)
bufs[0] = src; throw new NullPointerException("'handler' is null");
return write(bufs, false, timeout, unit, attachment, handler); write(false, src, null, timeout, unit, attachment, handler);
} }
@Override @Override
public final <A> Future<Long> write(ByteBuffer[] srcs, public final <A> void write(ByteBuffer[] srcs,
int offset, int offset,
int length, int length,
long timeout, long timeout,
TimeUnit unit, TimeUnit unit,
A attachment, A attachment,
CompletionHandler<Long,? super A> handler) CompletionHandler<Long,? super A> handler)
{ {
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
srcs = Util.subsequence(srcs, offset, length); srcs = Util.subsequence(srcs, offset, length);
return write(srcs, true, timeout, unit, attachment, handler); write(true, null, srcs, timeout, unit, attachment, handler);
} }
@Override @Override
...@@ -461,7 +502,6 @@ abstract class AsynchronousSocketChannelImpl ...@@ -461,7 +502,6 @@ abstract class AsynchronousSocketChannelImpl
} }
@Override @Override
@SuppressWarnings("unchecked")
public final SocketAddress getRemoteAddress() throws IOException { public final SocketAddress getRemoteAddress() throws IOException {
if (!isOpen()) if (!isOpen())
throw new ClosedChannelException(); throw new ClosedChannelException();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
package sun.nio.ch; package sun.nio.ch;
import java.nio.channels.AsynchronousChannel; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.io.IOException; import java.io.IOException;
...@@ -35,39 +35,35 @@ import java.io.IOException; ...@@ -35,39 +35,35 @@ import java.io.IOException;
* completed. * completed.
*/ */
final class CompletedFuture<V,A> final class CompletedFuture<V> implements Future<V> {
extends AbstractFuture<V,A>
{
private final V result; private final V result;
private final Throwable exc; private final Throwable exc;
private CompletedFuture(AsynchronousChannel channel, private CompletedFuture(V result, Throwable exc) {
V result,
Throwable exc,
A attachment)
{
super(channel, attachment);
this.result = result; this.result = result;
this.exc = exc; this.exc = exc;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel, static <V> CompletedFuture<V> withResult(V result) {
V result, return new CompletedFuture<V>(result, null);
A attachment)
{
return new CompletedFuture<V,A>(channel, result, null, attachment);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel, static <V> CompletedFuture<V> withFailure(Throwable exc) {
Throwable exc,
A attachment)
{
// exception must be IOException or SecurityException // exception must be IOException or SecurityException
if (!(exc instanceof IOException) && !(exc instanceof SecurityException)) if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
exc = new IOException(exc); 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 @Override
...@@ -100,14 +96,4 @@ final class CompletedFuture<V,A> ...@@ -100,14 +96,4 @@ final class CompletedFuture<V,A>
public boolean cancel(boolean mayInterruptIfRunning) { public boolean cancel(boolean mayInterruptIfRunning) {
return false; return false;
} }
@Override
Throwable exception() {
return exc;
}
@Override
V value() {
return result;
}
} }
...@@ -117,33 +117,32 @@ class Invoker { ...@@ -117,33 +117,32 @@ class Invoker {
* Invoke handler without checking the thread identity or number of handlers * Invoke handler without checking the thread identity or number of handlers
* on the thread stack. * on the thread stack.
*/ */
@SuppressWarnings("unchecked")
static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler, 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()) { if (exc == null) {
Throwable exc = result.exception(); handler.completed(value, attachment);
if (exc == null) { } else {
handler.completed(result.value(), result.attachment()); handler.failed(exc, attachment);
} else {
handler.failed(exc, result.attachment());
}
// clear interrupt
Thread.interrupted();
} }
}
// clear interrupt
Thread.interrupted();
}
/** /**
* Invoke handler after incrementing the invoke count. * Invoke handler assuming thread identity already checked
*/ */
static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount, static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
CompletionHandler<V,? super A> handler, CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result) A attachment,
V result,
Throwable exc)
{ {
myGroupAndInvokeCount.incrementInvokeCount(); myGroupAndInvokeCount.incrementInvokeCount();
invokeUnchecked(handler, result); Invoker.invokeUnchecked(handler, attachment, result, exc);
} }
/** /**
...@@ -151,64 +150,64 @@ class Invoker { ...@@ -151,64 +150,64 @@ class Invoker {
* thread pool then the handler is invoked directly, otherwise it is * thread pool then the handler is invoked directly, otherwise it is
* invoked indirectly. * invoked indirectly.
*/ */
static <V,A> void invoke(CompletionHandler<V,? super A> handler, static <V,A> void invoke(AsynchronousChannel channel,
AbstractFuture<V,A> result) CompletionHandler<V,? super A> handler,
A attachment,
V result,
Throwable exc)
{ {
if (handler != null) { boolean invokeDirect = false;
boolean invokeDirect = false; boolean identityOkay = false;
boolean identityOkay = false; GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get(); if (thisGroupAndInvokeCount != null) {
if (thisGroupAndInvokeCount != null) { if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
AsynchronousChannel channel = result.channel(); identityOkay = true;
if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group())) if (identityOkay &&
identityOkay = true; (thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
if (identityOkay && {
(thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount)) // group match
{ invokeDirect = true;
// group match
invokeDirect = true;
}
} }
if (invokeDirect) { }
thisGroupAndInvokeCount.incrementInvokeCount(); if (invokeDirect) {
invokeUnchecked(handler, result); invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
} else { } else {
try { try {
invokeIndirectly(handler, result); invokeIndirectly(channel, handler, attachment, result, exc);
} catch (RejectedExecutionException ree) { } catch (RejectedExecutionException ree) {
// channel group shutdown; fallback to invoking directly // channel group shutdown; fallback to invoking directly
// if the current thread has the right identity. // if the current thread has the right identity.
if (identityOkay) { if (identityOkay) {
invokeUnchecked(handler, result); invokeDirect(thisGroupAndInvokeCount,
} else { handler, attachment, result, exc);
throw new ShutdownChannelGroupException(); } 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, static <V,A> void invokeIndirectly(AsynchronousChannel channel,
final AbstractFuture<V,A> result) final CompletionHandler<V,? super A> handler,
final A attachment,
final V result,
final Throwable exc)
{ {
if (handler != null) { try {
AsynchronousChannel channel = result.channel(); ((Groupable)channel).group().executeOnPooledThread(new Runnable() {
try { public void run() {
((Groupable)channel).group().executeOnPooledThread(new Runnable() { GroupAndInvokeCount thisGroupAndInvokeCount =
public void run() { myGroupAndInvokeCount.get();
GroupAndInvokeCount thisGroupAndInvokeCount = if (thisGroupAndInvokeCount != null)
myGroupAndInvokeCount.get(); thisGroupAndInvokeCount.setInvokeCount(1);
if (thisGroupAndInvokeCount != null) invokeUnchecked(handler, attachment, result, exc);
thisGroupAndInvokeCount.setInvokeCount(1); }
invokeUnchecked(handler, result); });
} } catch (RejectedExecutionException ree) {
}); throw new ShutdownChannelGroupException();
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
} }
} }
...@@ -216,19 +215,19 @@ class Invoker { ...@@ -216,19 +215,19 @@ class Invoker {
* Invokes the handler "indirectly" in the given Executor * Invokes the handler "indirectly" in the given Executor
*/ */
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler, 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) Executor executor)
{ {
if (handler != null) { try {
try { executor.execute(new Runnable() {
executor.execute(new Runnable() { public void run() {
public void run() { invokeUnchecked(handler, attachment, value, exc);
invokeUnchecked(handler, result); }
} });
}); } catch (RejectedExecutionException ree) {
} catch (RejectedExecutionException ree) { throw new ShutdownChannelGroupException();
throw new ShutdownChannelGroupException();
}
} }
} }
...@@ -258,4 +257,52 @@ class Invoker { ...@@ -258,4 +257,52 @@ class Invoker {
throw new ShutdownChannelGroupException(); 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; ...@@ -34,13 +34,13 @@ import java.io.IOException;
* attachment of an additional arbitrary context object and a timer task. * attachment of an additional arbitrary context object and a timer task.
*/ */
final class PendingFuture<V,A> final class PendingFuture<V,A> implements Future<V> {
extends AbstractFuture<V,A>
{
private static final CancellationException CANCELLED = private static final CancellationException CANCELLED =
new CancellationException(); new CancellationException();
private final AsynchronousChannel channel;
private final CompletionHandler<V,? super A> handler; private final CompletionHandler<V,? super A> handler;
private final A attachment;
// true if result (or exception) is available // true if result (or exception) is available
private volatile boolean haveResult; private volatile boolean haveResult;
...@@ -56,14 +56,14 @@ final class PendingFuture<V,A> ...@@ -56,14 +56,14 @@ final class PendingFuture<V,A>
// optional context object // optional context object
private volatile Object context; private volatile Object context;
PendingFuture(AsynchronousChannel channel, PendingFuture(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler, CompletionHandler<V,? super A> handler,
A attachment, A attachment,
Object context) Object context)
{ {
super(channel, attachment); this.channel = channel;
this.handler = handler; this.handler = handler;
this.attachment = attachment;
this.context = context; this.context = context;
} }
...@@ -71,14 +71,31 @@ final class PendingFuture<V,A> ...@@ -71,14 +71,31 @@ final class PendingFuture<V,A>
CompletionHandler<V,? super A> handler, CompletionHandler<V,? super A> handler,
A attachment) A attachment)
{ {
super(channel, attachment); this.channel = channel;
this.handler = handler; 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() { CompletionHandler<V,? super A> handler() {
return handler; return handler;
} }
A attachment() {
return attachment;
}
void setContext(Object context) { void setContext(Object context) {
this.context = context; this.context = context;
} }
...@@ -113,36 +130,45 @@ final class PendingFuture<V,A> ...@@ -113,36 +130,45 @@ final class PendingFuture<V,A>
/** /**
* Sets the result, or a no-op if the result or exception is already set. * 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) { synchronized (this) {
if (haveResult) if (haveResult)
return false; return;
result = res; result = res;
haveResult = true; haveResult = true;
if (timeoutTask != null) if (timeoutTask != null)
timeoutTask.cancel(false); timeoutTask.cancel(false);
if (latch != null) if (latch != null)
latch.countDown(); latch.countDown();
return true;
} }
} }
/** /**
* Sets the result, or a no-op if the result or exception is already set. * 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)) if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x); x = new IOException(x);
synchronized (this) { synchronized (this) {
if (haveResult) if (haveResult)
return false; return;
exc = x; exc = x;
haveResult = true; haveResult = true;
if (timeoutTask != null) if (timeoutTask != null)
timeoutTask.cancel(false); timeoutTask.cancel(false);
if (latch != null) if (latch != null)
latch.countDown(); 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> ...@@ -178,12 +204,10 @@ final class PendingFuture<V,A>
return result; return result;
} }
@Override
Throwable exception() { Throwable exception() {
return (exc != CANCELLED) ? exc : null; return (exc != CANCELLED) ? exc : null;
} }
@Override
V value() { V value() {
return result; return result;
} }
...@@ -204,33 +228,6 @@ final class PendingFuture<V,A> ...@@ -204,33 +228,6 @@ final class PendingFuture<V,A>
if (haveResult) if (haveResult)
return false; // already completed 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 // notify channel
if (channel() instanceof Cancellable) if (channel() instanceof Cancellable)
((Cancellable)channel()).onCancel(this); ((Cancellable)channel()).onCancel(this);
...@@ -249,7 +246,7 @@ final class PendingFuture<V,A> ...@@ -249,7 +246,7 @@ final class PendingFuture<V,A>
} catch (IOException ignore) { } } catch (IOException ignore) { }
} }
// release waiters (this also releases the invoker) // release waiters
if (latch != null) if (latch != null)
latch.countDown(); latch.countDown();
return true; return true;
......
...@@ -317,51 +317,71 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -317,51 +317,71 @@ class SimpleAsynchronousDatagramChannelImpl
return new WrappedMembershipKey(this, key); return new WrappedMembershipKey(this, key);
} }
@Override private <A> Future<Integer> implSend(ByteBuffer src,
public <A> Future<Integer> send(ByteBuffer src, SocketAddress target,
SocketAddress target, A attachment,
long timeout, CompletionHandler<Integer,? super A> handler)
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{ {
if (timeout < 0L) int n = 0;
throw new IllegalArgumentException("Negative timeout"); Throwable exc = null;
if (unit == null)
throw new NullPointerException();
CompletedFuture<Integer,A> result;
try { try {
int n = dc.send(src, target); n = dc.send(src, target);
result = CompletedFuture.withResult(this, n, attachment);
} catch (IOException ioe) { } catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment); exc = ioe;
} }
Invoker.invoke(handler, result); if (handler == null)
return result; return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> send(ByteBuffer src, SocketAddress target) {
return implSend(src, target, null, null);
} }
@Override @Override
public <A> Future<Integer> write(ByteBuffer src, public <A> void send(ByteBuffer src,
long timeout, SocketAddress target,
TimeUnit unit, A attachment,
A attachment, CompletionHandler<Integer,? super A> handler)
CompletionHandler<Integer,? super A> handler)
{ {
if (timeout < 0L) if (handler == null)
throw new IllegalArgumentException("Negative timeout"); throw new NullPointerException("'handler' is null");
if (unit == null) implSend(src, target, attachment, handler);
throw new NullPointerException(); }
CompletedFuture<Integer,A> result; private <A> Future<Integer> implWrite(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
int n = 0;
Throwable exc = null;
try { try {
int n = dc.write(src); n = dc.write(src);
result = CompletedFuture.withResult(this, n, attachment);
} catch (IOException ioe) { } catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment); exc = ioe;
} }
Invoker.invoke(handler, result); if (handler == null)
return result; 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 ...@@ -390,12 +410,11 @@ class SimpleAsynchronousDatagramChannelImpl
} }
} }
@Override private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
public <A> Future<SocketAddress> receive(final ByteBuffer dst, final long timeout,
final long timeout, final TimeUnit unit,
final TimeUnit unit, A attachment,
A attachment, final CompletionHandler<SocketAddress,? super A> handler)
final CompletionHandler<SocketAddress,? super A> handler)
{ {
if (dst.isReadOnly()) if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer"); throw new IllegalArgumentException("Read-only buffer");
...@@ -406,10 +425,11 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -406,10 +425,11 @@ class SimpleAsynchronousDatagramChannelImpl
// complete immediately if channel closed // complete immediately if channel closed
if (!isOpen()) { if (!isOpen()) {
CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this, Throwable exc = new ClosedChannelException();
new ClosedChannelException(), attachment); if (handler == null)
Invoker.invoke(handler, result); return CompletedFuture.withFailure(exc);
return result; Invoker.invoke(this, handler, attachment, null, exc);
return null;
} }
final AccessControlContext acc = (System.getSecurityManager() == null) ? final AccessControlContext acc = (System.getSecurityManager() == null) ?
...@@ -471,7 +491,7 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -471,7 +491,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException(); x = new AsynchronousCloseException();
result.setFailure(x); result.setFailure(x);
} }
Invoker.invokeUnchecked(handler, result); Invoker.invokeUnchecked(result);
} }
}; };
try { try {
...@@ -483,11 +503,27 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -483,11 +503,27 @@ class SimpleAsynchronousDatagramChannelImpl
} }
@Override @Override
public <A> Future<Integer> read(final ByteBuffer dst, public Future<SocketAddress> receive(ByteBuffer dst) {
final long timeout, return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
final TimeUnit unit, }
A attachment,
final CompletionHandler<Integer,? super A> handler) @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()) if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer"); throw new IllegalArgumentException("Read-only buffer");
...@@ -495,18 +531,20 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -495,18 +531,20 @@ class SimpleAsynchronousDatagramChannelImpl
throw new IllegalArgumentException("Negative timeout"); throw new IllegalArgumentException("Negative timeout");
if (unit == null) if (unit == null)
throw new NullPointerException(); throw new NullPointerException();
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
// complete immediately if channel closed // complete immediately if channel closed
if (!isOpen()) { if (!isOpen()) {
CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this, Throwable exc = new ClosedChannelException();
new ClosedChannelException(), attachment); if (handler == null)
Invoker.invoke(handler, result); return CompletedFuture.withFailure(exc);
return result; 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 = final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment); new PendingFuture<Integer,A>(this, handler, attachment);
Runnable task = new Runnable() { Runnable task = new Runnable() {
...@@ -563,7 +601,7 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -563,7 +601,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException(); x = new AsynchronousCloseException();
result.setFailure(x); result.setFailure(x);
} }
Invoker.invokeUnchecked(handler, result); Invoker.invokeUnchecked(result);
} }
}; };
try { try {
...@@ -574,6 +612,23 @@ class SimpleAsynchronousDatagramChannelImpl ...@@ -574,6 +612,23 @@ class SimpleAsynchronousDatagramChannelImpl
return result; 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 @Override
public AsynchronousDatagramChannel bind(SocketAddress local) public AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException throws IOException
......
...@@ -50,9 +50,6 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -50,9 +50,6 @@ public class SimpleAsynchronousFileChannelImpl
// Used to make native read and write calls // Used to make native read and write calls
private static final FileDispatcher nd = new FileDispatcherImpl(); 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 // Thread-safe set of IDs of native threads, for signalling
private final NativeThreadSet threads = new NativeThreadSet(2); private final NativeThreadSet threads = new NativeThreadSet(2);
...@@ -60,11 +57,9 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -60,11 +57,9 @@ public class SimpleAsynchronousFileChannelImpl
SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj, SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
boolean reading, boolean reading,
boolean writing, boolean writing,
ExecutorService executor, ExecutorService executor)
boolean isDefaultexecutor)
{ {
super(fdObj, reading, writing, executor); super(fdObj, reading, writing, executor);
this.isDefaultExecutor = isDefaultexecutor;
} }
public static AsynchronousFileChannel open(FileDescriptor fdo, public static AsynchronousFileChannel open(FileDescriptor fdo,
...@@ -73,17 +68,9 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -73,17 +68,9 @@ public class SimpleAsynchronousFileChannelImpl
ThreadPool pool) ThreadPool pool)
{ {
// Executor is either default or based on pool parameters // Executor is either default or based on pool parameters
ExecutorService executor; ExecutorService executor = (pool == null) ?
boolean isDefaultexecutor; DefaultExecutorHolder.defaultExecutor : pool.executor();
if (pool == null) { return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
executor = DefaultExecutorHolder.defaultExecutor;
isDefaultexecutor = true;
} else {
executor = pool.executor();
isDefaultexecutor = false;
}
return new SimpleAsynchronousFileChannelImpl(fdo,
reading, writing, executor, isDefaultexecutor);
} }
@Override @Override
...@@ -114,16 +101,6 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -114,16 +101,6 @@ public class SimpleAsynchronousFileChannelImpl
// close file // close file
nd.close(fdObj); 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 @Override
...@@ -194,11 +171,11 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -194,11 +171,11 @@ public class SimpleAsynchronousFileChannelImpl
} }
@Override @Override
public <A> Future<FileLock> lock(final long position, <A> Future<FileLock> implLock(final long position,
final long size, final long size,
final boolean shared, final boolean shared,
A attachment, final A attachment,
final CompletionHandler<FileLock,? super A> handler) final CompletionHandler<FileLock,? super A> handler)
{ {
if (shared && !reading) if (shared && !reading)
throw new NonReadableChannelException(); throw new NonReadableChannelException();
...@@ -208,16 +185,19 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -208,16 +185,19 @@ public class SimpleAsynchronousFileChannelImpl
// add to lock table // add to lock table
final FileLockImpl fli = addToFileLockTable(position, size, shared); final FileLockImpl fli = addToFileLockTable(position, size, shared);
if (fli == null) { if (fli == null) {
CompletedFuture<FileLock,A> result = CompletedFuture Throwable exc = new ClosedChannelException();
.withFailure(this, new ClosedChannelException(), attachment); if (handler == null)
Invoker.invokeIndirectly(handler, result, executor); return CompletedFuture.withFailure(exc);
return result; Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
return null;
} }
final PendingFuture<FileLock,A> result = final PendingFuture<FileLock,A> result = (handler == null) ?
new PendingFuture<FileLock,A>(this, handler, attachment); new PendingFuture<FileLock,A>(this) : null;
Runnable task = new Runnable() { Runnable task = new Runnable() {
public void run() { public void run() {
Throwable exc = null;
int ti = threads.add(); int ti = threads.add();
try { try {
int n; int n;
...@@ -226,31 +206,36 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -226,31 +206,36 @@ public class SimpleAsynchronousFileChannelImpl
do { do {
n = nd.lock(fdObj, true, position, size, shared); n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen()); } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n == FileDispatcher.LOCKED && isOpen()) { if (n != FileDispatcher.LOCKED || !isOpen()) {
result.setResult(fli);
} else {
throw new AsynchronousCloseException(); throw new AsynchronousCloseException();
} }
} catch (IOException x) { } catch (IOException x) {
removeFromFileLockTable(fli); removeFromFileLockTable(fli);
if (!isOpen()) if (!isOpen())
x = new AsynchronousCloseException(); x = new AsynchronousCloseException();
result.setFailure(x); exc = x;
} finally { } finally {
end(); end();
} }
} finally { } finally {
threads.remove(ti); 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 { try {
executor.execute(task); executor.execute(task);
} catch (RejectedExecutionException ree) { executed = true;
// rollback } finally {
removeFromFileLockTable(fli); if (!executed) {
throw new ShutdownChannelGroupException(); // rollback
removeFromFileLockTable(fli);
}
} }
return result; return result;
} }
...@@ -301,10 +286,10 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -301,10 +286,10 @@ public class SimpleAsynchronousFileChannelImpl
} }
@Override @Override
public <A> Future<Integer> read(final ByteBuffer dst, <A> Future<Integer> implRead(final ByteBuffer dst,
final long position, final long position,
A attachment, final A attachment,
final CompletionHandler<Integer,? super A> handler) final CompletionHandler<Integer,? super A> handler)
{ {
if (position < 0) if (position < 0)
throw new IllegalArgumentException("Negative position"); throw new IllegalArgumentException("Negative position");
...@@ -315,55 +300,52 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -315,55 +300,52 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel closed or no space remaining // complete immediately if channel closed or no space remaining
if (!isOpen() || (dst.remaining() == 0)) { if (!isOpen() || (dst.remaining() == 0)) {
CompletedFuture<Integer,A> result; Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (isOpen()) { if (handler == null)
result = CompletedFuture.withResult(this, 0, attachment); return CompletedFuture.withResult(0, exc);
} else { Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
result = CompletedFuture.withFailure(this, return null;
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
} }
final PendingFuture<Integer,A> result = final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this, handler, attachment); new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() { Runnable task = new Runnable() {
public void run() { public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add(); int ti = threads.add();
try { try {
begin(); begin();
int n;
do { do {
n = IOUtil.read(fdObj, dst, position, nd, null); n = IOUtil.read(fdObj, dst, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen()) if (n < 0 && !isOpen())
throw new AsynchronousCloseException(); throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) { } catch (IOException x) {
if (!isOpen()) if (!isOpen())
x = new AsynchronousCloseException(); x = new AsynchronousCloseException();
result.setFailure(x); exc = x;
} finally { } finally {
end(); end();
threads.remove(ti); 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);
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result; return result;
} }
@Override @Override
public <A> Future<Integer> write(final ByteBuffer src, <A> Future<Integer> implWrite(final ByteBuffer src,
final long position, final long position,
A attachment, final A attachment,
final CompletionHandler<Integer,? super A> handler) final CompletionHandler<Integer,? super A> handler)
{ {
if (position < 0) if (position < 0)
throw new IllegalArgumentException("Negative position"); throw new IllegalArgumentException("Negative position");
...@@ -372,47 +354,44 @@ public class SimpleAsynchronousFileChannelImpl ...@@ -372,47 +354,44 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel is closed or no bytes remaining // complete immediately if channel is closed or no bytes remaining
if (!isOpen() || (src.remaining() == 0)) { if (!isOpen() || (src.remaining() == 0)) {
CompletedFuture<Integer,A> result; Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (isOpen()) { if (handler == null)
result = CompletedFuture.withResult(this, 0, attachment); return CompletedFuture.withResult(0, exc);
} else { Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
result = CompletedFuture.withFailure(this, return null;
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
} }
final PendingFuture<Integer,A> result = final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this, handler, attachment); new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() { Runnable task = new Runnable() {
public void run() { public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add(); int ti = threads.add();
try { try {
begin(); begin();
int n;
do { do {
n = IOUtil.write(fdObj, src, position, nd, null); n = IOUtil.write(fdObj, src, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen()) if (n < 0 && !isOpen())
throw new AsynchronousCloseException(); throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) { } catch (IOException x) {
if (!isOpen()) if (!isOpen())
x = new AsynchronousCloseException(); x = new AsynchronousCloseException();
result.setFailure(x); exc = x;
} finally { } finally {
end(); end();
threads.remove(ti); 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);
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result; return result;
} }
} }
...@@ -41,6 +41,7 @@ import java.io.IOException; ...@@ -41,6 +41,7 @@ import java.io.IOException;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.File; import java.io.File;
import java.util.Comparator;
import java.util.StringTokenizer; import java.util.StringTokenizer;
/** /**
...@@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants { ...@@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants {
/** /**
* Reads the service key from the keytab file. * Reads the service key from the keytab file.
* @param service the PrincipalName of the requested service. * @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) { public EncryptionKey readServiceKey(PrincipalName service) {
KeyTabEntry entry = null; KeyTabEntry entry = null;
EncryptionKey key = null;
if (entries != null) { if (entries != null) {
// Find latest entry for this service that has an etype // Find latest entry for this service that has an etype
// that has been configured for use // that has been configured for use
...@@ -240,9 +242,12 @@ public class KeyTab implements KeyTabConstants { ...@@ -240,9 +242,12 @@ public class KeyTab implements KeyTabConstants {
entry = entries.elementAt(i); entry = entries.elementAt(i);
if (entry.service.match(service)) { if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) { if (EType.isSupported(entry.keyType)) {
return new EncryptionKey(entry.keyblock, if (key == null ||
entry.keyVersion > key.getKeyVersionNumber()) {
key = new EncryptionKey(entry.keyblock,
entry.keyType, entry.keyType,
new Integer(entry.keyVersion)); new Integer(entry.keyVersion));
}
} else if (DEBUG) { } else if (DEBUG) {
System.out.println("Found unsupported keytype (" + System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service); entry.keyType + ") for " + service);
...@@ -250,12 +255,13 @@ public class KeyTab implements KeyTabConstants { ...@@ -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 * 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 * @param service the PrincipalName of the requested service
* @return an array containing all the service keys * @return an array containing all the service keys
*/ */
...@@ -288,49 +294,39 @@ public class KeyTab implements KeyTabConstants { ...@@ -288,49 +294,39 @@ public class KeyTab implements KeyTabConstants {
size = keys.size(); size = keys.size();
if (size == 0) if (size == 0)
return null; return null;
EncryptionKey[] retVal = new EncryptionKey[size]; EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
// Sort keys according to default_tkt_enctypes // Sort keys according to default_tkt_enctypes
int pos = 0;
EncryptionKey k;
if (DEBUG) { if (DEBUG) {
System.out.println("Ordering keys wrt default_tkt_enctypes list"); System.out.println("Ordering keys wrt default_tkt_enctypes list");
} }
int[] etypes = EType.getDefaults("default_tkt_enctypes");
if (etypes == null || etypes == EType.getBuiltInDefaults()) { final int[] etypes = EType.getDefaults("default_tkt_enctypes");
// Either no supported types specified in default_tkt_enctypes
// or no default_tkt_enctypes entry at all. For both cases, // Sort the keys, k1 is preferred than k2 if:
// just return supported keys in the order retrieved // 1. k1's etype appears earlier in etypes than k2's
for (int i = 0; i < size; i++) { // 2. If same, k1's KVNO is higher
retVal[pos++] = keys.get(i); Arrays.sort(retVal, new Comparator<EncryptionKey>() {
} @Override
} else { public int compare(EncryptionKey o1, EncryptionKey o2) {
for (int j = 0; j < etypes.length && pos < size; j++) { if (etypes != null && etypes != EType.getBuiltInDefaults()) {
int target = etypes[j]; int o1EType = o1.getEType();
for (int i = 0; i < size && pos < size; i++) { int o2EType = o2.getEType();
k = keys.get(i); if (o1EType != o2EType) {
if (k != null && k.getEType() == target) { for (int i=0; i<etypes.length; i++) {
if (DEBUG) { if (etypes[i] == o1EType) {
System.out.println(pos + ": " + k); 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; return retVal;
} }
......
1. Compression algorithm (deflate)
The deflation algorithm used by gzip (also zip and zlib) is a variation of
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
the input data. The second occurrence of a string is replaced by a
pointer to the previous string, in the form of a pair (distance,
length). Distances are limited to 32K bytes, and lengths are limited
to 258 bytes. When a string does not occur anywhere in the previous
32K bytes, it is emitted as a sequence of literal bytes. (In this
description, `string' must be taken as an arbitrary sequence of bytes,
and is not restricted to printable characters.)
Literals or match lengths are compressed with one Huffman tree, and
match distances are compressed with another tree. The trees are stored
in a compact form at the start of each block. The blocks can have any
size (except that the compressed data for one block must fit in
available memory). A block is terminated when deflate() determines that
it would be useful to start another block with fresh trees. (This is
somewhat similar to the behavior of LZW-based _compress_.)
Duplicated strings are found using a hash table. All input strings of
length 3 are inserted in the hash table. A hash index is computed for
the next 3 bytes. If the hash chain for this index is not empty, all
strings in the chain are compared with the current input string, and
the longest match is selected.
The hash chains are searched starting with the most recent strings, to
favor small distances and thus take advantage of the Huffman encoding.
The hash chains are singly linked. There are no deletions from the
hash chains, the algorithm simply discards matches that are too old.
To avoid a worst-case situation, very long hash chains are arbitrarily
truncated at a certain length, determined by a runtime option (level
parameter of deflateInit). So deflate() does not always find the longest
possible match but generally finds a match which is long enough.
deflate() also defers the selection of matches with a lazy evaluation
mechanism. After a match of length N has been found, deflate() searches for
a longer match at the next input byte. If a longer match is found, the
previous match is truncated to a length of one (thus producing a single
literal byte) and the process of lazy evaluation begins again. Otherwise,
the original match is kept, and the next match search is attempted only N
steps later.
The lazy match evaluation is also subject to a runtime parameter. If
the current match is long enough, deflate() reduces the search for a longer
match, thus speeding up the whole process. If compression ratio is more
important than speed, deflate() attempts a complete second search even if
the first match is already long enough.
The lazy match evaluation is not performed for the fastest compression
modes (level parameter 1 to 3). For these fast modes, new strings
are inserted in the hash table only when no match was found, or
when the match is not too long. This degrades the compression ratio
but saves time since there are both fewer insertions and fewer searches.
2. Decompression algorithm (inflate)
2.1 Introduction
The real question is, given a Huffman tree, how to decode fast. The most
important realization is that shorter codes are much more common than
longer codes, so pay attention to decoding the short codes fast, and let
the long codes take longer to decode.
inflate() sets up a first level table that covers some number of bits of
input less than the length of longest code. It gets that many bits from the
stream, and looks it up in the table. The table will tell if the next
code is that many bits or less and how many, and if it is, it will tell
the value, else it will point to the next level table for which inflate()
grabs more bits and tries to decode a longer code.
How many bits to make the first lookup is a tradeoff between the time it
takes to decode and the time it takes to build the table. If building the
table took no time (and if you had infinite memory), then there would only
be a first level table to cover all the way to the longest code. However,
building the table ends up taking a lot longer for more bits since short
codes are replicated many times in such a table. What inflate() does is
simply to make the number of bits in the first table a variable, and set it
for the maximum speed.
inflate() sends new trees relatively often, so it is possibly set for a
smaller first level table than an application that has only one tree for
all the data. For inflate, which has 286 possible codes for the
literal/length tree, the size of the first table is nine bits. Also the
distance trees have 30 possible values, and the size of the first table is
six bits. Note that for each of those cases, the table ended up one bit
longer than the ``average'' code length, i.e. the code length of an
approximately flat code which would be a little more than eight bits for
286 symbols and a little less than five bits for 30 symbols. It would be
interesting to see if optimizing the first level table for other
applications gave values within a bit or two of the flat code size.
2.2 More details on the inflate table lookup
Ok, you want to know what this cleverly obfuscated inflate tree actually
looks like. You are correct that it's not a Huffman tree. It is simply a
lookup table for the first, let's say, nine bits of a Huffman symbol. The
symbol could be as short as one bit or as long as 15 bits. If a particular
symbol is shorter than nine bits, then that symbol's translation is duplicated
in all those entries that start with that symbol's bits. For example, if the
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
symbol is nine bits long, it appears in the table once.
If the symbol is longer than nine bits, then that entry in the table points
to another similar table for the remaining bits. Again, there are duplicated
entries as needed. The idea is that most of the time the symbol will be short
and there will only be one table look up. (That's whole idea behind data
compression in the first place.) For the less frequent long symbols, there
will be two lookups. If you had a compression method with really long
symbols, you could have as many levels of lookups as is efficient. For
inflate, two is enough.
So a table entry either points to another table (in which case nine bits in
the above example are gobbled), or it contains the translation for the symbol
and the number of bits to gobble. Then you start again with the next
ungobbled bit.
You may wonder: why not just have one lookup table for how ever many bits the
longest symbol is? The reason is that if you do that, you end up spending
more time filling in duplicate symbol entries than you do actually decoding.
At least for deflate's output that generates new trees every several 10's of
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
would take too long if you're only decoding several thousand symbols. At the
other extreme, you could make a new table for every bit in the code. In fact,
that's essentially a Huffman tree. But then you spend two much time
traversing the tree while decoding, even for short symbols.
So the number of bits for the first lookup table is a trade of the time to
fill out the table vs. the time spent looking at the second level and above of
the table.
Here is an example, scaled down:
The code being decoded, with 10 symbols, from 1 to 6 bits long:
A: 0
B: 10
C: 1100
D: 11010
E: 11011
F: 11100
G: 11101
H: 11110
I: 111110
J: 111111
Let's make the first table three bits long (eight entries):
000: A,1
001: A,1
010: A,1
011: A,1
100: B,2
101: B,2
110: -> table X (gobble 3 bits)
111: -> table Y (gobble 3 bits)
Each entry is what the bits decode to and how many bits that is, i.e. how
many bits to gobble. Or the entry points to another table, with the number of
bits to gobble implicit in the size of the table.
Table X is two bits long since the longest code starting with 110 is five bits
long:
00: C,1
01: C,1
10: D,2
11: E,2
Table Y is three bits long since the longest code starting with 111 is six
bits long:
000: F,2
001: F,2
010: G,2
011: G,2
100: H,2
101: H,2
110: I,3
111: J,3
So what we have here are three tables with a total of 20 entries that had to
be constructed. That's compared to 64 entries for a single table. Or
compared to 16 entries for a Huffman tree (six two entry tables and one four
entry table). Assuming that the code ideally represents the probability of
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
to one lookup for the single table, or 1.66 lookups per symbol for the
Huffman tree.
There, I think that gives you a picture of what's going on. For inflate, the
meaning of a particular symbol is often more than just a letter. It can be a
byte (a "literal"), or it can be either a length or a distance which
indicates a base value and a number of bits to fetch after the code that is
added to the base value. Or it might be the special end-of-block code. The
data structures created in inftrees.c try to encode all that information
compactly in the tables.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
References:
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
pp. 337-343.
``DEFLATE Compressed Data Format Specification'' available in
ftp://ds.internic.net/rfc/rfc1951.txt
/*
* 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
* infcodes.h -- header to use infcodes.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
struct inflate_codes_state;
typedef struct inflate_codes_state FAR inflate_codes_statef;
extern inflate_codes_statef *inflate_codes_new OF((
uInt, uInt,
inflate_huft *, inflate_huft *,
z_streamp ));
extern int inflate_codes OF((
inflate_blocks_statef *,
z_streamp ,
int));
extern void inflate_codes_free OF((
inflate_codes_statef *,
z_streamp ));
...@@ -22,17 +22,14 @@ ...@@ -22,17 +22,14 @@
* have any questions. * have any questions.
*/ */
/* /* compress.c -- compress a memory buffer
* This file is available under and governed by the GNU General Public * Copyright (C) 1995-2003 Jean-loup Gailly.
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
* compress.c -- compress a memory buffer
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h" #include "zlib.h"
/* =========================================================================== /* ===========================================================================
...@@ -94,3 +91,13 @@ int ZEXPORT compress (dest, destLen, source, sourceLen) ...@@ -94,3 +91,13 @@ int ZEXPORT compress (dest, destLen, source, sourceLen)
{ {
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
} }
/* ===========================================================================
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
uLong ZEXPORT compressBound (sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -149,3 +149,4 @@ local const int base_dist[D_CODES] = { ...@@ -149,3 +149,4 @@ local const int base_dist[D_CODES] = {
32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
}; };
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册