提交 3e4cf7db 编写于 作者: T tbell

Merge

^build/
^dist/
^nbproject/private/
^make/netbeans/.*/nbproject/private/
^make/netbeans/.*/build/
^make/netbeans/.*/dist/
......@@ -160,7 +160,6 @@ FILES_src = \
\
sun/nio/ByteBuffered.java \
\
sun/nio/ch/AbstractFuture.java \
sun/nio/ch/AbstractPollArrayWrapper.java \
sun/nio/ch/AllocatedNativeObject.java \
sun/nio/ch/AsynchronousChannelGroupImpl.java \
......
<?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
......@@ -30,7 +30,7 @@ import java.io.*;
abstract class AbstractNamedNode extends Node {
NameNode nameNode;
NameNode nameNode = null;
String name;
public String name() {
......
......@@ -30,7 +30,7 @@ import java.io.*;
class AltNode extends AbstractGroupNode implements TypeNode {
SelectNode select;
SelectNode select = null;
void constrain(Context ctx) {
super.constrain(ctx);
......
......@@ -33,13 +33,7 @@ class ConstantSetNode extends AbstractNamedNode {
/**
* The mapping between a constant and its value.
*/
protected static Map<String, String> constantMap;
ConstantSetNode(){
if (constantMap == null) {
constantMap = new HashMap<String, String>();
}
}
protected static final Map<String, String> constantMap = new HashMap<String, String>();
void prune() {
List<Node> addons = new ArrayList<Node>();
......@@ -95,9 +89,6 @@ class ConstantSetNode extends AbstractNamedNode {
}
public static String getConstant(String key){
if (constantMap == null) {
return "";
}
String com = constantMap.get(key);
if(com == null){
return "";
......
......@@ -25,13 +25,11 @@
package build.tools.jdwpgen;
import java.util.*;
import java.io.*;
class Main {
static String specSource;
static Map nameMap = new HashMap();
static boolean genDebug = true;
static void usage() {
......@@ -43,7 +41,6 @@ class Main {
System.err.println("-doc <doc_output>");
System.err.println("-jdi <java_output>");
System.err.println("-include <include_file_output>");
System.exit(1);
}
public static void main(String args[]) throws IOException {
......@@ -66,6 +63,7 @@ class Main {
} else {
System.err.println("Invalid option: " + arg);
usage();
return;
}
} else {
specSource = arg;
......@@ -75,6 +73,7 @@ class Main {
if (reader == null) {
System.err.println("<spec_input> must be specified");
usage();
return;
}
Parse parse = new Parse(reader);
......
......@@ -36,7 +36,7 @@ abstract class Node {
int lineno;
List<String> commentList = new ArrayList<String>();
Node parent = null;
Context context;
Context context = null;
static final int maxStructIndent = 5;
static int structIndent = 0; // horrible hack
......@@ -82,7 +82,7 @@ abstract class Node {
}
void indent(PrintWriter writer, int depth) {
for (int i = depth; i > 0; --i) {
for (int i = 0; i < depth; i++) {
writer.print(" ");
}
}
......@@ -195,6 +195,6 @@ abstract class Node {
System.err.println(Main.specSource + ":" + lineno + ": " +
kind + " - " + errmsg);
System.err.println();
System.exit(1);
throw new RuntimeException("Error: " + errmsg);
}
}
......@@ -146,8 +146,12 @@ class Parse {
Node node = (Node)proto.getClass().newInstance();
node.set(kind, list, izer.lineno());
return node;
} catch (Exception exc) {
} catch (InstantiationException exc) {
error(exc.toString());
return null;
} catch (IllegalAccessException exc) {
error(exc.toString());
return null;
}
}
} else {
......@@ -166,6 +170,6 @@ class Parse {
void error(String errmsg) {
System.err.println(Main.specSource + ":" + izer.lineno() +
": " + errmsg);
System.exit(1);
throw new RuntimeException("Error: " + errmsg);
}
}
......@@ -30,7 +30,7 @@ import java.io.*;
class RepeatNode extends AbstractTypeNode {
Node member;
Node member = null;
void constrain(Context ctx) {
super.constrain(ctx);
......
......@@ -30,7 +30,7 @@ import java.io.*;
class SelectNode extends AbstractGroupNode implements TypeNode {
AbstractSimpleTypeNode typeNode;
AbstractSimpleTypeNode typeNode = null;
void prune() {
super.prune();
......
......@@ -129,7 +129,7 @@ public class TextCallbackHandler implements CallbackHandler {
System.err.print(pc.getPrompt());
System.err.flush();
pc.setPassword(Password.readPassword(System.in));
pc.setPassword(Password.readPassword(System.in, pc.isEchoOn()));
} else if (callbacks[i] instanceof ConfirmationCallback) {
confirmation = (ConfirmationCallback) callbacks[i];
......
......@@ -51,7 +51,7 @@ public final class Provider extends java.security.Provider {
" server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
public Provider() {
super("SunSASL", 1.5, info);
super("SunSASL", 1.7d, info);
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
......
......@@ -28,8 +28,12 @@ package java.lang;
/**
* Thrown when an application tries to access an enum constant by name
* and the enum type contains no constant with the specified name.
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class EnumConstantNotPresentException extends RuntimeException {
......
......@@ -2301,6 +2301,54 @@ public final class String
* @spec JSR-51
*/
public String[] split(String regex, int limit) {
/* fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx's meta characters ".$|()[{^?*+\\", or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.
*/
char ch = 0;
if (((regex.count == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<String>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
list.add(substring(off, count));
off = count;
break;
}
}
// If no match was found, return this
if (off == 0)
return new String[] { this };
// Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, count));
// Construct result
int resultSize = list.size();
if (limit == 0)
while (resultSize > 0 && list.get(resultSize-1).length() == 0)
resultSize--;
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
}
......
......@@ -35,8 +35,12 @@ package java.lang;
* <p>Note that this exception may be used when undefined type variables
* are accessed as well as when types (e.g., classes, interfaces or
* annotation types) are loaded.
* In particular, this exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class TypeNotPresentException extends RuntimeException {
......
......@@ -28,8 +28,12 @@ package java.lang.annotation;
/**
* Thrown when the annotation parser attempts to read an annotation
* from a class file and determines that the annotation is malformed.
* This error can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationFormatError extends Error {
......
......@@ -30,8 +30,12 @@ import java.lang.reflect.Method;
* Thrown to indicate that a program has attempted to access an element of
* an annotation whose type has changed after the annotation was compiled
* (or serialized).
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationTypeMismatchException extends RuntimeException {
......
......@@ -30,8 +30,12 @@ package java.lang.annotation;
* an annotation type that was added to the annotation type definition after
* the annotation was compiled (or serialized). This exception will not be
* thrown if the new element has a default value.
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class IncompleteAnnotationException extends RuntimeException {
......
......@@ -50,6 +50,11 @@ import java.lang.annotation.Annotation;
* java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}.
*
* @see java.lang.EnumConstantNotPresentException
* @see java.lang.TypeNotPresentException
* @see java.lang.annotation.AnnotationFormatError
* @see java.lang.annotation.AnnotationTypeMismatchException
* @see java.lang.annotation.IncompleteAnnotationException
* @since 1.5
* @author Josh Bloch
*/
......
......@@ -56,18 +56,18 @@ public interface AsynchronousByteChannel
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> This method initiates an operation to read a sequence of bytes from
* this channel into the given buffer. The method returns a {@link Future}
* representing the pending result of the operation. The result of the
* operation, obtained by invoking the {@code Future} 's {@link
* Future#get() get} method, is the number of bytes read or {@code -1} if
* all bytes have been read and the channel has reached end-of-stream.
*
* <p> This method initiates a read operation to read up to <i>r</i> bytes
* from the channel, where <i>r</i> is the number of bytes remaining in the
* buffer, that is, {@code dst.remaining()} at the time that the read is
* attempted. Where <i>r</i> is 0, the read operation completes immediately
* with a result of {@code 0} without initiating an I/O operation.
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the read
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes read or {@code -1} if no bytes could be
* read because the channel has reached end-of-stream.
*
* <p> The read operation may read up to <i>r</i> bytes from the channel,
* where <i>r</i> is the number of bytes remaining in the buffer, that is,
* {@code dst.remaining()} at the time that the read is attempted. Where
* <i>r</i> is 0, the read operation completes immediately with a result of
* {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is read, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
......@@ -79,44 +79,46 @@ public interface AsynchronousByteChannel
* <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
* should be taken to not to access the buffer until the operaton has completed.
* should be taken to not access the buffer until the operation has
* completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one read to be outstanding at any given time. If a thread
* initiates a read operation before a previous read operation has
* completed then a {@link ReadPendingException} will be thrown.
*
* <p> The <tt>handler</tt> parameter is used to specify a {@link
* CompletionHandler}. When the read operation completes the handler's
* {@link CompletionHandler#completed completed} method is executed.
*
*
* @param dst
* The buffer into which bytes are to be transferred
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The completion handler object; can be {@code null}
*
* @return A Future representing the result of the operation
* The completion handler
*
* @throws IllegalArgumentException
* If the buffer is read-only
* @throws ReadPendingException
* If the channel does not allow more than one read to be outstanding
* and a previous read has not completed
* @throws ShutdownChannelGroupException
* If the channel is associated with a {@link AsynchronousChannelGroup
* group} that has terminated
*/
<A> Future<Integer> read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler);
<A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> An invocation of this method of the form <tt>c.read(dst)</tt>
* behaves in exactly the same manner as the invocation
* <blockquote><pre>
* c.read(dst, null, null);</pre></blockquote>
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The method
* behaves in exactly the same manner as the {@link
* #read(ByteBuffer,Object,CompletionHandler)
* read(ByteBuffer,Object,CompletionHandler)} method except that instead
* of specifying a completion handler, this method returns a {@code Future}
* representing the pending result. The {@code Future}'s {@link Future#get()
* get} method returns the number of bytes read or {@code -1} if no bytes
* could be read because the channel has reached end-of-stream.
*
* @param dst
* The buffer into which bytes are to be transferred
......@@ -134,17 +136,17 @@ public interface AsynchronousByteChannel
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> This method initiates an operation to write a sequence of bytes to
* this channel from the given buffer. This method returns a {@link
* Future} representing the pending result of the operation. The result
* of the operation, obtained by invoking the <tt>Future</tt>'s {@link
* Future#get() get} method, is the number of bytes written, possibly zero.
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the write
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes written.
*
* <p> This method initiates a write operation to write up to <i>r</i> bytes
* to the channel, where <i>r</i> is the number of bytes remaining in the
* buffer, that is, {@code src.remaining()} at the moment the write is
* attempted. Where <i>r</i> is 0, the write operation completes immediately
* with a result of {@code 0} without initiating an I/O operation.
* <p> The write operation may write up to <i>r</i> bytes to the channel,
* where <i>r</i> is the number of bytes remaining in the buffer, that is,
* {@code src.remaining()} at the time that the write is attempted. Where
* <i>r</i> is 0, the write operation completes immediately with a result of
* {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is written, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
......@@ -156,41 +158,43 @@ public interface AsynchronousByteChannel
* <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
* should be taken to not to access the buffer until the operaton has completed.
* should be taken to not access the buffer until the operation has
* completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one write to be outstanding at any given time. If a thread
* initiates a write operation before a previous write operation has
* completed then a {@link WritePendingException} will be thrown.
*
* <p> The <tt>handler</tt> parameter is used to specify a {@link
* CompletionHandler}. When the write operation completes the handler's
* {@link CompletionHandler#completed completed} method is executed.
*
* @param src
* The buffer from which bytes are to be retrieved
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The completion handler object; can be {@code null}
*
* @return A Future representing the result of the operation
* The completion handler object
*
* @throws WritePendingException
* If the channel does not allow more than one write to be outstanding
* and a previous write has not completed
* @throws ShutdownChannelGroupException
* If the channel is associated with a {@link AsynchronousChannelGroup
* group} that has terminated
*/
<A> Future<Integer> write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler);
<A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> An invocation of this method of the form <tt>c.write(src)</tt>
* behaves in exactly the same manner as the invocation
* <blockquote><pre>
* c.write(src, null, null);</pre></blockquote>
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The method
* behaves in exactly the same manner as the {@link
* #write(ByteBuffer,Object,CompletionHandler)
* write(ByteBuffer,Object,CompletionHandler)} method except that instead
* of specifying a completion handler, this method returns a {@code Future}
* representing the pending result. The {@code Future}'s {@link Future#get()
* get} method returns the number of bytes written.
*
* @param src
* The buffer from which bytes are to be retrieved
......
......@@ -34,7 +34,8 @@ import java.util.concurrent.Future; // javadoc
*
* <ol>
* <li><pre>{@link Future}&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>
*
* where <i>operation</i> is the name of the I/O operation (read or write for
......@@ -48,7 +49,7 @@ import java.util.concurrent.Future; // javadoc
* interface may be used to check if the operation has completed, wait for its
* completion, and to retrieve the result. In the second form, a {@link
* CompletionHandler} is invoked to consume the result of the I/O operation when
* it completes, fails, or is cancelled.
* it completes or fails.
*
* <p> A channel that implements this interface is <em>asynchronously
* closeable</em>: If an I/O operation is outstanding on the channel and the
......@@ -63,33 +64,33 @@ import java.util.concurrent.Future; // javadoc
* <h4>Cancellation</h4>
*
* <p> The {@code Future} interface defines the {@link Future#cancel cancel}
* method to cancel execution of a task.
*
* <p> Where the {@code cancel} method is invoked with the {@code
* method to cancel execution. This causes all threads waiting on the result of
* the I/O operation to throw {@link java.util.concurrent.CancellationException}.
* Whether the underlying I/O operation can be cancelled is highly implementation
* specific and therefore not specified. Where cancellation leaves the channel,
* or the entity to which it is connected, in an inconsistent state, then the
* channel is put into an implementation specific <em>error state</em> that
* prevents further attempts to initiate I/O operations that are <i>similar</i>
* to the operation that was cancelled. For example, if a read operation is
* cancelled but the implementation cannot guarantee that bytes have not been
* read from the channel then it puts the channel into an error state; further
* attempts to initiate a {@code read} operation cause an unspecified runtime
* exception to be thrown. Similarly, if a write operation is cancelled but the
* implementation cannot guarantee that bytes have not been written to the
* channel then subsequent attempts to initiate a {@code write} will fail with
* an unspecified runtime exception.
*
* <p> Where the {@link Future#cancel cancel} method is invoked with the {@code
* mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
* may be interrupted by closing the channel. This will cause any other I/O
* operations outstanding on the channel to complete with the exception {@link
* AsynchronousCloseException}.
*
* <p> If a {@code CompletionHandler} is specified when initiating an I/O
* operation, and the {@code cancel} method is invoked to cancel the I/O
* operation before it completes, then the {@code CompletionHandler}'s {@link
* CompletionHandler#cancelled cancelled} method is invoked.
*
* <p> If an implementation of this interface supports a means to cancel I/O
* operations, and where cancellation may leave the channel, or the entity to
* which it is connected, in an inconsistent state, then the channel is put into
* an implementation specific <em>error state</em> that prevents further
* attempts to initiate I/O operations on the channel. For example, if a read
* operation is cancelled but the implementation cannot guarantee that bytes
* have not been read from the channel then it puts the channel into error state
* state; further attempts to initiate a {@code read} operation causes an
* unspecified runtime exception to be thrown.
* may be interrupted by closing the channel. In that case all threads waiting
* on the result of the I/O operation throw {@code CancellationException} and
* any other I/O operations outstanding on the channel complete with the
* exception {@link AsynchronousCloseException}.
*
* <p> Where the {@code cancel} method is invoked to cancel read or write
* operations then it recommended that all buffers used in the I/O operations be
* discarded or care taken to ensure that the buffers are not accessed while the
* channel remains open.
* operations then it is recommended that all buffers used in the I/O operations
* be discarded or care taken to ensure that the buffers are not accessed while
* the channel remains open.
*
* @since 1.7
*/
......@@ -102,7 +103,7 @@ public interface AsynchronousChannel
*
* <p> Any outstanding asynchronous operations upon this channel will
* complete with the exception {@link AsynchronousCloseException}. After a
* channel is closed then further attempts to initiate asynchronous I/O
* channel is closed, further attempts to initiate asynchronous I/O
* operations complete immediately with cause {@link ClosedChannelException}.
*
* <p> This method otherwise behaves exactly as specified by the {@link
......
......@@ -85,9 +85,6 @@ import java.io.IOException;
* public void failed(Throwable exc, Void att) {
* ...
* }
* public void cancelled(Void att) {
* ...
* }
* });
* </pre>
*
......@@ -240,11 +237,11 @@ public abstract class AsynchronousServerSocketChannel
/**
* Accepts a connection.
*
* <p> This method initiates accepting a connection made to this channel's
* socket, returning a {@link Future} representing the pending result
* of the operation. The {@code Future}'s {@link Future#get() get}
* method will return the {@link AsynchronousSocketChannel} for the new
* connection on successful completion.
* <p> This method initiates an asynchronous operation to accept a
* connection made to this channel's socket. The {@code handler} parameter is
* a completion handler that is invoked when a connection is accepted (or
* the operation fails). The result passed to the completion handler is
* the {@link AsynchronousSocketChannel} to the new connection.
*
* <p> When a new connection is accepted then the resulting {@code
* AsynchronousSocketChannel} will be bound to the same {@link
......@@ -269,35 +266,35 @@ public abstract class AsynchronousServerSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return an <tt>Future</tt> object representing the pending result
* The handler for consuming the result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<AsynchronousSocketChannel>
accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
public abstract <A> void accept(A attachment,
CompletionHandler<AsynchronousSocketChannel,? super A> handler);
/**
* Accepts a connection.
*
* <p> This method is equivalent to invoking {@link
* #accept(Object,CompletionHandler)} with the {@code attachment}
* and {@code handler} parameters set to {@code null}.
* <p> This method initiates an asynchronous operation to accept a
* connection made to this channel's socket. The method behaves in exactly
* the same manner as the {@link #accept(Object, CompletionHandler)} method
* except that instead of specifying a completion handler, this method
* returns a {@code Future} representing the pending result. The {@code
* Future}'s {@link Future#get() get} method returns the {@link
* AsynchronousSocketChannel} to the new connection on successful completion.
*
* @return an <tt>Future</tt> object representing the pending result
* @return a {@code Future} object representing the pending result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
*/
public final Future<AsynchronousSocketChannel> accept() {
return accept(null, null);
}
public abstract Future<AsynchronousSocketChannel> accept();
}
......@@ -274,14 +274,11 @@ public abstract class AsynchronousSocketChannel
/**
* Connects this channel.
*
* <p> This method initiates an operation to connect this channel, returning
* a {@code Future} representing the pending result of the operation. If
* the connection is successfully established then the {@code Future}'s
* {@link Future#get() get} method will return {@code null}. If the
* connection cannot be established then the channel is closed. In that case,
* invoking the {@code get} method throws {@link
* java.util.concurrent.ExecutionException} with an {@code IOException} as
* the cause.
* <p> This method initiates an operation to connect this channel. The
* {@code handler} parameter is a completion handler that is invoked when
* the connection is successfully established or connection cannot be
* established. If the connection cannot be established then the channel is
* closed.
*
* <p> This method performs exactly the same security checks as the {@link
* java.net.Socket} class. That is, if a security manager has been
......@@ -294,9 +291,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
......@@ -307,23 +302,26 @@ public abstract class AsynchronousSocketChannel
* @throws ConnectionPendingException
* If a connection operation is already in progress on this channel
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*
* @see #getRemoteAddress
*/
public abstract <A> Future<Void> connect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler);
public abstract <A> void connect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler);
/**
* Connects this channel.
*
* <p> This method is equivalent to invoking {@link
* #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
* and handler parameters set to {@code null}.
* <p> This method initiates an operation to connect this channel. This
* method behaves in exactly the same manner as the {@link
* #connect(SocketAddress, Object, CompletionHandler)} method except that
* instead of specifying a completion handler, this method returns a {@code
* Future} representing the pending result. The {@code Future}'s {@link
* Future#get() get} method returns {@code null} on successful completion.
*
* @param remote
* The remote address to which this channel is to be connected
......@@ -342,18 +340,17 @@ public abstract class AsynchronousSocketChannel
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*/
public final Future<Void> connect(SocketAddress remote) {
return connect(remote, null, null);
}
public abstract Future<Void> connect(SocketAddress remote);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> This method initiates the reading of a sequence of bytes from this
* channel into the given buffer, returning a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method returns the number of bytes read or {@code -1}
* if all bytes have been read and channel has reached end-of-stream.
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the read
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes read or {@code -1} if no bytes could be
* read because the channel has reached end-of-stream.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link
......@@ -376,9 +373,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative or the buffer is
......@@ -388,13 +383,13 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Integer> read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler);
public abstract <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* @throws IllegalArgumentException {@inheritDoc}
......@@ -402,14 +397,14 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
@Override
public final <A> Future<Integer> read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler)
public final <A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
......@@ -419,16 +414,18 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected
*/
@Override
public final Future<Integer> read(ByteBuffer dst) {
return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
public abstract Future<Integer> read(ByteBuffer dst);
/**
* Reads a sequence of bytes from this channel into a subsequence of the
* given buffers. This operation, sometimes called a <em>scattering read</em>,
* is often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
* variable-length body.
* variable-length body. The {@code handler} parameter is a completion
* handler that is invoked when the read operation completes (or fails). The
* result passed to the completion handler is the number of bytes read or
* {@code -1} if no bytes could be read because the channel has reached
* end-of-stream.
*
* <p> This method initiates a read of up to <i>r</i> bytes from this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
......@@ -456,11 +453,6 @@ public abstract class AsynchronousSocketChannel
* I/O operation is performed with the maximum number of buffers allowed by
* the operating system.
*
* <p> The return value from this method is a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method returns the number of bytes read or {@code -1L}
* if all bytes have been read and the channel has reached end-of-stream.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
......@@ -485,9 +477,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
......@@ -500,23 +490,24 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Long> read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler);
public abstract <A> void read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> This method initiates the writing of a sequence of bytes to this channel
* from the given buffer, returning a {@code Future} representing the
* pending result of the operation. The {@code Future}'s {@link Future#get()
* get} method will return the number of bytes written.
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the write
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes written.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
......@@ -539,9 +530,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative
......@@ -550,28 +539,28 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Integer> write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler);
public abstract <A> void write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* @throws WritePendingException {@inheritDoc}
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
@Override
public final <A> Future<Integer> write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
public final <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
......@@ -580,16 +569,16 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected
*/
@Override
public final Future<Integer> write(ByteBuffer src) {
return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
}
public abstract Future<Integer> write(ByteBuffer src);
/**
* Writes a sequence of bytes to this channel from a subsequence of the given
* buffers. This operation, sometimes called a <em>gathering write</em>, is
* often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
* variable-length body.
* variable-length body. The {@code handler} parameter is a completion
* handler that is invoked when the write operation completes (or fails).
* The result passed to the completion handler is the number of bytes written.
*
* <p> This method initiates a write of up to <i>r</i> bytes to this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
......@@ -616,10 +605,6 @@ public abstract class AsynchronousSocketChannel
* remaining), exceeds this limit, then the I/O operation is performed with
* the maximum number of buffers allowed by the operating system.
*
* <p> The return value from this method is a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method will return the number of bytes written.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
......@@ -644,9 +629,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
......@@ -658,13 +641,13 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Long> write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler);
public abstract <A> void write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler);
}
......@@ -182,7 +182,6 @@ public final class Channels {
}
/**
* {@note new}
* Constructs a stream that reads bytes from the given channel.
*
* <p> The stream will not be buffered, and it will not support the {@link
......@@ -258,7 +257,6 @@ public final class Channels {
}
/**
* {@note new}
* Constructs a stream that writes bytes to the given channel.
*
* <p> The stream will not be buffered. The stream will be safe for access
......
......@@ -32,11 +32,9 @@ package java.nio.channels;
* handler to be specified to consume the result of an asynchronous operation.
* The {@link #completed completed} method is invoked when the I/O operation
* completes successfully. The {@link #failed failed} method is invoked if the
* I/O operations fails. The {@link #cancelled cancelled} method is invoked when
* the I/O operation is cancelled by invoking the {@link
* java.util.concurrent.Future#cancel cancel} method. The implementations of
* these methods should complete in a timely manner so as to avoid keeping the
* invoking thread from dispatching to other completion handlers.
* I/O operations fails. The implementations of these methods should complete
* in a timely manner so as to avoid keeping the invoking thread from dispatching
* to other completion handlers.
*
* @param <V> The result type of the I/O operation
* @param <A> The type of the object attached to the I/O operation
......@@ -65,13 +63,4 @@ public interface CompletionHandler<V,A> {
* The object attached to the I/O operation when it was initiated.
*/
void failed(Throwable exc, A attachment);
/**
* Invoked when an operation is cancelled by invoking the {@link
* java.util.concurrent.Future#cancel cancel} method.
*
* @param attachment
* The object attached to the I/O operation when it was initiated.
*/
void cancelled(A attachment);
}
......@@ -39,8 +39,7 @@ import java.util.Collections;
/**
* A channel for reading, writing, mapping, and manipulating a file.
*
* <p> {@note revised}
* A file channel is a {@link SeekableByteChannel} that is connected to
* <p> A file channel is a {@link SeekableByteChannel} that is connected to
* a file. It has a current <i>position</i> within its file which can
* be both {@link #position() <i>queried</i>} and {@link #position(long)
* <i>modified</i>}. The file itself contains a variable-length sequence
......@@ -151,7 +150,6 @@ import java.util.Collections;
* @author Mike McCloskey
* @author JSR-51 Expert Group
* @since 1.4
* @updated 1.7
*/
public abstract class FileChannel
......@@ -164,7 +162,6 @@ public abstract class FileChannel
protected FileChannel() { }
/**
* {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> The {@code options} parameter determines how the file is opened.
......@@ -293,7 +290,6 @@ public abstract class FileChannel
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
/**
* {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> An invocation of this method behaves in exactly the same way as the
......
......@@ -114,7 +114,6 @@ import java.io.IOException;
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
* @updated 1.7
*/
public abstract class FileLock {
......@@ -161,7 +160,7 @@ public abstract class FileLock {
}
/**
* {@note new} Initializes a new instance of this class.
* Initializes a new instance of this class.
*
* @param channel
* The channel upon whose file this lock is held
......@@ -199,7 +198,6 @@ public abstract class FileLock {
}
/**
* {@note revised}
* Returns the file channel upon whose file this lock was acquired.
*
* <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
......@@ -213,7 +211,6 @@ public abstract class FileLock {
}
/**
* {@note new}
* Returns the channel upon whose file this lock was acquired.
*
* @return The channel upon whose file this lock was acquired.
......
......@@ -190,5 +190,5 @@ gen WritePendingException "
gen ShutdownChannelGroupException "
* Unchecked exception thrown when an attempt is made to construct a channel in
* a group that is shutdown or the completion handler for an I/O operation
* cannot be invoked because the channel group is shutdown." \
* cannot be invoked because the channel group has terminated." \
-3903801676350154157L
......@@ -285,7 +285,6 @@
* java.lang.NullPointerException NullPointerException} to be thrown.
*
* @since 1.4
* @updated 1.7
* @author Mark Reinhold
* @author JSR-51 Expert Group
*/
......
......@@ -39,8 +39,6 @@ import java.io.IOException;
* metadata or file attributes.
*
* @since 1.7
* @see java.io.Inputs
* @see java.io.Outputs
* @see java.nio.file.attribute.Attributes
* @see java.io.File#toPath
*/
......
......@@ -674,7 +674,6 @@ public final class Scanner implements Iterator<String> {
}
/**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the underlying platform's
......@@ -694,7 +693,6 @@ public final class Scanner implements Iterator<String> {
}
/**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the specified charset.
......
......@@ -32,8 +32,8 @@ import java.io.IOException;
import java.io.FileDescriptor;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import java.security.PrivilegedAction;
import java.security.AccessController;
import java.security.AccessControlContext;
......@@ -65,11 +65,8 @@ abstract class AsynchronousChannelGroupImpl
private final Queue<Runnable> taskQueue;
// group shutdown
// shutdownLock is RW lock so as to allow for concurrent queuing of tasks
// when using a fixed thread pool.
private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
private final AtomicBoolean shutdown = new AtomicBoolean();
private final Object shutdownNowLock = new Object();
private volatile boolean shutdown;
private volatile boolean terminateInitiated;
AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
......@@ -214,7 +211,7 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final boolean isShutdown() {
return shutdown;
return shutdown.get();
}
@Override
......@@ -260,17 +257,10 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final void shutdown() {
shutdownLock.writeLock().lock();
try {
if (shutdown) {
// already shutdown
return;
}
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
if (shutdown.getAndSet(true)) {
// already shutdown
return;
}
// if there are channels in the group then shutdown will continue
// when the last channel is closed
if (!isEmpty()) {
......@@ -289,12 +279,7 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final void shutdownNow() throws IOException {
shutdownLock.writeLock().lock();
try {
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
}
shutdown.set(true);
synchronized (shutdownNowLock) {
if (!terminateInitiated) {
terminateInitiated = true;
......@@ -305,6 +290,18 @@ abstract class AsynchronousChannelGroupImpl
}
}
/**
* For use by AsynchronousFileChannel to release resources without shutting
* down the thread pool.
*/
final void detachFromThreadPool() {
if (shutdown.getAndSet(true))
throw new AssertionError("Already shutdown");
if (!isEmpty())
throw new AssertionError("Group not empty");
shutdownHandlerTasks();
}
@Override
public final boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException
......
......@@ -25,8 +25,10 @@
package sun.nio.ch;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.locks.*;
import java.io.FileDescriptor;
import java.io.IOException;
......@@ -101,6 +103,33 @@ abstract class AsynchronousFileChannelImpl
// -- file locking --
abstract <A> Future<FileLock> implLock(long position,
long size,
boolean shared,
A attachment,
CompletionHandler<FileLock,? super A> handler);
@Override
public final Future<FileLock> lock(long position,
long size,
boolean shared)
{
return implLock(position, size, shared, null, null);
}
@Override
public final <A> void lock(long position,
long size,
boolean shared,
A attachment,
CompletionHandler<FileLock,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implLock(position, size, shared, attachment, handler);
}
private volatile FileLockTable fileLockTable;
final void ensureFileLockTableInitialized() throws IOException {
......@@ -175,4 +204,50 @@ abstract class AsynchronousFileChannelImpl
end();
}
}
// -- reading and writing --
abstract <A> Future<Integer> implRead(ByteBuffer dst,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler);
@Override
public final Future<Integer> read(ByteBuffer dst, long position) {
return implRead(dst, position, null, null);
}
@Override
public final <A> void read(ByteBuffer dst,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implRead(dst, position, attachment, handler);
}
abstract <A> Future<Integer> implWrite(ByteBuffer src,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler);
@Override
public final Future<Integer> write(ByteBuffer src, long position) {
return implWrite(src, position, null, null);
}
@Override
public final <A> void write(ByteBuffer src,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implWrite(src, position, attachment, handler);
}
}
......@@ -35,6 +35,7 @@ import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.net.NetHooks;
......@@ -108,6 +109,29 @@ abstract class AsynchronousServerSocketChannelImpl
implClose();
}
/**
* Invoked by accept to accept connection
*/
abstract Future<AsynchronousSocketChannel>
implAccept(Object attachment,
CompletionHandler<AsynchronousSocketChannel,Object> handler);
@Override
public final Future<AsynchronousSocketChannel> accept() {
return implAccept(null, null);
}
@Override
@SuppressWarnings("unchecked")
public final <A> void accept(A attachment,
CompletionHandler<AsynchronousSocketChannel,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);
}
final boolean isAcceptKilled() {
return acceptKilled;
}
......
......@@ -183,29 +183,54 @@ abstract class AsynchronousSocketChannelImpl
killWriting();
}
/**
* Invoked by connect to initiate the connect operation.
*/
abstract <A> Future<Void> implConnect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler);
@Override
public final Future<Void> connect(SocketAddress remote) {
return implConnect(remote, null, null);
}
@Override
public final <A> void connect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implConnect(remote, attachment, handler);
}
/**
* Invoked by read to initiate the I/O operation.
*/
abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
boolean isScatteringRead,
abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
ByteBuffer dst,
ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> read(ByteBuffer[] dsts,
boolean isScatteringRead,
private <V extends Number,A> Future<V> read(boolean isScatteringRead,
ByteBuffer dst,
ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
A att,
CompletionHandler<V,? super A> handler)
{
if (!isOpen()) {
CompletedFuture<V,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable e = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(e);
Invoker.invoke(this, handler, att, null, e);
return null;
}
if (remoteAddress == null)
......@@ -213,13 +238,13 @@ abstract class AsynchronousSocketChannelImpl
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining();
boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
boolean shutdown = false;
// check and update state
synchronized (readLock) {
if (readKilled)
throw new RuntimeException("Reading not allowed due to timeout or cancellation");
throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
if (reading)
throw new ReadPendingException();
if (readShutdown) {
......@@ -234,44 +259,53 @@ abstract class AsynchronousSocketChannelImpl
// immediately complete with -1 if shutdown for read
// immediately complete with 0 if no space remaining
if (shutdown || !hasSpaceToRead) {
CompletedFuture<V,A> result;
Number result;
if (isScatteringRead) {
Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
} else {
int value = (shutdown) ? -1 : 0;
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
result = (shutdown) ? -1 : 0;
}
Invoker.invoke(handler, result);
return result;
if (handler == null)
return CompletedFuture.withResult((V)result);
Invoker.invoke(this, handler, att, (V)result, null);
return null;
}
return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler);
return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
}
@Override
public final <A> Future<Integer> read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
public final Future<Integer> read(ByteBuffer dst) {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@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())
throw new IllegalArgumentException("Read-only buffer");
ByteBuffer[] bufs = new ByteBuffer[1];
bufs[0] = dst;
return read(bufs, false, timeout, unit, attachment, handler);
read(false, dst, null, timeout, unit, attachment, handler);
}
@Override
public final <A> Future<Long> read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler)
public final <A> void read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
......@@ -279,39 +313,41 @@ abstract class AsynchronousSocketChannelImpl
if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
}
return read(bufs, true, timeout, unit, attachment, handler);
read(true, null, bufs, timeout, unit, attachment, handler);
}
/**
* Invoked by write to initiate the I/O operation.
*/
abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
boolean isGatheringWrite,
abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
ByteBuffer src,
ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> write(ByteBuffer[] srcs,
boolean isGatheringWrite,
private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
ByteBuffer src,
ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
A att,
CompletionHandler<V,? super A> handler)
{
boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining();
boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
boolean closed = false;
if (isOpen()) {
if (remoteAddress == null)
throw new NotYetConnectedException();
if (timeout < 0L)
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
// check and update state
synchronized (writeLock) {
if (writeKilled)
throw new RuntimeException("Writing not allowed due to timeout or cancellation");
throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
if (writing)
throw new WritePendingException();
if (writeShutdown) {
......@@ -327,52 +363,57 @@ abstract class AsynchronousSocketChannelImpl
// channel is closed or shutdown for write
if (closed) {
CompletedFuture<V,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable e = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(e);
Invoker.invoke(this, handler, att, null, e);
return null;
}
// nothing to write so complete immediately
if (!hasDataToWrite) {
CompletedFuture<V,A> result;
if (isGatheringWrite) {
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment);
} else {
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment);
}
Invoker.invoke(handler, result);
return result;
Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
if (handler == null)
return CompletedFuture.withResult((V)result);
Invoker.invoke(this, handler, att, (V)result, null);
return null;
}
return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler);
return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
}
@Override
public final <A> Future<Integer> write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
public final Future<Integer> write(ByteBuffer src) {
return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public final <A> void write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
ByteBuffer[] bufs = new ByteBuffer[1];
bufs[0] = src;
return write(bufs, false, timeout, unit, attachment, handler);
if (handler == null)
throw new NullPointerException("'handler' is null");
write(false, src, null, timeout, unit, attachment, handler);
}
@Override
public final <A> Future<Long> write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler)
public final <A> void write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Long,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
srcs = Util.subsequence(srcs, offset, length);
return write(srcs, true, timeout, unit, attachment, handler);
write(true, null, srcs, timeout, unit, attachment, handler);
}
@Override
......@@ -461,7 +502,6 @@ abstract class AsynchronousSocketChannelImpl
}
@Override
@SuppressWarnings("unchecked")
public final SocketAddress getRemoteAddress() throws IOException {
if (!isOpen())
throw new ClosedChannelException();
......
......@@ -25,7 +25,7 @@
package sun.nio.ch;
import java.nio.channels.AsynchronousChannel;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.io.IOException;
......@@ -35,39 +35,35 @@ import java.io.IOException;
* completed.
*/
final class CompletedFuture<V,A>
extends AbstractFuture<V,A>
{
final class CompletedFuture<V> implements Future<V> {
private final V result;
private final Throwable exc;
private CompletedFuture(AsynchronousChannel channel,
V result,
Throwable exc,
A attachment)
{
super(channel, attachment);
private CompletedFuture(V result, Throwable exc) {
this.result = result;
this.exc = exc;
}
@SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel,
V result,
A attachment)
{
return new CompletedFuture<V,A>(channel, result, null, attachment);
static <V> CompletedFuture<V> withResult(V result) {
return new CompletedFuture<V>(result, null);
}
@SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel,
Throwable exc,
A attachment)
{
static <V> CompletedFuture<V> withFailure(Throwable exc) {
// exception must be IOException or SecurityException
if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
exc = new IOException(exc);
return new CompletedFuture(channel, null, exc, attachment);
return new CompletedFuture(null, exc);
}
@SuppressWarnings("unchecked")
static <V> CompletedFuture<V> withResult(V result, Throwable exc) {
if (exc == null) {
return withResult(result);
} else {
return withFailure(exc);
}
}
@Override
......@@ -100,14 +96,4 @@ final class CompletedFuture<V,A>
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
Throwable exception() {
return exc;
}
@Override
V value() {
return result;
}
}
......@@ -117,33 +117,32 @@ class Invoker {
* Invoke handler without checking the thread identity or number of handlers
* on the thread stack.
*/
@SuppressWarnings("unchecked")
static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
A attachment,
V value,
Throwable exc)
{
if (handler != null && !result.isCancelled()) {
Throwable exc = result.exception();
if (exc == null) {
handler.completed(result.value(), result.attachment());
} else {
handler.failed(exc, result.attachment());
}
// clear interrupt
Thread.interrupted();
if (exc == null) {
handler.completed(value, attachment);
} else {
handler.failed(exc, attachment);
}
}
// clear interrupt
Thread.interrupted();
}
/**
* Invoke handler after incrementing the invoke count.
* Invoke handler assuming thread identity already checked
*/
static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
A attachment,
V result,
Throwable exc)
{
myGroupAndInvokeCount.incrementInvokeCount();
invokeUnchecked(handler, result);
Invoker.invokeUnchecked(handler, attachment, result, exc);
}
/**
......@@ -151,64 +150,64 @@ class Invoker {
* thread pool then the handler is invoked directly, otherwise it is
* invoked indirectly.
*/
static <V,A> void invoke(CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
static <V,A> void invoke(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler,
A attachment,
V result,
Throwable exc)
{
if (handler != null) {
boolean invokeDirect = false;
boolean identityOkay = false;
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null) {
AsynchronousChannel channel = result.channel();
if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
identityOkay = true;
if (identityOkay &&
(thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
{
// group match
invokeDirect = true;
}
boolean invokeDirect = false;
boolean identityOkay = false;
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null) {
if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
identityOkay = true;
if (identityOkay &&
(thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
{
// group match
invokeDirect = true;
}
if (invokeDirect) {
thisGroupAndInvokeCount.incrementInvokeCount();
invokeUnchecked(handler, result);
} else {
try {
invokeIndirectly(handler, result);
} catch (RejectedExecutionException ree) {
// channel group shutdown; fallback to invoking directly
// if the current thread has the right identity.
if (identityOkay) {
invokeUnchecked(handler, result);
} else {
throw new ShutdownChannelGroupException();
}
}
if (invokeDirect) {
invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
} else {
try {
invokeIndirectly(channel, handler, attachment, result, exc);
} catch (RejectedExecutionException ree) {
// channel group shutdown; fallback to invoking directly
// if the current thread has the right identity.
if (identityOkay) {
invokeDirect(thisGroupAndInvokeCount,
handler, attachment, result, exc);
} else {
throw new ShutdownChannelGroupException();
}
}
}
}
/**
* Invokes the handler "indirectly" in the channel group's thread pool.
* Invokes the handler indirectly via the channel group's thread pool.
*/
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
final AbstractFuture<V,A> result)
static <V,A> void invokeIndirectly(AsynchronousChannel channel,
final CompletionHandler<V,? super A> handler,
final A attachment,
final V result,
final Throwable exc)
{
if (handler != null) {
AsynchronousChannel channel = result.channel();
try {
((Groupable)channel).group().executeOnPooledThread(new Runnable() {
public void run() {
GroupAndInvokeCount thisGroupAndInvokeCount =
myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null)
thisGroupAndInvokeCount.setInvokeCount(1);
invokeUnchecked(handler, result);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
try {
((Groupable)channel).group().executeOnPooledThread(new Runnable() {
public void run() {
GroupAndInvokeCount thisGroupAndInvokeCount =
myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null)
thisGroupAndInvokeCount.setInvokeCount(1);
invokeUnchecked(handler, attachment, result, exc);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
}
......@@ -216,19 +215,19 @@ class Invoker {
* Invokes the handler "indirectly" in the given Executor
*/
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
final AbstractFuture<V,A> result,
final A attachment,
final V value,
final Throwable exc,
Executor executor)
{
if (handler != null) {
try {
executor.execute(new Runnable() {
public void run() {
invokeUnchecked(handler, result);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
try {
executor.execute(new Runnable() {
public void run() {
invokeUnchecked(handler, attachment, value, exc);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
}
......@@ -258,4 +257,52 @@ class Invoker {
throw new ShutdownChannelGroupException();
}
}
/**
* Invoke handler with completed result. This method does not check the
* thread identity or the number of handlers on the thread stack.
*/
static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invokeUnchecked(handler,
future.attachment(),
future.value(),
future.exception());
}
}
/**
* Invoke handler with completed result. If the current thread is in the
* channel group's thread pool then the handler is invoked directly,
* otherwise it is invoked indirectly.
*/
static <V,A> void invoke(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invoke(future.channel(),
handler,
future.attachment(),
future.value(),
future.exception());
}
}
/**
* Invoke handler with completed result. The handler is invoked indirectly,
* via the channel group's thread pool.
*/
static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invokeIndirectly(future.channel(),
handler,
future.attachment(),
future.value(),
future.exception());
}
}
}
......@@ -34,13 +34,13 @@ import java.io.IOException;
* attachment of an additional arbitrary context object and a timer task.
*/
final class PendingFuture<V,A>
extends AbstractFuture<V,A>
{
final class PendingFuture<V,A> implements Future<V> {
private static final CancellationException CANCELLED =
new CancellationException();
private final AsynchronousChannel channel;
private final CompletionHandler<V,? super A> handler;
private final A attachment;
// true if result (or exception) is available
private volatile boolean haveResult;
......@@ -56,14 +56,14 @@ final class PendingFuture<V,A>
// optional context object
private volatile Object context;
PendingFuture(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler,
A attachment,
Object context)
{
super(channel, attachment);
this.channel = channel;
this.handler = handler;
this.attachment = attachment;
this.context = context;
}
......@@ -71,14 +71,31 @@ final class PendingFuture<V,A>
CompletionHandler<V,? super A> handler,
A attachment)
{
super(channel, attachment);
this.channel = channel;
this.handler = handler;
this.attachment = attachment;
}
PendingFuture(AsynchronousChannel channel) {
this(channel, null, null);
}
PendingFuture(AsynchronousChannel channel, Object context) {
this(channel, null, null, context);
}
AsynchronousChannel channel() {
return channel;
}
CompletionHandler<V,? super A> handler() {
return handler;
}
A attachment() {
return attachment;
}
void setContext(Object context) {
this.context = context;
}
......@@ -113,36 +130,45 @@ final class PendingFuture<V,A>
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
boolean setResult(V res) {
void setResult(V res) {
synchronized (this) {
if (haveResult)
return false;
return;
result = res;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
return true;
}
}
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
boolean setFailure(Throwable x) {
void setFailure(Throwable x) {
if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x);
synchronized (this) {
if (haveResult)
return false;
return;
exc = x;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
return true;
}
}
/**
* Sets the result
*/
void setResult(V res, Throwable x) {
if (x == null) {
setResult(res);
} else {
setFailure(x);
}
}
......@@ -178,12 +204,10 @@ final class PendingFuture<V,A>
return result;
}
@Override
Throwable exception() {
return (exc != CANCELLED) ? exc : null;
}
@Override
V value() {
return result;
}
......@@ -204,33 +228,6 @@ final class PendingFuture<V,A>
if (haveResult)
return false; // already completed
// A shutdown of the channel group will close all channels and
// shutdown the executor. To ensure that the completion handler
// is executed we queue the task while holding the lock.
if (handler != null) {
prepareForWait();
Runnable cancelTask = new Runnable() {
public void run() {
while (!haveResult) {
try {
latch.await();
} catch (InterruptedException ignore) { }
}
handler.cancelled(attachment());
}
};
AsynchronousChannel ch = channel();
if (ch instanceof Groupable) {
((Groupable)ch).group().executeOnPooledThread(cancelTask);
} else {
if (ch instanceof AsynchronousFileChannelImpl) {
((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask);
} else {
throw new AssertionError("Should not get here");
}
}
}
// notify channel
if (channel() instanceof Cancellable)
((Cancellable)channel()).onCancel(this);
......@@ -249,7 +246,7 @@ final class PendingFuture<V,A>
} catch (IOException ignore) { }
}
// release waiters (this also releases the invoker)
// release waiters
if (latch != null)
latch.countDown();
return true;
......
......@@ -317,51 +317,71 @@ class SimpleAsynchronousDatagramChannelImpl
return new WrappedMembershipKey(this, key);
}
@Override
public <A> Future<Integer> send(ByteBuffer src,
SocketAddress target,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
private <A> Future<Integer> implSend(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
CompletedFuture<Integer,A> result;
int n = 0;
Throwable exc = null;
try {
int n = dc.send(src, target);
result = CompletedFuture.withResult(this, n, attachment);
n = dc.send(src, target);
} catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment);
exc = ioe;
}
Invoker.invoke(handler, result);
return result;
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> send(ByteBuffer src, SocketAddress target) {
return implSend(src, target, null, null);
}
@Override
public <A> Future<Integer> write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
public <A> void send(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
if (handler == null)
throw new NullPointerException("'handler' is null");
implSend(src, target, attachment, handler);
}
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 {
int n = dc.write(src);
result = CompletedFuture.withResult(this, n, attachment);
n = dc.write(src);
} catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment);
exc = ioe;
}
Invoker.invoke(handler, result);
return result;
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> write(ByteBuffer src) {
return implWrite(src, null, null);
}
@Override
public <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implWrite(src, attachment, handler);
}
/**
......@@ -390,12 +410,11 @@ class SimpleAsynchronousDatagramChannelImpl
}
}
@Override
public <A> Future<SocketAddress> receive(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<SocketAddress,? super A> handler)
private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<SocketAddress,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
......@@ -406,10 +425,11 @@ class SimpleAsynchronousDatagramChannelImpl
// complete immediately if channel closed
if (!isOpen()) {
CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
final AccessControlContext acc = (System.getSecurityManager() == null) ?
......@@ -471,7 +491,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(handler, result);
Invoker.invokeUnchecked(result);
}
};
try {
......@@ -483,11 +503,27 @@ class SimpleAsynchronousDatagramChannelImpl
}
@Override
public <A> Future<Integer> read(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<Integer,? super A> handler)
public Future<SocketAddress> receive(ByteBuffer dst) {
return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void receive(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<SocketAddress,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implReceive(dst, timeout, unit, attachment, handler);
}
private <A> Future<Integer> implRead(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
......@@ -495,18 +531,20 @@ class SimpleAsynchronousDatagramChannelImpl
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
// complete immediately if channel closed
if (!isOpen()) {
CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
Runnable task = new Runnable() {
......@@ -563,7 +601,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(handler, result);
Invoker.invokeUnchecked(result);
}
};
try {
......@@ -574,6 +612,23 @@ class SimpleAsynchronousDatagramChannelImpl
return result;
}
@Override
public Future<Integer> read(ByteBuffer dst) {
return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implRead(dst, timeout, unit, attachment, handler);
}
@Override
public AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException
......
......@@ -50,9 +50,6 @@ public class SimpleAsynchronousFileChannelImpl
// Used to make native read and write calls
private static final FileDispatcher nd = new FileDispatcherImpl();
// indicates if the associated thread pool is the default thread pool
private final boolean isDefaultExecutor;
// Thread-safe set of IDs of native threads, for signalling
private final NativeThreadSet threads = new NativeThreadSet(2);
......@@ -60,11 +57,9 @@ public class SimpleAsynchronousFileChannelImpl
SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
boolean reading,
boolean writing,
ExecutorService executor,
boolean isDefaultexecutor)
ExecutorService executor)
{
super(fdObj, reading, writing, executor);
this.isDefaultExecutor = isDefaultexecutor;
}
public static AsynchronousFileChannel open(FileDescriptor fdo,
......@@ -73,17 +68,9 @@ public class SimpleAsynchronousFileChannelImpl
ThreadPool pool)
{
// Executor is either default or based on pool parameters
ExecutorService executor;
boolean isDefaultexecutor;
if (pool == null) {
executor = DefaultExecutorHolder.defaultExecutor;
isDefaultexecutor = true;
} else {
executor = pool.executor();
isDefaultexecutor = false;
}
return new SimpleAsynchronousFileChannelImpl(fdo,
reading, writing, executor, isDefaultexecutor);
ExecutorService executor = (pool == null) ?
DefaultExecutorHolder.defaultExecutor : pool.executor();
return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
}
@Override
......@@ -114,16 +101,6 @@ public class SimpleAsynchronousFileChannelImpl
// close file
nd.close(fdObj);
// shutdown executor if specific to this channel
if (!isDefaultExecutor) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
executor.shutdown();
return null;
}
});
}
}
@Override
......@@ -194,11 +171,11 @@ public class SimpleAsynchronousFileChannelImpl
}
@Override
public <A> Future<FileLock> lock(final long position,
final long size,
final boolean shared,
A attachment,
final CompletionHandler<FileLock,? super A> handler)
<A> Future<FileLock> implLock(final long position,
final long size,
final boolean shared,
final A attachment,
final CompletionHandler<FileLock,? super A> handler)
{
if (shared && !reading)
throw new NonReadableChannelException();
......@@ -208,16 +185,19 @@ public class SimpleAsynchronousFileChannelImpl
// add to lock table
final FileLockImpl fli = addToFileLockTable(position, size, shared);
if (fli == null) {
CompletedFuture<FileLock,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
return null;
}
final PendingFuture<FileLock,A> result =
new PendingFuture<FileLock,A>(this, handler, attachment);
final PendingFuture<FileLock,A> result = (handler == null) ?
new PendingFuture<FileLock,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
Throwable exc = null;
int ti = threads.add();
try {
int n;
......@@ -226,31 +206,36 @@ public class SimpleAsynchronousFileChannelImpl
do {
n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n == FileDispatcher.LOCKED && isOpen()) {
result.setResult(fli);
} else {
if (n != FileDispatcher.LOCKED || !isOpen()) {
throw new AsynchronousCloseException();
}
} catch (IOException x) {
removeFromFileLockTable(fli);
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
}
} finally {
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(fli, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, fli, exc);
}
}
};
boolean executed = false;
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
// rollback
removeFromFileLockTable(fli);
throw new ShutdownChannelGroupException();
executed = true;
} finally {
if (!executed) {
// rollback
removeFromFileLockTable(fli);
}
}
return result;
}
......@@ -301,10 +286,10 @@ public class SimpleAsynchronousFileChannelImpl
}
@Override
public <A> Future<Integer> read(final ByteBuffer dst,
final long position,
A attachment,
final CompletionHandler<Integer,? super A> handler)
<A> Future<Integer> implRead(final ByteBuffer dst,
final long position,
final A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
throw new IllegalArgumentException("Negative position");
......@@ -315,55 +300,52 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel closed or no space remaining
if (!isOpen() || (dst.remaining() == 0)) {
CompletedFuture<Integer,A> result;
if (isOpen()) {
result = CompletedFuture.withResult(this, 0, attachment);
} else {
result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (handler == null)
return CompletedFuture.withResult(0, exc);
Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
return null;
}
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add();
try {
begin();
int n;
do {
n = IOUtil.read(fdObj, dst, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(n, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, n, exc);
}
}
};
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
executor.execute(task);
return result;
}
@Override
public <A> Future<Integer> write(final ByteBuffer src,
final long position,
A attachment,
final CompletionHandler<Integer,? super A> handler)
<A> Future<Integer> implWrite(final ByteBuffer src,
final long position,
final A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
throw new IllegalArgumentException("Negative position");
......@@ -372,47 +354,44 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel is closed or no bytes remaining
if (!isOpen() || (src.remaining() == 0)) {
CompletedFuture<Integer,A> result;
if (isOpen()) {
result = CompletedFuture.withResult(this, 0, attachment);
} else {
result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (handler == null)
return CompletedFuture.withResult(0, exc);
Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
return null;
}
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add();
try {
begin();
int n;
do {
n = IOUtil.write(fdObj, src, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(n, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, n, exc);
}
}
};
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
executor.execute(task);
return result;
}
}
......@@ -388,9 +388,9 @@ abstract class ISO2022
protected static class Encoder extends CharsetEncoder {
private final Surrogate.Parser sgp = new Surrogate.Parser();
private final byte SS2 = (byte)0x8e;
private final byte PLANE2 = (byte)0xA2;
private final byte PLANE3 = (byte)0xA3;
public static final byte SS2 = (byte)0x8e;
public static final byte PLANE2 = (byte)0xA2;
public static final byte PLANE3 = (byte)0xA3;
private final byte MSB = (byte)0x80;
protected final byte maximumDesignatorLength = 4;
......
......@@ -76,6 +76,15 @@ public class ISO2022_CN_CNS extends ISO2022 implements HistoricallyNamedCharset
} catch (Exception e) { }
}
private byte[] bb = new byte[4];
public boolean canEncode(char c) {
int n = 0;
return (c <= '\u007f' ||
(n = ((EUC_TW.Encoder)ISOEncoder).toEUC(c, bb)) == 2 ||
(n == 4 && bb[0] == SS2 &&
(bb[1] == PLANE2 || bb[1] == PLANE3)));
}
/*
* Since ISO2022-CN-CNS possesses a CharsetEncoder
* without the corresponding CharsetDecoder half the
......
......@@ -62,7 +62,7 @@ public final class SunProvider extends Provider {
public SunProvider() {
/* We are the Sun JGSS provider */
super("SunJGSS", 1.0, INFO);
super("SunJGSS", 1.7d, INFO);
AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
......
......@@ -41,6 +41,7 @@ import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.util.Comparator;
import java.util.StringTokenizer;
/**
......@@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants {
/**
* Reads the service key from the keytab file.
* @param service the PrincipalName of the requested service.
* @return the last service key in the keytab
* @return the last service key in the keytab with the highest kvno
*/
public EncryptionKey readServiceKey(PrincipalName service) {
KeyTabEntry entry = null;
EncryptionKey key = null;
if (entries != null) {
// Find latest entry for this service that has an etype
// that has been configured for use
......@@ -240,9 +242,12 @@ public class KeyTab implements KeyTabConstants {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
return new EncryptionKey(entry.keyblock,
if (key == null ||
entry.keyVersion > key.getKeyVersionNumber()) {
key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
}
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
......@@ -250,12 +255,13 @@ public class KeyTab implements KeyTabConstants {
}
}
}
return null;
return key;
}
/**
* Reads all keys for a service from the keytab file that have
* etypes that have been configured for use.
* etypes that have been configured for use. If there are multiple
* keys with same etype, the one with the highest kvno is returned.
* @param service the PrincipalName of the requested service
* @return an array containing all the service keys
*/
......@@ -288,49 +294,39 @@ public class KeyTab implements KeyTabConstants {
size = keys.size();
if (size == 0)
return null;
EncryptionKey[] retVal = new EncryptionKey[size];
EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
// Sort keys according to default_tkt_enctypes
int pos = 0;
EncryptionKey k;
if (DEBUG) {
System.out.println("Ordering keys wrt default_tkt_enctypes list");
}
int[] etypes = EType.getDefaults("default_tkt_enctypes");
if (etypes == null || etypes == EType.getBuiltInDefaults()) {
// Either no supported types specified in default_tkt_enctypes
// or no default_tkt_enctypes entry at all. For both cases,
// just return supported keys in the order retrieved
for (int i = 0; i < size; i++) {
retVal[pos++] = keys.get(i);
}
} else {
for (int j = 0; j < etypes.length && pos < size; j++) {
int target = etypes[j];
for (int i = 0; i < size && pos < size; i++) {
k = keys.get(i);
if (k != null && k.getEType() == target) {
if (DEBUG) {
System.out.println(pos + ": " + k);
final int[] etypes = EType.getDefaults("default_tkt_enctypes");
// Sort the keys, k1 is preferred than k2 if:
// 1. k1's etype appears earlier in etypes than k2's
// 2. If same, k1's KVNO is higher
Arrays.sort(retVal, new Comparator<EncryptionKey>() {
@Override
public int compare(EncryptionKey o1, EncryptionKey o2) {
if (etypes != null && etypes != EType.getBuiltInDefaults()) {
int o1EType = o1.getEType();
int o2EType = o2.getEType();
if (o1EType != o2EType) {
for (int i=0; i<etypes.length; i++) {
if (etypes[i] == o1EType) {
return -1;
} else if (etypes[i] == o2EType) {
return 1;
}
}
retVal[pos++] = k;
keys.set(i, null); // Cleared from consideration
}
}
return o2.getKeyVersionNumber().intValue()
- o1.getKeyVersionNumber().intValue();
}
// copy the rest
for (int i = 0; i < size && pos < size; i++) {
k = keys.get(i);
if (k != null) {
retVal[pos++] = k;
}
}
}
if (pos != size) {
throw new RuntimeException(
"Internal Error: did not copy all keys;expecting " + size +
"; got " + pos);
}
});
return retVal;
}
......
......@@ -46,7 +46,7 @@ public final class Sun extends Provider {
public Sun() {
/* We are the SUN provider */
super("SUN", 1.6, INFO);
super("SUN", 1.7, INFO);
// if there is no security manager installed, put directly into
// the provider. Otherwise, create a temporary map and use a
......
......@@ -40,7 +40,7 @@ public final class SunPCSC extends Provider {
private static final long serialVersionUID = 6168388284028876579L;
public SunPCSC() {
super("SunPCSC", 1.6d, "Sun PC/SC provider");
super("SunPCSC", 1.7d, "Sun PC/SC provider");
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
put("TerminalFactory.PC/SC", "sun.security.smartcardio.SunPCSC$Factory");
......
......@@ -103,7 +103,7 @@ public abstract class SunJSSE extends java.security.Provider {
// standard constructor
protected SunJSSE() {
super("SunJSSE", 1.6d, info);
super("SunJSSE", 1.7d, info);
subclassCheck();
if (Boolean.TRUE.equals(fips)) {
throw new ProviderException
......
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -37,6 +37,14 @@ import java.util.Arrays;
public class Password {
/** Reads user password from given input stream. */
public static char[] readPassword(InputStream in) throws IOException {
return readPassword(in, false);
}
/** Reads user password from given input stream.
* @param isEchoOn true if the password should be echoed on the screen
*/
public static char[] readPassword(InputStream in, boolean isEchoOn)
throws IOException {
char[] consoleEntered = null;
byte[] consoleBytes = null;
......@@ -44,7 +52,7 @@ public class Password {
try {
// Use the new java.io.Console class
Console con = null;
if (in == System.in && ((con = System.console()) != null)) {
if (!isEchoOn && in == System.in && ((con = System.console()) != null)) {
consoleEntered = con.readPassword();
// readPassword returns "" if you just print ENTER,
// to be compatible with old Password class, change to null
......
......@@ -422,7 +422,7 @@ ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
*/
if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
if (randomlen != 2 * len) {
goto cleanup;
randomlen = 2 * len;
}
/* No need to generate - random bytes are now supplied */
/* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
......
......@@ -248,12 +248,13 @@ final class EPollPort
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
final boolean isPooledThread = (myGroupAndInvokeCount != null);
boolean replaceMe = false;
Event ev;
try {
for (;;) {
// reset invoke count
if (myGroupAndInvokeCount != null)
if (isPooledThread)
myGroupAndInvokeCount.resetInvokeCount();
try {
......@@ -289,7 +290,7 @@ final class EPollPort
// process event
try {
ev.channel().onEvent(ev.events());
ev.channel().onEvent(ev.events(), isPooledThread);
} catch (Error x) {
replaceMe = true; throw x;
} catch (RuntimeException x) {
......
......@@ -49,7 +49,7 @@ abstract class Port extends AsynchronousChannelGroupImpl {
* Implemented by clients registered with this port.
*/
interface PollableChannel extends Closeable {
void onEvent(int events);
void onEvent(int events, boolean mayInvokeDirect);
}
// maps fd to "pollable" channel
......@@ -121,7 +121,7 @@ abstract class Port extends AsynchronousChannelGroupImpl {
final Object attachForeignChannel(final Channel channel, FileDescriptor fd) {
int fdVal = IOUtil.fdVal(fd);
register(fdVal, new PollableChannel() {
public void onEvent(int events) { }
public void onEvent(int events, boolean mayInvokeDirect) { }
public void close() throws IOException {
channel.close();
}
......
......@@ -151,12 +151,13 @@ class SolarisEventPort
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
final boolean isPooledThread = (myGroupAndInvokeCount != null);
boolean replaceMe = false;
long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
try {
for (;;) {
// reset invoke count
if (myGroupAndInvokeCount != null)
if (isPooledThread)
myGroupAndInvokeCount.resetInvokeCount();
// wait for I/O completion event
......@@ -205,7 +206,7 @@ class SolarisEventPort
if (ch != null) {
replaceMe = true;
// no need to translate events
ch.onEvent(events);
ch.onEvent(events, isPooledThread);
}
}
} finally {
......
......@@ -59,10 +59,13 @@ class UnixAsynchronousServerSocketChannelImpl
private final Object updateLock = new Object();
// pending accept
private PendingFuture<AsynchronousSocketChannel,Object> pendingAccept;
private boolean acceptPending;
private CompletionHandler<AsynchronousSocketChannel,Object> acceptHandler;
private Object acceptAttachment;
private PendingFuture<AsynchronousSocketChannel,Object> acceptFuture;
// context for permission check when security manager set
private AccessControlContext acc;
private AccessControlContext acceptAcc;
UnixAsynchronousServerSocketChannelImpl(Port port)
......@@ -83,15 +86,6 @@ class UnixAsynchronousServerSocketChannelImpl
port.register(fdVal, this);
}
// returns and clears the result of a pending accept
private PendingFuture<AsynchronousSocketChannel,Object> grabPendingAccept() {
synchronized (updateLock) {
PendingFuture<AsynchronousSocketChannel,Object> result = pendingAccept;
pendingAccept = null;
return result;
}
}
@Override
void implClose() throws IOException {
// remove the mapping
......@@ -101,17 +95,27 @@ class UnixAsynchronousServerSocketChannelImpl
nd.close(fd);
// if there is a pending accept then complete it
final PendingFuture<AsynchronousSocketChannel,Object> result =
grabPendingAccept();
if (result != null) {
// discard the stack trace as otherwise it may appear that implClose
// has thrown the exception.
AsynchronousCloseException x = new AsynchronousCloseException();
x.setStackTrace(new StackTraceElement[0]);
result.setFailure(x);
CompletionHandler<AsynchronousSocketChannel,Object> handler;
Object att;
PendingFuture<AsynchronousSocketChannel,Object> future;
synchronized (updateLock) {
if (!acceptPending)
return; // no pending accept
acceptPending = false;
handler = acceptHandler;
att = acceptAttachment;
future = acceptFuture;
}
// discard the stack trace as otherwise it may appear that implClose
// has thrown the exception.
AsynchronousCloseException x = new AsynchronousCloseException();
x.setStackTrace(new StackTraceElement[0]);
if (handler == null) {
future.setFailure(x);
} else {
// invoke by submitting task rather than directly
Invoker.invokeIndirectly(result.handler(), result);
Invoker.invokeIndirectly(this, handler, att, null, x);
}
}
......@@ -124,15 +128,17 @@ class UnixAsynchronousServerSocketChannelImpl
* Invoked by event handling thread when listener socket is polled
*/
@Override
public void onEvent(int events) {
PendingFuture<AsynchronousSocketChannel,Object> result = grabPendingAccept();
if (result == null)
return; // may have been grabbed by asynchronous close
public void onEvent(int events, boolean mayInvokeDirect) {
synchronized (updateLock) {
if (!acceptPending)
return; // may have been grabbed by asynchronous close
acceptPending = false;
}
// attempt to accept connection
FileDescriptor newfd = new FileDescriptor();
InetSocketAddress[] isaa = new InetSocketAddress[1];
boolean accepted = false;
Throwable exc = null;
try {
begin();
int n = accept0(this.fd, newfd, isaa);
......@@ -140,49 +146,52 @@ class UnixAsynchronousServerSocketChannelImpl
// spurious wakeup, is this possible?
if (n == IOStatus.UNAVAILABLE) {
synchronized (updateLock) {
this.pendingAccept = result;
acceptPending = true;
}
port.startPoll(fdVal, Port.POLLIN);
return;
}
// connection accepted
accepted = true;
} catch (Throwable x) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
enableAccept();
result.setFailure(x);
exc = x;
} finally {
end();
}
// Connection accepted so finish it when not holding locks.
AsynchronousSocketChannel child = null;
if (accepted) {
if (exc == null) {
try {
child = finishAccept(newfd, isaa[0], acc);
enableAccept();
result.setResult(child);
child = finishAccept(newfd, isaa[0], acceptAcc);
} catch (Throwable x) {
enableAccept();
if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x);
result.setFailure(x);
exc = x;
}
}
// if an async cancel has already cancelled the operation then
// close the new channel so as to free resources
if (child != null && result.isCancelled()) {
try {
child.close();
} catch (IOException ignore) { }
}
// copy field befores accept is re-renabled
CompletionHandler<AsynchronousSocketChannel,Object> handler = acceptHandler;
Object att = acceptAttachment;
PendingFuture<AsynchronousSocketChannel,Object> future = acceptFuture;
// invoke the handler
Invoker.invoke(result.handler(), result);
// re-enable accepting and invoke handler
enableAccept();
if (handler == null) {
future.setResult(child, exc);
// if an async cancel has already cancelled the operation then
// close the new channel so as to free resources
if (child != null && future.isCancelled()) {
try {
child.close();
} catch (IOException ignore) { }
}
} else {
Invoker.invoke(this, handler, att, child, exc);
}
}
/**
......@@ -234,16 +243,18 @@ class UnixAsynchronousServerSocketChannelImpl
}
@Override
@SuppressWarnings("unchecked")
public <A> Future<AsynchronousSocketChannel> accept(A attachment,
final CompletionHandler<AsynchronousSocketChannel,? super A> handler)
Future<AsynchronousSocketChannel> implAccept(Object att,
CompletionHandler<AsynchronousSocketChannel,Object> handler)
{
// complete immediately if channel is closed
if (!isOpen()) {
CompletedFuture<AsynchronousSocketChannel,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invokeIndirectly(handler, result);
return result;
Throwable e = new ClosedChannelException();
if (handler == null) {
return CompletedFuture.withFailure(e);
} else {
Invoker.invoke(this, handler, att, null, e);
return null;
}
}
if (localAddress == null)
throw new NotYetBoundException();
......@@ -258,25 +269,31 @@ class UnixAsynchronousServerSocketChannelImpl
throw new AcceptPendingException();
// attempt accept
AbstractFuture<AsynchronousSocketChannel,A> result = null;
FileDescriptor newfd = new FileDescriptor();
InetSocketAddress[] isaa = new InetSocketAddress[1];
Throwable exc = null;
try {
begin();
int n = accept0(this.fd, newfd, isaa);
if (n == IOStatus.UNAVAILABLE) {
// no connection to accept
result = new PendingFuture<AsynchronousSocketChannel,A>(this, handler, attachment);
// need calling context when there is security manager as
// permission check may be done in a different thread without
// any application call frames on the stack
synchronized (this) {
this.acc = (System.getSecurityManager() == null) ?
PendingFuture<AsynchronousSocketChannel,Object> result = null;
synchronized (updateLock) {
if (handler == null) {
this.acceptHandler = null;
result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
this.acceptFuture = result;
} else {
this.acceptHandler = handler;
this.acceptAttachment = att;
}
this.acceptAcc = (System.getSecurityManager() == null) ?
null : AccessController.getContext();
this.pendingAccept =
(PendingFuture<AsynchronousSocketChannel,Object>)result;
this.acceptPending = true;
}
// register for connections
......@@ -287,25 +304,30 @@ class UnixAsynchronousServerSocketChannelImpl
// accept failed
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
result = CompletedFuture.withFailure(this, x, attachment);
exc = x;
} finally {
end();
}
// connection accepted immediately
if (result == null) {
AsynchronousSocketChannel child = null;
if (exc == null) {
// connection accepted immediately
try {
AsynchronousSocketChannel ch = finishAccept(newfd, isaa[0], null);
result = CompletedFuture.withResult(this, ch, attachment);
child = finishAccept(newfd, isaa[0], null);
} catch (Throwable x) {
result = CompletedFuture.withFailure(this, x, attachment);
exc = x;
}
}
// re-enable accepting and invoke handler
// re-enable accepting before invoking handler
enableAccept();
Invoker.invokeIndirectly(handler, result);
return result;
if (handler == null) {
return CompletedFuture.withResult(child, exc);
} else {
Invoker.invokeIndirectly(this, handler, att, child, exc);
return null;
}
}
// -- Native methods --
......
......@@ -65,9 +65,6 @@ class UnixPath
// array of offsets of elements in path (created lazily)
private volatile int[] offsets;
// file permissions (created lazily)
private volatile FilePermission[] perms;
UnixPath(UnixFileSystem fs, byte[] path) {
this.fs = fs;
this.path = path;
......@@ -768,45 +765,23 @@ class UnixPath
}
}
// create file permissions used for read and write checks
private void checkReadOrWrite(boolean checkRead) {
SecurityManager sm = System.getSecurityManager();
if (sm == null)
return;
if (perms == null) {
synchronized (this) {
if (perms == null) {
FilePermission[] p = new FilePermission[2];
String pathForPermCheck = getPathForPermissionCheck();
p[0] = new FilePermission(pathForPermCheck,
SecurityConstants.FILE_READ_ACTION);
p[1] = new FilePermission(pathForPermCheck,
SecurityConstants.FILE_WRITE_ACTION);
perms = p;
}
}
}
if (checkRead) {
sm.checkPermission(perms[0]);
} else {
sm.checkPermission(perms[1]);
}
}
void checkRead() {
checkReadOrWrite(true);
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkRead(getPathForPermissionCheck());
}
void checkWrite() {
checkReadOrWrite(false);
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkWrite(getPathForPermissionCheck());
}
void checkDelete() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// permission not cached
if (sm != null)
sm.checkDelete(getPathForPermissionCheck());
}
}
@Override
......
......@@ -34,6 +34,8 @@ import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
import sun.misc.Unsafe;
/**
......@@ -44,6 +46,7 @@ import sun.misc.Unsafe;
class Iocp extends AsynchronousChannelGroupImpl {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long INVALID_HANDLE_VALUE = -1L;
private static final boolean supportsThreadAgnosticIo;
// maps completion key to channel
private final ReadWriteLock keyToChannelLock = new ReentrantReadWriteLock();
......@@ -87,6 +90,13 @@ class Iocp extends AsynchronousChannelGroupImpl {
<V,A> PendingFuture<V,A> getByOverlapped(long overlapped);
}
/**
* Indicates if this operating system supports thread agnostic I/O.
*/
static boolean supportsThreadAgnosticIo() {
return supportsThreadAgnosticIo;
}
// release all resources
void implClose() {
synchronized (this) {
......@@ -216,8 +226,9 @@ class Iocp extends AsynchronousChannelGroupImpl {
} while ((key == 0) || keyToChannel.containsKey(key));
// associate with I/O completion port
if (handle != 0L)
if (handle != 0L) {
createIoCompletionPort(handle, port, key, 0);
}
// setup mapping
keyToChannel.put(key, ch);
......@@ -282,7 +293,7 @@ class Iocp extends AsynchronousChannelGroupImpl {
/**
* Invoked if the I/O operation completes successfully.
*/
public void completed(int bytesTransferred);
public void completed(int bytesTransferred, boolean canInvokeDirect);
/**
* Invoked if the I/O operation fails.
......@@ -305,6 +316,7 @@ class Iocp extends AsynchronousChannelGroupImpl {
public void run() {
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
Invoker.getGroupAndInvokeCount();
boolean canInvokeDirect = (myGroupAndInvokeCount != null);
CompletionStatus ioResult = new CompletionStatus();
boolean replaceMe = false;
......@@ -382,7 +394,7 @@ class Iocp extends AsynchronousChannelGroupImpl {
ResultHandler rh = (ResultHandler)result.getContext();
replaceMe = true; // (if error/exception then replace thread)
if (error == 0) {
rh.completed(ioResult.bytesTransferred());
rh.completed(ioResult.bytesTransferred(), canInvokeDirect);
} else {
rh.failed(error, translateErrorToIOException(error));
}
......@@ -433,5 +445,11 @@ class Iocp extends AsynchronousChannelGroupImpl {
static {
Util.load();
initIDs();
// thread agnostic I/O on Vista/2008 or newer
String osversion = AccessController.doPrivileged(
new GetPropertyAction("os.version"));
String vers[] = osversion.split("\\.");
supportsThreadAgnosticIo = Integer.parseInt(vers[0]) >= 6;
}
}
......@@ -46,6 +46,7 @@ class WindowsFileAttributeViews {
@Override
public WindowsFileAttributes readAttributes() throws IOException {
file.checkRead();
try {
return WindowsFileAttributes.get(file, followLinks);
} catch (WindowsException x) {
......
......@@ -283,25 +283,15 @@ class WindowsFileSystem
}
}
// match in uppercase
StringBuilder sb = new StringBuilder(expr.length());
for (int i=0; i<expr.length(); i++) {
sb.append(Character.toUpperCase(expr.charAt(i)));
}
expr = sb.toString();
// match in unicode_case_insensitive
final Pattern pattern = Pattern.compile(expr,
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
// return matcher
final Pattern pattern = Pattern.compile(expr);
return new PathMatcher() {
@Override
public boolean matches(Path path) {
// match in uppercase
String s = path.toString();
StringBuilder sb = new StringBuilder(s.length());
for (int i=0; i<s.length(); i++) {
sb.append( Character.toUpperCase(s.charAt(i)) );
}
return pattern.matcher(sb).matches();
return pattern.matcher(path.toString()).matches();
}
};
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册