mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-20 07:15:31 +00:00
Merge
This commit is contained in:
commit
7df21ac3bf
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
|
||||
@ -90,14 +90,16 @@ public class Continuation extends ResolveResult {
|
||||
* Constructs a new instance of Continuation.
|
||||
* @param top The name of the object that is to be resolved/operated upon.
|
||||
* This becomes the Continuation's 'starter' and is used to
|
||||
* calculate the "resolved name" when filling in a NamingException.
|
||||
* calculate the "resolved name" when filling in a NamingException.
|
||||
* @param environment The environment used by the caller. It is used
|
||||
* when setting the "environment" of a CannotProceedException.
|
||||
* when setting the "environment" of a CannotProceedException.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // For Hashtable clone: environment.clone()
|
||||
public Continuation(Name top, Hashtable<?,?> environment) {
|
||||
super();
|
||||
starter = top;
|
||||
this.environment = environment;
|
||||
this.environment = (Hashtable<?,?>)
|
||||
((environment == null) ? null : environment.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
|
||||
@ -69,6 +69,7 @@ final public class LazySearchEnumerationImpl
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // For Hashtable clone: env.clone()
|
||||
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
|
||||
AttrFilter filter, SearchControls cons,
|
||||
Context ctx, Hashtable<String, Object> env, boolean useFactory)
|
||||
@ -76,7 +77,8 @@ final public class LazySearchEnumerationImpl
|
||||
|
||||
this.candidates = candidates;
|
||||
this.filter = filter;
|
||||
this.env = env;
|
||||
this.env = (Hashtable<String, Object>)
|
||||
((env == null) ? null : env.clone());
|
||||
this.context = ctx;
|
||||
this.useFactory = useFactory;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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
|
||||
@ -53,7 +53,8 @@ abstract public class GenericURLContext implements Context {
|
||||
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
|
||||
public GenericURLContext(Hashtable<?,?> env) {
|
||||
// context that is not tied to any specific URL
|
||||
myEnv = (Hashtable<String, Object>)env; // copied on write
|
||||
myEnv =
|
||||
(Hashtable<String, Object>)(env == null ? null : env.clone());
|
||||
}
|
||||
|
||||
public void close() throws NamingException {
|
||||
@ -488,22 +489,19 @@ abstract public class GenericURLContext implements Context {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // clone()
|
||||
public Object removeFromEnvironment(String propName)
|
||||
throws NamingException {
|
||||
if (myEnv == null) {
|
||||
return null;
|
||||
}
|
||||
myEnv = (Hashtable<String, Object>)myEnv.clone();
|
||||
return myEnv.remove(propName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // clone()
|
||||
public Object addToEnvironment(String propName, Object propVal)
|
||||
throws NamingException {
|
||||
myEnv = (myEnv == null)
|
||||
? new Hashtable<String, Object>(11, 0.75f)
|
||||
: (Hashtable<String, Object>)myEnv.clone();
|
||||
if (myEnv == null) {
|
||||
myEnv = new Hashtable<String, Object>(11, 0.75f);
|
||||
}
|
||||
return myEnv.put(propName, propVal);
|
||||
}
|
||||
|
||||
|
||||
@ -240,13 +240,15 @@ class FileInputStream extends InputStream
|
||||
*
|
||||
* <p>The <code>skip</code> method may, for a variety of
|
||||
* reasons, end up skipping over some smaller number of bytes,
|
||||
* possibly <code>0</code>. If <code>n</code> is negative, an
|
||||
* <code>IOException</code> is thrown, even though the <code>skip</code>
|
||||
* method of the {@link InputStream} superclass does nothing in this case.
|
||||
* The actual number of bytes skipped is returned.
|
||||
* possibly <code>0</code>. If <code>n</code> is negative, the method
|
||||
* will try to skip backwards. In case the backing file does not support
|
||||
* backward skip at its current position, an <code>IOException</code> is
|
||||
* thrown. The actual number of bytes skipped is returned. If it skips
|
||||
* forwards, it returns a positive value. If it skips backwards, it
|
||||
* returns a negative value.
|
||||
*
|
||||
* <p>This method may skip more bytes than are remaining in the backing
|
||||
* file. This produces no exception and the number of bytes skipped
|
||||
* <p>This method may skip more bytes than what are remaining in the
|
||||
* backing file. This produces no exception and the number of bytes skipped
|
||||
* may include some number of bytes that were beyond the EOF of the
|
||||
* backing file. Attempting to read from the stream after skipping past
|
||||
* the end will result in -1 indicating the end of the file.
|
||||
@ -261,9 +263,10 @@ class FileInputStream extends InputStream
|
||||
/**
|
||||
* Returns an estimate of the number of remaining bytes that can be read (or
|
||||
* skipped over) from this input stream without blocking by the next
|
||||
* invocation of a method for this input stream. The next invocation might be
|
||||
* the same thread or another thread. A single read or skip of this
|
||||
* many bytes will not block, but may read or skip fewer bytes.
|
||||
* invocation of a method for this input stream. Returns 0 when the file
|
||||
* position is beyond EOF. The next invocation might be the same thread
|
||||
* or another thread. A single read or skip of this many bytes will not
|
||||
* block, but may read or skip fewer bytes.
|
||||
*
|
||||
* <p> In some cases, a non-blocking read (or skip) may appear to be
|
||||
* blocked when it is merely slow, for example when reading large
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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
|
||||
@ -193,8 +193,10 @@ public abstract class InputStream implements Closeable {
|
||||
* up skipping over some smaller number of bytes, possibly <code>0</code>.
|
||||
* This may result from any of a number of conditions; reaching end of file
|
||||
* before <code>n</code> bytes have been skipped is only one possibility.
|
||||
* The actual number of bytes skipped is returned. If <code>n</code> is
|
||||
* negative, no bytes are skipped.
|
||||
* The actual number of bytes skipped is returned. If {@code n} is
|
||||
* negative, the {@code skip} method for class {@code InputStream} always
|
||||
* returns 0, and no bytes are skipped. Subclasses may handle the negative
|
||||
* value differently.
|
||||
*
|
||||
* <p> The <code>skip</code> method of this class creates a
|
||||
* byte array and then repeatedly reads into it until <code>n</code> bytes
|
||||
|
||||
@ -28,6 +28,7 @@ package java.lang;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.GenericDeclaration;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Executable;
|
||||
@ -115,9 +116,9 @@ import sun.reflect.misc.ReflectUtil;
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public final class Class<T> implements java.io.Serializable,
|
||||
java.lang.reflect.GenericDeclaration,
|
||||
java.lang.reflect.Type,
|
||||
java.lang.reflect.AnnotatedElement {
|
||||
GenericDeclaration,
|
||||
Type,
|
||||
AnnotatedElement {
|
||||
private static final int ANNOTATION= 0x00002000;
|
||||
private static final int ENUM = 0x00004000;
|
||||
private static final int SYNTHETIC = 0x00001000;
|
||||
@ -3182,7 +3183,7 @@ public final class Class<T> implements java.io.Serializable,
|
||||
*/
|
||||
@Override
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||
return AnnotatedElement.super.isAnnotationPresent(annotationClass);
|
||||
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1010,13 +1010,14 @@ public final class String
|
||||
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
|
||||
char v1[] = value;
|
||||
char v2[] = sb.getValue();
|
||||
int i = 0;
|
||||
int n = value.length;
|
||||
while (n-- != 0) {
|
||||
int n = v1.length;
|
||||
if (n != sb.length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (v1[i] != v2[i]) {
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1038,8 +1039,6 @@ public final class String
|
||||
* @since 1.5
|
||||
*/
|
||||
public boolean contentEquals(CharSequence cs) {
|
||||
if (value.length != cs.length())
|
||||
return false;
|
||||
// Argument is a StringBuffer, StringBuilder
|
||||
if (cs instanceof AbstractStringBuilder) {
|
||||
if (cs instanceof StringBuffer) {
|
||||
@ -1055,12 +1054,14 @@ public final class String
|
||||
return true;
|
||||
// Argument is a generic CharSequence
|
||||
char v1[] = value;
|
||||
int i = 0;
|
||||
int n = value.length;
|
||||
while (n-- != 0) {
|
||||
if (v1[i] != cs.charAt(i))
|
||||
int n = v1.length;
|
||||
if (n != cs.length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (v1[i] != cs.charAt(i)) {
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -335,10 +335,8 @@ import java.util.Arrays;
|
||||
* @since 1.5
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer append(CharSequence s) {
|
||||
// Note, synchronization achieved via invocations of other StringBuffer methods after
|
||||
// narrowing of s to specific type
|
||||
// Ditto for toStringCache clearing
|
||||
public synchronized StringBuffer append(CharSequence s) {
|
||||
toStringCache = null;
|
||||
super.append(s);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -145,10 +145,10 @@ class Thread implements Runnable {
|
||||
registerNatives();
|
||||
}
|
||||
|
||||
private char name[];
|
||||
private int priority;
|
||||
private Thread threadQ;
|
||||
private long eetop;
|
||||
private volatile char name[];
|
||||
private int priority;
|
||||
private Thread threadQ;
|
||||
private long eetop;
|
||||
|
||||
/* Whether or not to single_step this thread. */
|
||||
private boolean single_step;
|
||||
@ -1135,7 +1135,7 @@ class Thread implements Runnable {
|
||||
* @see #getName
|
||||
* @see #checkAccess()
|
||||
*/
|
||||
public final void setName(String name) {
|
||||
public final synchronized void setName(String name) {
|
||||
checkAccess();
|
||||
this.name = name.toCharArray();
|
||||
if (threadStatus != 0) {
|
||||
@ -1150,7 +1150,7 @@ class Thread implements Runnable {
|
||||
* @see #setName(String)
|
||||
*/
|
||||
public final String getName() {
|
||||
return String.valueOf(name);
|
||||
return new String(name, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
|
||||
@ -138,8 +138,23 @@ public abstract class Reference<T> {
|
||||
pending = r.discovered;
|
||||
r.discovered = null;
|
||||
} else {
|
||||
// The waiting on the lock may cause an OOME because it may try to allocate
|
||||
// exception objects, so also catch OOME here to avoid silent exit of the
|
||||
// reference handler thread.
|
||||
//
|
||||
// Explicitly define the order of the two exceptions we catch here
|
||||
// when waiting for the lock.
|
||||
//
|
||||
// We do not want to try to potentially load the InterruptedException class
|
||||
// (which would be done if this was its first use, and InterruptedException
|
||||
// were checked first) in this situation.
|
||||
//
|
||||
// This may lead to the VM not ever trying to load the InterruptedException
|
||||
// class again.
|
||||
try {
|
||||
lock.wait();
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (OutOfMemoryError x) { }
|
||||
} catch (InterruptedException x) { }
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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
|
||||
@ -30,7 +30,7 @@ package java.lang.reflect;
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface GenericDeclaration {
|
||||
public interface GenericDeclaration extends AnnotatedElement {
|
||||
/**
|
||||
* Returns an array of {@code TypeVariable} objects that
|
||||
* represent the type variables declared by the generic
|
||||
|
||||
@ -34,6 +34,7 @@ import java.nio.BufferOverflowException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.charset.CoderMalfunctionError; // javadoc
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
@ -244,7 +245,12 @@ public abstract class Charset$Coder$ {
|
||||
* which is never <tt>null</tt> and is never empty
|
||||
*/
|
||||
public final $replType$ replacement() {
|
||||
#if[decoder]
|
||||
return replacement;
|
||||
#end[decoder]
|
||||
#if[encoder]
|
||||
return Arrays.copyOf(replacement, replacement.$replLength$);
|
||||
#end[encoder]
|
||||
}
|
||||
|
||||
/**
|
||||
@ -280,12 +286,15 @@ public abstract class Charset$Coder$ {
|
||||
throw new IllegalArgumentException("Empty replacement");
|
||||
if (len > max$ItypesPerOtype$)
|
||||
throw new IllegalArgumentException("Replacement too long");
|
||||
#if[decoder]
|
||||
this.replacement = newReplacement;
|
||||
#end[decoder]
|
||||
#if[encoder]
|
||||
if (!isLegalReplacement(newReplacement))
|
||||
throw new IllegalArgumentException("Illegal replacement");
|
||||
this.replacement = Arrays.copyOf(newReplacement, newReplacement.$replLength$);
|
||||
#end[encoder]
|
||||
this.replacement = newReplacement;
|
||||
implReplaceWith(newReplacement);
|
||||
implReplaceWith(this.replacement);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
124
jdk/src/share/classes/java/nio/file/FileTreeIterator.java
Normal file
124
jdk/src/share/classes/java/nio/file/FileTreeIterator.java
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.nio.file;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.nio.file.FileTreeWalker.Event;
|
||||
|
||||
/**
|
||||
* An {@code Iterator to iterate over the nodes of a file tree.
|
||||
*
|
||||
* <pre>{@code
|
||||
* try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
|
||||
* while (iterator.hasNext()) {
|
||||
* Event ev = iterator.next();
|
||||
* Path path = ev.file();
|
||||
* BasicFileAttributes attrs = ev.attributes();
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
|
||||
class FileTreeIterator implements Iterator<Event>, Closeable {
|
||||
private final FileTreeWalker walker;
|
||||
private Event next;
|
||||
|
||||
/**
|
||||
* Creates a new iterator to walk the file tree starting at the given file.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code maxDepth} is negative
|
||||
* @throws IOException
|
||||
* if an I/O errors occurs opening the starting file
|
||||
* @throws SecurityException
|
||||
* if the security manager denies access to the starting file
|
||||
* @throws NullPointerException
|
||||
* if {@code start} or {@code options} is {@ocde null} or
|
||||
* the options array contains a {@code null} element
|
||||
*/
|
||||
FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
|
||||
throws IOException
|
||||
{
|
||||
this.walker = new FileTreeWalker(Arrays.asList(options), maxDepth);
|
||||
this.next = walker.walk(start);
|
||||
assert next.type() == FileTreeWalker.EventType.ENTRY ||
|
||||
next.type() == FileTreeWalker.EventType.START_DIRECTORY;
|
||||
|
||||
// IOException if there a problem accessing the starting file
|
||||
IOException ioe = next.ioeException();
|
||||
if (ioe != null)
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
private void fetchNextIfNeeded() {
|
||||
if (next == null) {
|
||||
FileTreeWalker.Event ev = walker.next();
|
||||
while (ev != null) {
|
||||
IOException ioe = ev.ioeException();
|
||||
if (ioe != null)
|
||||
throw new UncheckedIOException(ioe);
|
||||
|
||||
// END_DIRECTORY events are ignored
|
||||
if (ev.type() != FileTreeWalker.EventType.END_DIRECTORY) {
|
||||
next = ev;
|
||||
return;
|
||||
}
|
||||
ev = walker.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (!walker.isOpen())
|
||||
throw new IllegalStateException();
|
||||
fetchNextIfNeeded();
|
||||
return next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event next() {
|
||||
if (!walker.isOpen())
|
||||
throw new IllegalStateException();
|
||||
fetchNextIfNeeded();
|
||||
if (next == null)
|
||||
throw new NoSuchElementException();
|
||||
Event result = next;
|
||||
next = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
walker.close();
|
||||
}
|
||||
}
|
||||
@ -29,8 +29,8 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import sun.nio.fs.BasicFileAttributesHolder;
|
||||
|
||||
/**
|
||||
@ -164,8 +164,17 @@ class FileTreeWalker implements Closeable {
|
||||
|
||||
/**
|
||||
* Creates a {@code FileTreeWalker}.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code maxDepth} is negative
|
||||
* @throws ClassCastException
|
||||
* if (@code options} contains an element that is not a
|
||||
* {@code FileVisitOption}
|
||||
* @throws NullPointerException
|
||||
* if {@code options} is {@ocde null} or the options
|
||||
* array contains a {@code null} element
|
||||
*/
|
||||
FileTreeWalker(Set<FileVisitOption> options, int maxDepth) {
|
||||
FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
|
||||
boolean fl = false;
|
||||
for (FileVisitOption option: options) {
|
||||
// will throw NPE if options contains null
|
||||
@ -175,6 +184,9 @@ class FileTreeWalker implements Closeable {
|
||||
throw new AssertionError("Should not get here");
|
||||
}
|
||||
}
|
||||
if (maxDepth < 0)
|
||||
throw new IllegalArgumentException("'maxDepth' is negative");
|
||||
|
||||
this.followLinks = fl;
|
||||
this.linkOptions = (fl) ? new LinkOption[0] :
|
||||
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
|
||||
|
||||
@ -25,10 +25,13 @@
|
||||
|
||||
package java.nio.file;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.nio.file.spi.FileTypeDetector;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.io.Closeable;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
@ -38,7 +41,13 @@ import java.io.BufferedWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.CloseableStream;
|
||||
import java.util.stream.DelegatingStream;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.nio.charset.Charset;
|
||||
@ -2587,9 +2596,6 @@ public final class Files {
|
||||
FileVisitor<? super Path> visitor)
|
||||
throws IOException
|
||||
{
|
||||
if (maxDepth < 0)
|
||||
throw new IllegalArgumentException("'maxDepth' is negative");
|
||||
|
||||
/**
|
||||
* Create a FileTreeWalker to walk the file tree, invoking the visitor
|
||||
* for each event.
|
||||
@ -2940,40 +2946,6 @@ public final class Files {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the bytes from an input stream. The {@code initialSize}
|
||||
* parameter indicates the initial size of the byte[] to allocate.
|
||||
*/
|
||||
private static byte[] read(InputStream source, int initialSize)
|
||||
throws IOException
|
||||
{
|
||||
int capacity = initialSize;
|
||||
byte[] buf = new byte[capacity];
|
||||
int nread = 0;
|
||||
int rem = buf.length;
|
||||
int n;
|
||||
// read to EOF which may read more or less than initialSize (eg: file
|
||||
// is truncated while we are reading)
|
||||
while ((n = source.read(buf, nread, rem)) > 0) {
|
||||
nread += n;
|
||||
rem -= n;
|
||||
assert rem >= 0;
|
||||
if (rem == 0) {
|
||||
// need larger buffer
|
||||
int newCapacity = capacity << 1;
|
||||
if (newCapacity < 0) {
|
||||
if (capacity == Integer.MAX_VALUE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
newCapacity = Integer.MAX_VALUE;
|
||||
}
|
||||
rem = newCapacity - capacity;
|
||||
buf = Arrays.copyOf(buf, newCapacity);
|
||||
capacity = newCapacity;
|
||||
}
|
||||
}
|
||||
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all the bytes from a file. The method ensures that the file is
|
||||
* closed when all bytes have been read or an I/O error, or other runtime
|
||||
@ -2999,12 +2971,22 @@ public final class Files {
|
||||
* method is invoked to check read access to the file.
|
||||
*/
|
||||
public static byte[] readAllBytes(Path path) throws IOException {
|
||||
long size = size(path);
|
||||
if (size > (long)Integer.MAX_VALUE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
try (FileChannel fc = FileChannel.open(path)) {
|
||||
long size = fc.size();
|
||||
if (size > (long)Integer.MAX_VALUE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
|
||||
try (InputStream in = newInputStream(path)) {
|
||||
return read(in, (int)size);
|
||||
byte[] arr = new byte[(int)size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(arr);
|
||||
while (bb.hasRemaining()) {
|
||||
if (fc.read(bb) < 0) {
|
||||
// truncated
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int nread = bb.position();
|
||||
return (nread == size) ? arr : Arrays.copyOf(arr, nread);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3177,4 +3159,336 @@ public final class Files {
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// -- Stream APIs --
|
||||
|
||||
/**
|
||||
* Implementation of CloseableStream
|
||||
*/
|
||||
private static class DelegatingCloseableStream<T> extends DelegatingStream<T>
|
||||
implements CloseableStream<T>
|
||||
{
|
||||
private final Closeable closeable;
|
||||
|
||||
DelegatingCloseableStream(Closeable c, Stream<T> delegate) {
|
||||
super(delegate);
|
||||
this.closeable = c;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
closeable.close();
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a lazily populated {@code CloseableStream}, the elements of
|
||||
* which are the entries in the directory. The listing is not recursive.
|
||||
*
|
||||
* <p> The elements of the stream are {@link Path} objects that are
|
||||
* obtained as if by {@link Path#resolve(Path) resolving} the name of the
|
||||
* directory entry against {@code dir}. Some file systems maintain special
|
||||
* links to the directory itself and the directory's parent directory.
|
||||
* Entries representing these links are not included.
|
||||
*
|
||||
* <p> The stream is <i>weakly consistent</i>. It is thread safe but does
|
||||
* not freeze the directory while iterating, so it may (or may not)
|
||||
* reflect updates to the directory that occur after returning from this
|
||||
* method.
|
||||
*
|
||||
* <p> When not using the try-with-resources construct, then the stream's
|
||||
* {@link CloseableStream#close close} method should be invoked after the
|
||||
* operation is completed so as to free any resources held for the open
|
||||
* directory. Operating on a closed stream behaves as if the end of stream
|
||||
* has been reached. Due to read-ahead, one or more elements may be
|
||||
* returned after the stream has been closed.
|
||||
*
|
||||
* <p> If an {@link IOException} is thrown when accessing the directory
|
||||
* after this method has returned, it is wrapped in an {@link
|
||||
* UncheckedIOException} which will be thrown from the method that caused
|
||||
* the access to take place.
|
||||
*
|
||||
* @param dir The path to the directory
|
||||
*
|
||||
* @return The {@code CloseableStream} describing the content of the
|
||||
* directory
|
||||
*
|
||||
* @throws NotDirectoryException
|
||||
* if the file could not otherwise be opened because it is not
|
||||
* a directory <i>(optional specific exception)</i>
|
||||
* @throws IOException
|
||||
* if an I/O error occurs when opening the directory
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the directory.
|
||||
*
|
||||
* @see #newDirectoryStream(Path)
|
||||
* @since 1.8
|
||||
*/
|
||||
public static CloseableStream<Path> list(Path dir) throws IOException {
|
||||
DirectoryStream<Path> ds = Files.newDirectoryStream(dir);
|
||||
final Iterator<Path> delegate = ds.iterator();
|
||||
|
||||
// Re-wrap DirectoryIteratorException to UncheckedIOException
|
||||
Iterator<Path> it = new Iterator<Path>() {
|
||||
public boolean hasNext() {
|
||||
try {
|
||||
return delegate.hasNext();
|
||||
} catch (DirectoryIteratorException e) {
|
||||
throw new UncheckedIOException(e.getCause());
|
||||
}
|
||||
}
|
||||
public Path next() {
|
||||
try {
|
||||
return delegate.next();
|
||||
} catch (DirectoryIteratorException e) {
|
||||
throw new UncheckedIOException(e.getCause());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return new DelegatingCloseableStream<>(ds,
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(it,
|
||||
Spliterator.DISTINCT)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@code CloseableStream} that is lazily populated with {@code
|
||||
* Path} by walking the file tree rooted at a given starting file. The
|
||||
* file tree is traversed <em>depth-first</em>, the elements in the stream
|
||||
* are {@link Path} objects that are obtained as if by {@link
|
||||
* Path#resolve(Path) resolving} the relative path against {@code start}.
|
||||
*
|
||||
* <p> The {@code stream} walks the file tree as elements are consumed.
|
||||
* The {@code CloseableStream} returned is guaranteed to have at least one
|
||||
* element, the starting file itself. For each file visited, the stream
|
||||
* attempts to read its {@link BasicFileAttributes}. If the file is a
|
||||
* directory and can be opened successfully, entries in the directory, and
|
||||
* their <em>descendants</em> will follow the directory in the stream as
|
||||
* they are encountered. When all entries have been visited, then the
|
||||
* directory is closed. The file tree walk then continues at the next
|
||||
* <em>sibling</em> of the directory.
|
||||
*
|
||||
* <p> The stream is <i>weakly consistent</i>. It does not freeze the
|
||||
* file tree while iterating, so it may (or may not) reflect updates to
|
||||
* the file tree that occur after returned from this method.
|
||||
*
|
||||
* <p> By default, symbolic links are not automatically followed by this
|
||||
* method. If the {@code options} parameter contains the {@link
|
||||
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then symbolic links are
|
||||
* followed. When following links, and the attributes of the target cannot
|
||||
* be read, then this method attempts to get the {@code BasicFileAttributes}
|
||||
* of the link.
|
||||
*
|
||||
* <p> If the {@code options} parameter contains the {@link
|
||||
* FileVisitOption#FOLLOW_LINKS FOLLOW_LINKS} option then the stream keeps
|
||||
* track of directories visited so that cycles can be detected. A cycle
|
||||
* arises when there is an entry in a directory that is an ancestor of the
|
||||
* directory. Cycle detection is done by recording the {@link
|
||||
* java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories,
|
||||
* or if file keys are not available, by invoking the {@link #isSameFile
|
||||
* isSameFile} method to test if a directory is the same file as an
|
||||
* ancestor. When a cycle is detected it is treated as an I/O error with
|
||||
* an instance of {@link FileSystemLoopException}.
|
||||
*
|
||||
* <p> The {@code maxDepth} parameter is the maximum number of levels of
|
||||
* directories to visit. A value of {@code 0} means that only the starting
|
||||
* file is visited, unless denied by the security manager. A value of
|
||||
* {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all
|
||||
* levels should be visited.
|
||||
*
|
||||
* <p> When a security manager is installed and it denies access to a file
|
||||
* (or directory), then it is ignored and not included in the stream.
|
||||
*
|
||||
* <p> When not using the try-with-resources construct, then the stream's
|
||||
* {@link CloseableStream#close close} method should be invoked after the
|
||||
* operation is completed so as to free any resources held for the open
|
||||
* directory. Operate the stream after it is closed will throw an
|
||||
* {@link java.lang.IllegalStateException}.
|
||||
*
|
||||
* <p> If an {@link IOException} is thrown when accessing the directory
|
||||
* after this method has returned, it is wrapped in an {@link
|
||||
* UncheckedIOException} which will be thrown from the method that caused
|
||||
* the access to take place.
|
||||
*
|
||||
* @param start
|
||||
* the starting file
|
||||
* @param maxDepth
|
||||
* the maximum number of directory levels to visit
|
||||
* @param options
|
||||
* options to configure the traversal
|
||||
*
|
||||
* @return the {@link CloseableStream} of {@link Path}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code maxDepth} parameter is negative
|
||||
* @throws SecurityException
|
||||
* If the security manager denies access to the starting file.
|
||||
* In the case of the default provider, the {@link
|
||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
||||
* to check read access to the directory.
|
||||
* @throws IOException
|
||||
* if an I/O error is thrown when accessing the starting file.
|
||||
* @since 1.8
|
||||
*/
|
||||
public static CloseableStream<Path> walk(Path start, int maxDepth,
|
||||
FileVisitOption... options)
|
||||
throws IOException
|
||||
{
|
||||
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
|
||||
return new DelegatingCloseableStream<>(iterator,
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
|
||||
.map(entry -> entry.file()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@code CloseableStream} that is lazily populated with {@code
|
||||
* Path} by walking the file tree rooted at a given starting file. The
|
||||
* file tree is traversed <em>depth-first</em>, the elements in the stream
|
||||
* are {@link Path} objects that are obtained as if by {@link
|
||||
* Path#resolve(Path) resolving} the relative path against {@code start}.
|
||||
*
|
||||
* <p> This method works as if invoking it were equivalent to evaluating the
|
||||
* expression:
|
||||
* <blockquote><pre>
|
||||
* walk(start, Integer.MAX_VALUE, options)
|
||||
* </pre></blockquote>
|
||||
* In other words, it visits all levels of the file tree.
|
||||
*
|
||||
* @param start
|
||||
* the starting file
|
||||
* @param options
|
||||
* options to configure the traversal
|
||||
*
|
||||
* @return the {@link CloseableStream} of {@link Path}
|
||||
*
|
||||
* @throws SecurityException
|
||||
* If the security manager denies access to the starting file.
|
||||
* In the case of the default provider, the {@link
|
||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
||||
* to check read access to the directory.
|
||||
* @throws IOException
|
||||
* if an I/O error is thrown when accessing the starting file.
|
||||
*
|
||||
* @see #walk(Path, int, FileVisitOption...)
|
||||
* @since 1.8
|
||||
*/
|
||||
public static CloseableStream<Path> walk(Path start,
|
||||
FileVisitOption... options)
|
||||
throws IOException
|
||||
{
|
||||
return walk(start, Integer.MAX_VALUE, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@code CloseableStream} that is lazily populated with {@code
|
||||
* Path} by searching for files in a file tree rooted at a given starting
|
||||
* file.
|
||||
*
|
||||
* <p> This method walks the file tree in exactly the manner specified by
|
||||
* the {@link #walk walk} method. For each file encountered, the given
|
||||
* {@link BiPredicate} is invoked with its {@link Path} and {@link
|
||||
* BasicFileAttributes}. The {@code Path} object is obtained as if by
|
||||
* {@link Path#resolve(Path) resolving} the relative path against {@code
|
||||
* start} and is only included in the returned {@link CloseableStream} if
|
||||
* the {@code BiPredicate} returns true. Compare to calling {@link
|
||||
* java.util.stream.Stream#filter filter} on the {@code Stream}
|
||||
* returned by {@code walk} method, this method may be more efficient by
|
||||
* avoiding redundant retrieval of the {@code BasicFileAttributes}.
|
||||
*
|
||||
* <p> If an {@link IOException} is thrown when accessing the directory
|
||||
* after returned from this method, it is wrapped in an {@link
|
||||
* UncheckedIOException} which will be thrown from the method that caused
|
||||
* the access to take place.
|
||||
*
|
||||
* @param start
|
||||
* the starting file
|
||||
* @param maxDepth
|
||||
* the maximum number of directory levels to search
|
||||
* @param matcher
|
||||
* the function used to decide whether a file should be included
|
||||
* in the returned stream
|
||||
* @param options
|
||||
* options to configure the traversal
|
||||
*
|
||||
* @return the {@link CloseableStream} of {@link Path}
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* if the {@code maxDepth} parameter is negative
|
||||
* @throws SecurityException
|
||||
* If the security manager denies access to the starting file.
|
||||
* In the case of the default provider, the {@link
|
||||
* SecurityManager#checkRead(String) checkRead} method is invoked
|
||||
* to check read access to the directory.
|
||||
* @throws IOException
|
||||
* if an I/O error is thrown when accessing the starting file.
|
||||
*
|
||||
* @see #walk(Path, int, FileVisitOption...)
|
||||
* @since 1.8
|
||||
*/
|
||||
public static CloseableStream<Path> find(Path start,
|
||||
int maxDepth,
|
||||
BiPredicate<Path, BasicFileAttributes> matcher,
|
||||
FileVisitOption... options)
|
||||
throws IOException
|
||||
{
|
||||
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
|
||||
return new DelegatingCloseableStream<>(iterator,
|
||||
StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT))
|
||||
.filter(entry -> matcher.test(entry.file(), entry.attributes()))
|
||||
.map(entry -> entry.file()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all lines from a file as a {@code CloseableStream}. Unlike {@link
|
||||
* #readAllLines(Path, Charset) readAllLines}, this method does not read
|
||||
* all lines into a {@code List}, but instead populates lazily as the stream
|
||||
* is consumed.
|
||||
*
|
||||
* <p> Bytes from the file are decoded into characters using the specified
|
||||
* charset and the same line terminators as specified by {@code
|
||||
* readAllLines} are supported.
|
||||
*
|
||||
* <p> After this method returns, then any subsequent I/O exception that
|
||||
* occurs while reading from the file or when a malformed or unmappable byte
|
||||
* sequence is read, is wrapped in an {@link UncheckedIOException} that will
|
||||
* be thrown form the
|
||||
* {@link java.util.stream.Stream} method that caused the read to take
|
||||
* place. In case an {@code IOException} is thrown when closing the file,
|
||||
* it is also wrapped as an {@code UncheckedIOException}.
|
||||
*
|
||||
* <p> When not using the try-with-resources construct, then stream's
|
||||
* {@link CloseableStream#close close} method should be invoked after
|
||||
* operation is completed so as to free any resources held for the open
|
||||
* file.
|
||||
*
|
||||
* @param path
|
||||
* the path to the file
|
||||
* @param cs
|
||||
* the charset to use for decoding
|
||||
*
|
||||
* @return the lines from the file as a {@code CloseableStream}
|
||||
*
|
||||
* @throws IOException
|
||||
* if an I/O error occurs opening the file
|
||||
* @throws SecurityException
|
||||
* In the case of the default provider, and a security manager is
|
||||
* installed, the {@link SecurityManager#checkRead(String) checkRead}
|
||||
* method is invoked to check read access to the file.
|
||||
*
|
||||
* @see #readAllLines(Path, Charset)
|
||||
* @see #newBufferedReader(Path, Charset)
|
||||
* @see java.io.BufferedReader#lines()
|
||||
* @since 1.8
|
||||
*/
|
||||
public static CloseableStream<String> lines(Path path, Charset cs)
|
||||
throws IOException
|
||||
{
|
||||
BufferedReader br = Files.newBufferedReader(path, cs);
|
||||
return new DelegatingCloseableStream<>(br, br.lines());
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
* <code>DateFormatSymbols</code> is a public class for encapsulating
|
||||
* localizable date-time formatting data, such as the names of the
|
||||
* months, the names of the days of the week, and the time zone data.
|
||||
* <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
|
||||
* <code>SimpleDateFormat</code> uses
|
||||
* <code>DateFormatSymbols</code> to encapsulate this information.
|
||||
*
|
||||
* <p>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -86,9 +86,13 @@ class ComparableTimSort {
|
||||
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
|
||||
|
||||
/**
|
||||
* Temp storage for merges.
|
||||
* Temp storage for merges. A workspace array may optionally be
|
||||
* provided in constructor, and if so will be used as long as it
|
||||
* is big enough.
|
||||
*/
|
||||
private Object[] tmp;
|
||||
private int tmpBase; // base of tmp array slice
|
||||
private int tmpLen; // length of tmp array slice
|
||||
|
||||
/**
|
||||
* A stack of pending runs yet to be merged. Run i starts at
|
||||
@ -108,15 +112,27 @@ class ComparableTimSort {
|
||||
* Creates a TimSort instance to maintain the state of an ongoing sort.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private ComparableTimSort(Object[] a) {
|
||||
private ComparableTimSort(Object[] a, Object[] work, int workBase, int workLen) {
|
||||
this.a = a;
|
||||
|
||||
// Allocate temp storage (which may be increased later if necessary)
|
||||
int len = a.length;
|
||||
Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
|
||||
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
|
||||
tmp = newArray;
|
||||
int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
|
||||
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
|
||||
if (work == null || workLen < tlen || workBase + tlen > work.length) {
|
||||
tmp = new Object[tlen];
|
||||
tmpBase = 0;
|
||||
tmpLen = tlen;
|
||||
}
|
||||
else {
|
||||
tmp = work;
|
||||
tmpBase = workBase;
|
||||
tmpLen = workLen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate runs-to-be-merged stack (which cannot be expanded). The
|
||||
@ -136,17 +152,28 @@ class ComparableTimSort {
|
||||
}
|
||||
|
||||
/*
|
||||
* The next two methods (which are package private and static) constitute
|
||||
* the entire API of this class. Each of these methods obeys the contract
|
||||
* of the public method with the same signature in java.util.Arrays.
|
||||
* The next method (package private and static) constitutes the
|
||||
* entire API of this class.
|
||||
*/
|
||||
|
||||
static void sort(Object[] a) {
|
||||
sort(a, 0, a.length);
|
||||
}
|
||||
/**
|
||||
* Sorts the given range, using the given workspace array slice
|
||||
* for temp storage when possible. This method is designed to be
|
||||
* invoked from public methods (in class Arrays) after performing
|
||||
* any necessary array bounds checks and expanding parameters into
|
||||
* the required forms.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param lo the index of the first element, inclusive, to be sorted
|
||||
* @param hi the index of the last element, exclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
* @since 1.8
|
||||
*/
|
||||
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
|
||||
assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
|
||||
|
||||
static void sort(Object[] a, int lo, int hi) {
|
||||
rangeCheck(a.length, lo, hi);
|
||||
int nRemaining = hi - lo;
|
||||
if (nRemaining < 2)
|
||||
return; // Arrays of size 0 and 1 are always sorted
|
||||
@ -163,7 +190,7 @@ class ComparableTimSort {
|
||||
* extending short natural runs to minRun elements, and merging runs
|
||||
* to maintain stack invariant.
|
||||
*/
|
||||
ComparableTimSort ts = new ComparableTimSort(a);
|
||||
ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
|
||||
int minRun = minRunLength(nRemaining);
|
||||
do {
|
||||
// Identify next run
|
||||
@ -619,11 +646,11 @@ class ComparableTimSort {
|
||||
// Copy first run into temp array
|
||||
Object[] a = this.a; // For performance
|
||||
Object[] tmp = ensureCapacity(len1);
|
||||
System.arraycopy(a, base1, tmp, 0, len1);
|
||||
|
||||
int cursor1 = 0; // Indexes into tmp array
|
||||
int cursor1 = tmpBase; // Indexes into tmp array
|
||||
int cursor2 = base2; // Indexes int a
|
||||
int dest = base1; // Indexes int a
|
||||
System.arraycopy(a, base1, tmp, cursor1, len1);
|
||||
|
||||
// Move first element of second run and deal with degenerate cases
|
||||
a[dest++] = a[cursor2++];
|
||||
@ -736,16 +763,17 @@ class ComparableTimSort {
|
||||
// Copy second run into temp array
|
||||
Object[] a = this.a; // For performance
|
||||
Object[] tmp = ensureCapacity(len2);
|
||||
System.arraycopy(a, base2, tmp, 0, len2);
|
||||
int tmpBase = this.tmpBase;
|
||||
System.arraycopy(a, base2, tmp, tmpBase, len2);
|
||||
|
||||
int cursor1 = base1 + len1 - 1; // Indexes into a
|
||||
int cursor2 = len2 - 1; // Indexes into tmp array
|
||||
int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
|
||||
int dest = base2 + len2 - 1; // Indexes into a
|
||||
|
||||
// Move last element of first run and deal with degenerate cases
|
||||
a[dest--] = a[cursor1--];
|
||||
if (--len1 == 0) {
|
||||
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
|
||||
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
|
||||
return;
|
||||
}
|
||||
if (len2 == 1) {
|
||||
@ -803,7 +831,7 @@ class ComparableTimSort {
|
||||
if (--len2 == 1)
|
||||
break outer;
|
||||
|
||||
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
|
||||
count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, tmpBase, len2, len2 - 1);
|
||||
if (count2 != 0) {
|
||||
dest -= count2;
|
||||
cursor2 -= count2;
|
||||
@ -835,7 +863,7 @@ class ComparableTimSort {
|
||||
} else {
|
||||
assert len1 == 0;
|
||||
assert len2 > 0;
|
||||
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
|
||||
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,7 +876,7 @@ class ComparableTimSort {
|
||||
* @return tmp, whether or not it grew
|
||||
*/
|
||||
private Object[] ensureCapacity(int minCapacity) {
|
||||
if (tmp.length < minCapacity) {
|
||||
if (tmpLen < minCapacity) {
|
||||
// Compute smallest power of 2 > minCapacity
|
||||
int newSize = minCapacity;
|
||||
newSize |= newSize >> 1;
|
||||
@ -863,30 +891,13 @@ class ComparableTimSort {
|
||||
else
|
||||
newSize = Math.min(newSize, a.length >>> 1);
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
|
||||
Object[] newArray = new Object[newSize];
|
||||
tmp = newArray;
|
||||
tmpLen = newSize;
|
||||
tmpBase = 0;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that fromIndex and toIndex are in range, and throws an
|
||||
* appropriate exception if they aren't.
|
||||
*
|
||||
* @param arrayLen the length of the array
|
||||
* @param fromIndex the index of the first element of the range
|
||||
* @param toIndex the index after the last element of the range
|
||||
* @throws IllegalArgumentException if fromIndex > toIndex
|
||||
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0
|
||||
* or toIndex > arrayLen
|
||||
*/
|
||||
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
|
||||
if (fromIndex > toIndex)
|
||||
throw new IllegalArgumentException("fromIndex(" + fromIndex +
|
||||
") > toIndex(" + toIndex+")");
|
||||
if (fromIndex < 0)
|
||||
throw new ArrayIndexOutOfBoundsException(fromIndex);
|
||||
if (toIndex > arrayLen)
|
||||
throw new ArrayIndexOutOfBoundsException(toIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,11 @@ package java.util;
|
||||
* quicksorts to degrade to quadratic performance, and is typically
|
||||
* faster than traditional (one-pivot) Quicksort implementations.
|
||||
*
|
||||
* All exposed methods are package-private, designed to be invoked
|
||||
* from public methods (in class Arrays) after performing any
|
||||
* necessary array bounds checks and expanding parameters into the
|
||||
* required forms.
|
||||
*
|
||||
* @author Vladimir Yaroslavskiy
|
||||
* @author Jon Bentley
|
||||
* @author Josh Bloch
|
||||
@ -89,22 +94,18 @@ final class DualPivotQuicksort {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(int[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(int[] a, int left, int right) {
|
||||
static void sort(int[] a, int left, int right,
|
||||
int[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -147,24 +148,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
int[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
int[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new int[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new int[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new int[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -172,21 +184,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
int[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,22 +542,18 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(long[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(long[] a, int left, int right) {
|
||||
static void sort(long[] a, int left, int right,
|
||||
long[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -587,24 +596,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
long[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
long[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new long[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new long[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new long[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -612,21 +632,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
long[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,22 +990,18 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(short[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(short[] a, int left, int right) {
|
||||
static void sort(short[] a, int left, int right,
|
||||
short[] work, int workBase, int workLen) {
|
||||
// Use counting sort on large arrays
|
||||
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
|
||||
int[] count = new int[NUM_SHORT_VALUES];
|
||||
@ -1002,7 +1019,7 @@ final class DualPivotQuicksort {
|
||||
} while (--s > 0);
|
||||
}
|
||||
} else { // Use Dual-Pivot Quicksort on small arrays
|
||||
doSort(a, left, right);
|
||||
doSort(a, left, right, work, workBase, workLen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1015,8 +1032,12 @@ final class DualPivotQuicksort {
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private static void doSort(short[] a, int left, int right) {
|
||||
private static void doSort(short[] a, int left, int right,
|
||||
short[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -1059,24 +1080,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
short[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
short[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new short[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new short[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new short[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -1084,21 +1116,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
short[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1441,22 +1474,18 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(char[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(char[] a, int left, int right) {
|
||||
static void sort(char[] a, int left, int right,
|
||||
char[] work, int workBase, int workLen) {
|
||||
// Use counting sort on large arrays
|
||||
if (right - left > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
|
||||
int[] count = new int[NUM_CHAR_VALUES];
|
||||
@ -1474,7 +1503,7 @@ final class DualPivotQuicksort {
|
||||
} while (--s > 0);
|
||||
}
|
||||
} else { // Use Dual-Pivot Quicksort on small arrays
|
||||
doSort(a, left, right);
|
||||
doSort(a, left, right, work, workBase, workLen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1487,8 +1516,12 @@ final class DualPivotQuicksort {
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private static void doSort(char[] a, int left, int right) {
|
||||
private static void doSort(char[] a, int left, int right,
|
||||
char[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -1531,24 +1564,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
char[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
char[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new char[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new char[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new char[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -1556,21 +1600,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
char[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1915,15 +1960,6 @@ final class DualPivotQuicksort {
|
||||
/** The number of distinct byte values. */
|
||||
private static final int NUM_BYTE_VALUES = 1 << 8;
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(byte[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
*
|
||||
@ -1931,7 +1967,7 @@ final class DualPivotQuicksort {
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
*/
|
||||
public static void sort(byte[] a, int left, int right) {
|
||||
static void sort(byte[] a, int left, int right) {
|
||||
// Use counting sort on large arrays
|
||||
if (right - left > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
|
||||
int[] count = new int[NUM_BYTE_VALUES];
|
||||
@ -1963,22 +1999,18 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(float[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(float[] a, int left, int right) {
|
||||
static void sort(float[] a, int left, int right,
|
||||
float[] work, int workBase, int workLen) {
|
||||
/*
|
||||
* Phase 1: Move NaNs to the end of the array.
|
||||
*/
|
||||
@ -1997,7 +2029,7 @@ final class DualPivotQuicksort {
|
||||
/*
|
||||
* Phase 2: Sort everything except NaNs (which are already in place).
|
||||
*/
|
||||
doSort(a, left, right);
|
||||
doSort(a, left, right, work, workBase, workLen);
|
||||
|
||||
/*
|
||||
* Phase 3: Place negative zeros before positive zeros.
|
||||
@ -2064,8 +2096,12 @@ final class DualPivotQuicksort {
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private static void doSort(float[] a, int left, int right) {
|
||||
private static void doSort(float[] a, int left, int right,
|
||||
float[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -2108,24 +2144,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
float[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
float[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new float[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new float[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new float[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -2133,21 +2180,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
float[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2490,22 +2538,18 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified array.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
*/
|
||||
public static void sort(double[] a) {
|
||||
sort(a, 0, a.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the specified range of the array.
|
||||
* Sorts the specified range of the array using the given
|
||||
* workspace array slice if possible for merging
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
public static void sort(double[] a, int left, int right) {
|
||||
static void sort(double[] a, int left, int right,
|
||||
double[] work, int workBase, int workLen) {
|
||||
/*
|
||||
* Phase 1: Move NaNs to the end of the array.
|
||||
*/
|
||||
@ -2524,7 +2568,7 @@ final class DualPivotQuicksort {
|
||||
/*
|
||||
* Phase 2: Sort everything except NaNs (which are already in place).
|
||||
*/
|
||||
doSort(a, left, right);
|
||||
doSort(a, left, right, work, workBase, workLen);
|
||||
|
||||
/*
|
||||
* Phase 3: Place negative zeros before positive zeros.
|
||||
@ -2591,8 +2635,12 @@ final class DualPivotQuicksort {
|
||||
* @param a the array to be sorted
|
||||
* @param left the index of the first element, inclusive, to be sorted
|
||||
* @param right the index of the last element, inclusive, to be sorted
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private static void doSort(double[] a, int left, int right) {
|
||||
private static void doSort(double[] a, int left, int right,
|
||||
double[] work, int workBase, int workLen) {
|
||||
// Use Quicksort on small arrays
|
||||
if (right - left < QUICKSORT_THRESHOLD) {
|
||||
sort(a, left, right, true);
|
||||
@ -2635,24 +2683,35 @@ final class DualPivotQuicksort {
|
||||
}
|
||||
|
||||
// Check special cases
|
||||
// Implementation note: variable "right" is increased by 1.
|
||||
if (run[count] == right++) { // The last run contains one element
|
||||
run[++count] = right;
|
||||
} else if (count == 1) { // The array is already sorted
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create temporary array, which is used for merging.
|
||||
* Implementation note: variable "right" is increased by 1.
|
||||
*/
|
||||
double[] b; byte odd = 0;
|
||||
// Determine alternation base for merge
|
||||
byte odd = 0;
|
||||
for (int n = 1; (n <<= 1) < count; odd ^= 1);
|
||||
|
||||
// Use or create temporary array b for merging
|
||||
double[] b; // temp array; alternates with a
|
||||
int ao, bo; // array offsets from 'left'
|
||||
int blen = right - left; // space needed for b
|
||||
if (work == null || workLen < blen || workBase + blen > work.length) {
|
||||
work = new double[blen];
|
||||
workBase = 0;
|
||||
}
|
||||
if (odd == 0) {
|
||||
b = a; a = new double[b.length];
|
||||
for (int i = left - 1; ++i < right; a[i] = b[i]);
|
||||
System.arraycopy(a, left, work, workBase, blen);
|
||||
b = a;
|
||||
bo = 0;
|
||||
a = work;
|
||||
ao = workBase - left;
|
||||
} else {
|
||||
b = new double[a.length];
|
||||
b = work;
|
||||
ao = 0;
|
||||
bo = workBase - left;
|
||||
}
|
||||
|
||||
// Merging
|
||||
@ -2660,21 +2719,22 @@ final class DualPivotQuicksort {
|
||||
for (int k = (last = 0) + 2; k <= count; k += 2) {
|
||||
int hi = run[k], mi = run[k - 1];
|
||||
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
|
||||
if (q >= hi || p < mi && a[p] <= a[q]) {
|
||||
b[i] = a[p++];
|
||||
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
|
||||
b[i + bo] = a[p++ + ao];
|
||||
} else {
|
||||
b[i] = a[q++];
|
||||
b[i + bo] = a[q++ + ao];
|
||||
}
|
||||
}
|
||||
run[++last] = hi;
|
||||
}
|
||||
if ((count & 1) != 0) {
|
||||
for (int i = right, lo = run[count - 1]; --i >= lo;
|
||||
b[i] = a[i]
|
||||
b[i + bo] = a[i + ao]
|
||||
);
|
||||
run[++last] = right;
|
||||
}
|
||||
double[] t = a; a = b; b = t;
|
||||
int o = ao; ao = bo; bo = o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ import sun.util.ResourceBundleEnumeration;
|
||||
*
|
||||
* public class MyResources_fr extends ListResourceBundle {
|
||||
* protected Object[][] getContents() {
|
||||
* return new Object[][] = {
|
||||
* return new Object[][] {
|
||||
* // LOCALIZE THIS
|
||||
* {"s1", "Le disque \"{1}\" {0}."}, // MessageFormat pattern
|
||||
* {"s2", "1"}, // location of {0} in pattern
|
||||
|
||||
@ -124,6 +124,8 @@ public class PropertyResourceBundle extends ResourceBundle {
|
||||
* to read from.
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws NullPointerException if <code>stream</code> is null
|
||||
* @throws IllegalArgumentException if {@code stream} contains a
|
||||
* malformed Unicode escape sequence.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public PropertyResourceBundle (InputStream stream) throws IOException {
|
||||
@ -142,6 +144,8 @@ public class PropertyResourceBundle extends ResourceBundle {
|
||||
* read from.
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws NullPointerException if <code>reader</code> is null
|
||||
* @throws IllegalArgumentException if a malformed Unicode escape sequence appears
|
||||
* from {@code reader}.
|
||||
* @since 1.6
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
|
||||
@ -140,32 +140,32 @@ import java.util.function.LongConsumer;
|
||||
* (in approximate order of decreasing desirability):
|
||||
* <ul>
|
||||
* <li>The source cannot be structurally interfered with.
|
||||
* </br>For example, an instance of
|
||||
* <br>For example, an instance of
|
||||
* {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source.
|
||||
* A Spliterator created from the source reports a characteristic of
|
||||
* {@code IMMUTABLE}.</li>
|
||||
* <li>The source manages concurrent modifications.
|
||||
* </br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
|
||||
* <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap}
|
||||
* is a concurrent source. A Spliterator created from the source reports a
|
||||
* characteristic of {@code CONCURRENT}.</li>
|
||||
* <li>The mutable source provides a late-binding and fail-fast Spliterator.
|
||||
* </br>Late binding narrows the window during which interference can affect
|
||||
* <br>Late binding narrows the window during which interference can affect
|
||||
* the calculation; fail-fast detects, on a best-effort basis, that structural
|
||||
* interference has occurred after traversal has commenced and throws
|
||||
* {@link ConcurrentModificationException}. For example, {@link ArrayList},
|
||||
* and many other non-concurrent {@code Collection} classes in the JDK, provide
|
||||
* a late-binding, fail-fast spliterator.</li>
|
||||
* <li>The mutable source provides a non-late-binding but fail-fast Spliterator.
|
||||
* </br>The source increases the likelihood of throwing
|
||||
* <br>The source increases the likelihood of throwing
|
||||
* {@code ConcurrentModificationException} since the window of potential
|
||||
* interference is larger.</li>
|
||||
* <li>The mutable source provides a late-binding and non-fail-fast Spliterator.
|
||||
* </br>The source risks arbitrary, non-deterministic behavior after traversal
|
||||
* <br>The source risks arbitrary, non-deterministic behavior after traversal
|
||||
* has commenced since interference is not detected.
|
||||
* </li>
|
||||
* <li>The mutable source provides a non-late-binding and non-fail-fast
|
||||
* Spliterator.
|
||||
* </br>The source increases the risk of arbitrary, non-deterministic behavior
|
||||
* <br>The source increases the risk of arbitrary, non-deterministic behavior
|
||||
* since non-detected interference may occur after construction.
|
||||
* </li>
|
||||
* </ul>
|
||||
@ -284,6 +284,8 @@ import java.util.function.LongConsumer;
|
||||
* is set to {@code true} then diagnostic warnings are reported if boxing of
|
||||
* primitive values occur when operating on primitive subtype specializations.
|
||||
*
|
||||
* @param <T> the type of elements returned by this Spliterator
|
||||
*
|
||||
* @see Collection
|
||||
* @since 1.8
|
||||
*/
|
||||
@ -333,9 +335,8 @@ public interface Spliterator<T> {
|
||||
* Upon non-null return:
|
||||
* <ul>
|
||||
* <li>the value reported for {@code estimateSize()} before splitting,
|
||||
* if not already zero or {@code Long.MAX_VALUE}, must, after splitting, be
|
||||
* greater than {@code estimateSize()} for this and the returned
|
||||
* Spliterator; and</li>
|
||||
* must, after splitting, be greater than or equal to {@code estimateSize()}
|
||||
* for this and the returned Spliterator; and</li>
|
||||
* <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()}
|
||||
* for this spliterator before splitting must be equal to the sum of
|
||||
* {@code estimateSize()} for this and the returned Spliterator after
|
||||
@ -566,13 +567,28 @@ public interface Spliterator<T> {
|
||||
public static final int SUBSIZED = 0x00004000;
|
||||
|
||||
/**
|
||||
* A Spliterator specialized for {@code int} values.
|
||||
* A Spliterator specialized for primitive values.
|
||||
*
|
||||
* @param <T> the type of elements returned by this Spliterator. The
|
||||
* type must be a wrapper type for a primitive type, such as {@code Integer}
|
||||
* for the primitive {@code int} type.
|
||||
* @param <T_CONS> the type of primitive consumer. The type must be a
|
||||
* primitive specialization of {@link java.util.function.Consumer} for
|
||||
* {@code T}, such as {@link java.util.function.IntConsumer} for
|
||||
* {@code Integer}.
|
||||
* @param <T_SPLITR> the type of primitive Spliterator. The type must be
|
||||
* a primitive specialization of Spliterator for {@code T}, such as
|
||||
* {@link Spliterator.OfInt} for {@code Integer}.
|
||||
*
|
||||
* @see Spliterator.OfInt
|
||||
* @see Spliterator.OfLong
|
||||
* @see Spliterator.OfDouble
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface OfInt extends Spliterator<Integer> {
|
||||
|
||||
public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
|
||||
extends Spliterator<T> {
|
||||
@Override
|
||||
OfInt trySplit();
|
||||
T_SPLITR trySplit();
|
||||
|
||||
/**
|
||||
* If a remaining element exists, performs the given action on it,
|
||||
@ -586,7 +602,7 @@ public interface Spliterator<T> {
|
||||
* upon entry to this method, else {@code true}.
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
boolean tryAdvance(IntConsumer action);
|
||||
boolean tryAdvance(T_CONS action);
|
||||
|
||||
/**
|
||||
* Performs the given action for each remaining element, sequentially in
|
||||
@ -603,6 +619,24 @@ public interface Spliterator<T> {
|
||||
* @param action The action
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
default void forEachRemaining(T_CONS action) {
|
||||
do { } while (tryAdvance(action));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Spliterator specialized for {@code int} values.
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {
|
||||
|
||||
@Override
|
||||
OfInt trySplit();
|
||||
|
||||
@Override
|
||||
boolean tryAdvance(IntConsumer action);
|
||||
|
||||
@Override
|
||||
default void forEachRemaining(IntConsumer action) {
|
||||
do { } while (tryAdvance(action));
|
||||
}
|
||||
@ -658,40 +692,15 @@ public interface Spliterator<T> {
|
||||
* A Spliterator specialized for {@code long} values.
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface OfLong extends Spliterator<Long> {
|
||||
public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {
|
||||
|
||||
@Override
|
||||
OfLong trySplit();
|
||||
|
||||
/**
|
||||
* If a remaining element exists, performs the given action on it,
|
||||
* returning {@code true}; else returns {@code false}. If this
|
||||
* Spliterator is {@link #ORDERED} the action is performed on the
|
||||
* next element in encounter order. Exceptions thrown by the
|
||||
* action are relayed to the caller.
|
||||
*
|
||||
* @param action The action
|
||||
* @return {@code false} if no remaining elements existed
|
||||
* upon entry to this method, else {@code true}.
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
@Override
|
||||
boolean tryAdvance(LongConsumer action);
|
||||
|
||||
/**
|
||||
* Performs the given action for each remaining element, sequentially in
|
||||
* the current thread, until all elements have been processed or the
|
||||
* action throws an exception. If this Spliterator is {@link #ORDERED},
|
||||
* actions are performed in encounter order. Exceptions thrown by the
|
||||
* action are relayed to the caller.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation repeatedly invokes {@link #tryAdvance}
|
||||
* until it returns {@code false}. It should be overridden whenever
|
||||
* possible.
|
||||
*
|
||||
* @param action The action
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
@Override
|
||||
default void forEachRemaining(LongConsumer action) {
|
||||
do { } while (tryAdvance(action));
|
||||
}
|
||||
@ -747,40 +756,15 @@ public interface Spliterator<T> {
|
||||
* A Spliterator specialized for {@code double} values.
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface OfDouble extends Spliterator<Double> {
|
||||
public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {
|
||||
|
||||
@Override
|
||||
OfDouble trySplit();
|
||||
|
||||
/**
|
||||
* If a remaining element exists, performs the given action on it,
|
||||
* returning {@code true}; else returns {@code false}. If this
|
||||
* Spliterator is {@link #ORDERED} the action is performed on the
|
||||
* next element in encounter order. Exceptions thrown by the
|
||||
* action are relayed to the caller.
|
||||
*
|
||||
* @param action The action
|
||||
* @return {@code false} if no remaining elements existed
|
||||
* upon entry to this method, else {@code true}.
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
@Override
|
||||
boolean tryAdvance(DoubleConsumer action);
|
||||
|
||||
/**
|
||||
* Performs the given action for each remaining element, sequentially in
|
||||
* the current thread, until all elements have been processed or the
|
||||
* action throws an exception. If this Spliterator is {@link #ORDERED},
|
||||
* actions are performed in encounter order. Exceptions thrown by the
|
||||
* action are relayed to the caller.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation repeatedly invokes {@link #tryAdvance}
|
||||
* until it returns {@code false}. It should be overridden whenever
|
||||
* possible.
|
||||
*
|
||||
* @param action The action
|
||||
* @throws NullPointerException if the specified action is null
|
||||
*/
|
||||
@Override
|
||||
default void forEachRemaining(DoubleConsumer action) {
|
||||
do { } while (tryAdvance(action));
|
||||
}
|
||||
|
||||
@ -111,9 +111,13 @@ class TimSort<T> {
|
||||
private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
|
||||
|
||||
/**
|
||||
* Temp storage for merges.
|
||||
* Temp storage for merges. A workspace array may optionally be
|
||||
* provided in constructor, and if so will be used as long as it
|
||||
* is big enough.
|
||||
*/
|
||||
private T[] tmp; // Actual runtime type will be Object[], regardless of T
|
||||
private T[] tmp;
|
||||
private int tmpBase; // base of tmp array slice
|
||||
private int tmpLen; // length of tmp array slice
|
||||
|
||||
/**
|
||||
* A stack of pending runs yet to be merged. Run i starts at
|
||||
@ -134,17 +138,31 @@ class TimSort<T> {
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param c the comparator to determine the order of the sort
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
*/
|
||||
private TimSort(T[] a, Comparator<? super T> c) {
|
||||
private TimSort(T[] a, Comparator<? super T> c, T[] work, int workBase, int workLen) {
|
||||
this.a = a;
|
||||
this.c = c;
|
||||
|
||||
// Allocate temp storage (which may be increased later if necessary)
|
||||
int len = a.length;
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
|
||||
T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
|
||||
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
|
||||
tmp = newArray;
|
||||
int tlen = (len < 2 * INITIAL_TMP_STORAGE_LENGTH) ?
|
||||
len >>> 1 : INITIAL_TMP_STORAGE_LENGTH;
|
||||
if (work == null || workLen < tlen || workBase + tlen > work.length) {
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
|
||||
T[] newArray = (T[])java.lang.reflect.Array.newInstance
|
||||
(a.getClass().getComponentType(), tlen);
|
||||
tmp = newArray;
|
||||
tmpBase = 0;
|
||||
tmpLen = tlen;
|
||||
}
|
||||
else {
|
||||
tmp = work;
|
||||
tmpBase = workBase;
|
||||
tmpLen = workLen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate runs-to-be-merged stack (which cannot be expanded). The
|
||||
@ -164,22 +182,30 @@ class TimSort<T> {
|
||||
}
|
||||
|
||||
/*
|
||||
* The next two methods (which are package private and static) constitute
|
||||
* the entire API of this class. Each of these methods obeys the contract
|
||||
* of the public method with the same signature in java.util.Arrays.
|
||||
* The next method (package private and static) constitutes the
|
||||
* entire API of this class.
|
||||
*/
|
||||
|
||||
static <T> void sort(T[] a, Comparator<? super T> c) {
|
||||
sort(a, 0, a.length, c);
|
||||
}
|
||||
/**
|
||||
* Sorts the given range, using the given workspace array slice
|
||||
* for temp storage when possible. This method is designed to be
|
||||
* invoked from public methods (in class Arrays) after performing
|
||||
* any necessary array bounds checks and expanding parameters into
|
||||
* the required forms.
|
||||
*
|
||||
* @param a the array to be sorted
|
||||
* @param lo the index of the first element, inclusive, to be sorted
|
||||
* @param hi the index of the last element, exclusive, to be sorted
|
||||
* @param c the comparator to use
|
||||
* @param work a workspace array (slice)
|
||||
* @param workBase origin of usable space in work array
|
||||
* @param workLen usable size of work array
|
||||
* @since 1.8
|
||||
*/
|
||||
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
|
||||
T[] work, int workBase, int workLen) {
|
||||
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
|
||||
|
||||
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
|
||||
if (c == null) {
|
||||
Arrays.sort(a, lo, hi);
|
||||
return;
|
||||
}
|
||||
|
||||
rangeCheck(a.length, lo, hi);
|
||||
int nRemaining = hi - lo;
|
||||
if (nRemaining < 2)
|
||||
return; // Arrays of size 0 and 1 are always sorted
|
||||
@ -196,7 +222,7 @@ class TimSort<T> {
|
||||
* extending short natural runs to minRun elements, and merging runs
|
||||
* to maintain stack invariant.
|
||||
*/
|
||||
TimSort<T> ts = new TimSort<>(a, c);
|
||||
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
|
||||
int minRun = minRunLength(nRemaining);
|
||||
do {
|
||||
// Identify next run
|
||||
@ -653,11 +679,10 @@ class TimSort<T> {
|
||||
// Copy first run into temp array
|
||||
T[] a = this.a; // For performance
|
||||
T[] tmp = ensureCapacity(len1);
|
||||
System.arraycopy(a, base1, tmp, 0, len1);
|
||||
|
||||
int cursor1 = 0; // Indexes into tmp array
|
||||
int cursor1 = tmpBase; // Indexes into tmp array
|
||||
int cursor2 = base2; // Indexes int a
|
||||
int dest = base1; // Indexes int a
|
||||
System.arraycopy(a, base1, tmp, cursor1, len1);
|
||||
|
||||
// Move first element of second run and deal with degenerate cases
|
||||
a[dest++] = a[cursor2++];
|
||||
@ -770,16 +795,17 @@ class TimSort<T> {
|
||||
// Copy second run into temp array
|
||||
T[] a = this.a; // For performance
|
||||
T[] tmp = ensureCapacity(len2);
|
||||
System.arraycopy(a, base2, tmp, 0, len2);
|
||||
int tmpBase = this.tmpBase;
|
||||
System.arraycopy(a, base2, tmp, tmpBase, len2);
|
||||
|
||||
int cursor1 = base1 + len1 - 1; // Indexes into a
|
||||
int cursor2 = len2 - 1; // Indexes into tmp array
|
||||
int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array
|
||||
int dest = base2 + len2 - 1; // Indexes into a
|
||||
|
||||
// Move last element of first run and deal with degenerate cases
|
||||
a[dest--] = a[cursor1--];
|
||||
if (--len1 == 0) {
|
||||
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
|
||||
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
|
||||
return;
|
||||
}
|
||||
if (len2 == 1) {
|
||||
@ -838,7 +864,7 @@ class TimSort<T> {
|
||||
if (--len2 == 1)
|
||||
break outer;
|
||||
|
||||
count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
|
||||
count2 = len2 - gallopLeft(a[cursor1], tmp, tmpBase, len2, len2 - 1, c);
|
||||
if (count2 != 0) {
|
||||
dest -= count2;
|
||||
cursor2 -= count2;
|
||||
@ -870,7 +896,7 @@ class TimSort<T> {
|
||||
} else {
|
||||
assert len1 == 0;
|
||||
assert len2 > 0;
|
||||
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
|
||||
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -883,7 +909,7 @@ class TimSort<T> {
|
||||
* @return tmp, whether or not it grew
|
||||
*/
|
||||
private T[] ensureCapacity(int minCapacity) {
|
||||
if (tmp.length < minCapacity) {
|
||||
if (tmpLen < minCapacity) {
|
||||
// Compute smallest power of 2 > minCapacity
|
||||
int newSize = minCapacity;
|
||||
newSize |= newSize >> 1;
|
||||
@ -899,30 +925,12 @@ class TimSort<T> {
|
||||
newSize = Math.min(newSize, a.length >>> 1);
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
|
||||
T[] newArray = (T[]) new Object[newSize];
|
||||
T[] newArray = (T[])java.lang.reflect.Array.newInstance
|
||||
(a.getClass().getComponentType(), newSize);
|
||||
tmp = newArray;
|
||||
tmpLen = newSize;
|
||||
tmpBase = 0;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that fromIndex and toIndex are in range, and throws an
|
||||
* appropriate exception if they aren't.
|
||||
*
|
||||
* @param arrayLen the length of the array
|
||||
* @param fromIndex the index of the first element of the range
|
||||
* @param toIndex the index after the last element of the range
|
||||
* @throws IllegalArgumentException if fromIndex > toIndex
|
||||
* @throws ArrayIndexOutOfBoundsException if fromIndex < 0
|
||||
* or toIndex > arrayLen
|
||||
*/
|
||||
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
|
||||
if (fromIndex > toIndex)
|
||||
throw new IllegalArgumentException("fromIndex(" + fromIndex +
|
||||
") > toIndex(" + toIndex+")");
|
||||
if (fromIndex < 0)
|
||||
throw new ArrayIndexOutOfBoundsException(fromIndex);
|
||||
if (toIndex > arrayLen)
|
||||
throw new ArrayIndexOutOfBoundsException(toIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,19 +44,19 @@ import java.io.Serializable;
|
||||
* adjustable expected concurrency for updates. This class obeys the
|
||||
* same functional specification as {@link java.util.Hashtable}, and
|
||||
* includes versions of methods corresponding to each method of
|
||||
* <tt>Hashtable</tt>. However, even though all operations are
|
||||
* {@code Hashtable}. However, even though all operations are
|
||||
* thread-safe, retrieval operations do <em>not</em> entail locking,
|
||||
* and there is <em>not</em> any support for locking the entire table
|
||||
* in a way that prevents all access. This class is fully
|
||||
* interoperable with <tt>Hashtable</tt> in programs that rely on its
|
||||
* interoperable with {@code Hashtable} in programs that rely on its
|
||||
* thread safety but not on its synchronization details.
|
||||
*
|
||||
* <p> Retrieval operations (including <tt>get</tt>) generally do not
|
||||
* <p> Retrieval operations (including {@code get}) generally do not
|
||||
* block, so may overlap with update operations (including
|
||||
* <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
|
||||
* {@code put} and {@code remove}). Retrievals reflect the results
|
||||
* of the most recently <em>completed</em> update operations holding
|
||||
* upon their onset. For aggregate operations such as <tt>putAll</tt>
|
||||
* and <tt>clear</tt>, concurrent retrievals may reflect insertion or
|
||||
* upon their onset. For aggregate operations such as {@code putAll}
|
||||
* and {@code clear}, concurrent retrievals may reflect insertion or
|
||||
* removal of only some entries. Similarly, Iterators and
|
||||
* Enumerations return elements reflecting the state of the hash table
|
||||
* at some point at or since the creation of the iterator/enumeration.
|
||||
@ -64,8 +64,8 @@ import java.io.Serializable;
|
||||
* However, iterators are designed to be used by only one thread at a time.
|
||||
*
|
||||
* <p> The allowed concurrency among update operations is guided by
|
||||
* the optional <tt>concurrencyLevel</tt> constructor argument
|
||||
* (default <tt>16</tt>), which is used as a hint for internal sizing. The
|
||||
* the optional {@code concurrencyLevel} constructor argument
|
||||
* (default {@code 16}), which is used as a hint for internal sizing. The
|
||||
* table is internally partitioned to try to permit the indicated
|
||||
* number of concurrent updates without contention. Because placement
|
||||
* in hash tables is essentially random, the actual concurrency will
|
||||
@ -85,8 +85,8 @@ import java.io.Serializable;
|
||||
* <em>optional</em> methods of the {@link Map} and {@link Iterator}
|
||||
* interfaces.
|
||||
*
|
||||
* <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
|
||||
* does <em>not</em> allow <tt>null</tt> to be used as a key or value.
|
||||
* <p>Like {@link Hashtable} but unlike {@link HashMap}, this class
|
||||
* does <em>not</em> allow {@code null} to be used as a key or value.
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
@ -353,8 +353,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
|
||||
/**
|
||||
* The table is rehashed when its size exceeds this threshold.
|
||||
* (The value of this field is always <tt>(int)(capacity *
|
||||
* loadFactor)</tt>.)
|
||||
* (The value of this field is always {@code (int)(capacity *
|
||||
* loadFactor)}.)
|
||||
*/
|
||||
transient int threshold;
|
||||
|
||||
@ -829,9 +829,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this map contains no key-value mappings.
|
||||
* Returns {@code true} if this map contains no key-value mappings.
|
||||
*
|
||||
* @return <tt>true</tt> if this map contains no key-value mappings
|
||||
* @return {@code true} if this map contains no key-value mappings
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
/*
|
||||
@ -870,8 +870,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
|
||||
/**
|
||||
* Returns the number of key-value mappings in this map. If the
|
||||
* map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
|
||||
* <tt>Integer.MAX_VALUE</tt>.
|
||||
* map contains more than {@code Integer.MAX_VALUE} elements, returns
|
||||
* {@code Integer.MAX_VALUE}.
|
||||
*
|
||||
* @return the number of key-value mappings in this map
|
||||
*/
|
||||
@ -948,10 +948,10 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
/**
|
||||
* Tests if the specified object is a key in this table.
|
||||
*
|
||||
* @param key possible key
|
||||
* @return <tt>true</tt> if and only if the specified object
|
||||
* @param key possible key
|
||||
* @return {@code true} if and only if the specified object
|
||||
* is a key in this table, as determined by the
|
||||
* <tt>equals</tt> method; <tt>false</tt> otherwise.
|
||||
* {@code equals} method; {@code false} otherwise
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -974,13 +974,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this map maps one or more keys to the
|
||||
* specified value. Note: This method requires a full internal
|
||||
* traversal of the hash table, and so is much slower than
|
||||
* method <tt>containsKey</tt>.
|
||||
* Returns {@code true} if this map maps one or more keys to the
|
||||
* specified value. Note: This method requires a full traversal
|
||||
* of the map, and so is much slower than method {@code containsKey}.
|
||||
*
|
||||
* @param value value whose presence in this map is to be tested
|
||||
* @return <tt>true</tt> if this map maps one or more keys to the
|
||||
* @return {@code true} if this map maps one or more keys to the
|
||||
* specified value
|
||||
* @throws NullPointerException if the specified value is null
|
||||
*/
|
||||
@ -1033,16 +1032,16 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
/**
|
||||
* Legacy method testing if some key maps into the specified value
|
||||
* in this table. This method is identical in functionality to
|
||||
* {@link #containsValue}, and exists solely to ensure
|
||||
* {@link #containsValue(Object)}, and exists solely to ensure
|
||||
* full compatibility with class {@link java.util.Hashtable},
|
||||
* which supported this method prior to introduction of the
|
||||
* Java Collections framework.
|
||||
*
|
||||
* @param value a value to search for
|
||||
* @return <tt>true</tt> if and only if some key maps to the
|
||||
* <tt>value</tt> argument in this table as
|
||||
* determined by the <tt>equals</tt> method;
|
||||
* <tt>false</tt> otherwise
|
||||
* @return {@code true} if and only if some key maps to the
|
||||
* {@code value} argument in this table as
|
||||
* determined by the {@code equals} method;
|
||||
* {@code false} otherwise
|
||||
* @throws NullPointerException if the specified value is null
|
||||
*/
|
||||
public boolean contains(Object value) {
|
||||
@ -1053,13 +1052,13 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* Maps the specified key to the specified value in this table.
|
||||
* Neither the key nor the value can be null.
|
||||
*
|
||||
* <p> The value can be retrieved by calling the <tt>get</tt> method
|
||||
* <p>The value can be retrieved by calling the {@code get} method
|
||||
* with a key that is equal to the original key.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated
|
||||
* @param value value to be associated with the specified key
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>
|
||||
* @return the previous value associated with {@code key}, or
|
||||
* {@code null} if there was no mapping for {@code key}
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -1079,7 +1078,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the previous value associated with the specified key,
|
||||
* or <tt>null</tt> if there was no mapping for the key
|
||||
* or {@code null} if there was no mapping for the key
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -1112,8 +1111,8 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* This method does nothing if the key is not in the map.
|
||||
*
|
||||
* @param key the key that needs to be removed
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>
|
||||
* @return the previous value associated with {@code key}, or
|
||||
* {@code null} if there was no mapping for {@code key}
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public V remove(Object key) {
|
||||
@ -1151,7 +1150,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the previous value associated with the specified key,
|
||||
* or <tt>null</tt> if there was no mapping for the key
|
||||
* or {@code null} if there was no mapping for the key
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
public V replace(K key, V value) {
|
||||
@ -1177,14 +1176,14 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys contained in this map.
|
||||
* The set is backed by the map, so changes to the map are
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* removal, which removes the corresponding mapping from this map,
|
||||
* via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
|
||||
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
|
||||
* operations. It does not support the <tt>add</tt> or
|
||||
* <tt>addAll</tt> operations.
|
||||
* via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or
|
||||
* {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
|
||||
* <p>The view's {@code iterator} is a "weakly consistent" iterator
|
||||
* that will never throw {@link ConcurrentModificationException},
|
||||
* and guarantees to traverse elements as they existed upon
|
||||
* construction of the iterator, and may (but is not guaranteed to)
|
||||
@ -1200,12 +1199,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* The collection is backed by the map, so changes to the map are
|
||||
* reflected in the collection, and vice-versa. The collection
|
||||
* supports element removal, which removes the corresponding
|
||||
* mapping from this map, via the <tt>Iterator.remove</tt>,
|
||||
* <tt>Collection.remove</tt>, <tt>removeAll</tt>,
|
||||
* <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not
|
||||
* support the <tt>add</tt> or <tt>addAll</tt> operations.
|
||||
* mapping from this map, via the {@code Iterator.remove},
|
||||
* {@code Collection.remove}, {@code removeAll},
|
||||
* {@code retainAll}, and {@code clear} operations. It does not
|
||||
* support the {@code add} or {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
|
||||
* <p>The view's {@code iterator} is a "weakly consistent" iterator
|
||||
* that will never throw {@link ConcurrentModificationException},
|
||||
* and guarantees to traverse elements as they existed upon
|
||||
* construction of the iterator, and may (but is not guaranteed to)
|
||||
@ -1221,12 +1220,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
* The set is backed by the map, so changes to the map are
|
||||
* reflected in the set, and vice-versa. The set supports element
|
||||
* removal, which removes the corresponding mapping from the map,
|
||||
* via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
|
||||
* <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
|
||||
* operations. It does not support the <tt>add</tt> or
|
||||
* <tt>addAll</tt> operations.
|
||||
* via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or
|
||||
* {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
|
||||
* <p>The view's {@code iterator} is a "weakly consistent" iterator
|
||||
* that will never throw {@link ConcurrentModificationException},
|
||||
* and guarantees to traverse elements as they existed upon
|
||||
* construction of the iterator, and may (but is not guaranteed to)
|
||||
@ -1440,7 +1439,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
/* ---------------- Serialization Support -------------- */
|
||||
|
||||
/**
|
||||
* Saves the state of the <tt>ConcurrentHashMap</tt> instance to a
|
||||
* Saves the state of the {@code ConcurrentHashMap} instance to a
|
||||
* stream (i.e., serializes it).
|
||||
* @param s the stream
|
||||
* @serialData
|
||||
@ -1477,8 +1476,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the <tt>ConcurrentHashMap</tt> instance from a
|
||||
* stream (i.e., deserializes it).
|
||||
* Reconstitutes the instance from a stream (that is, deserializes it).
|
||||
* @param s the stream
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@ -24,14 +24,16 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation which accepts two input arguments and returns no result. This is
|
||||
* the two-arity specialization of {@link Consumer}. Unlike most other
|
||||
* functional interfaces, {@code BiConsumer} is expected to operate via
|
||||
* side-effects.
|
||||
*
|
||||
* @param <T> the type of the first argument to the {@code accept} operation.
|
||||
* @param <U> the type of the second argument to the {@code accept} operation.
|
||||
* @param <T> the type of the first argument to the {@code accept} operation
|
||||
* @param <U> the type of the second argument to the {@code accept} operation
|
||||
*
|
||||
* @see Consumer
|
||||
* @since 1.8
|
||||
@ -47,4 +49,28 @@ public interface BiConsumer<T, U> {
|
||||
* @param u an input object
|
||||
*/
|
||||
void accept(T t, U u);
|
||||
|
||||
/**
|
||||
* Returns a {@code BiConsumer} which performs, in sequence, the operation
|
||||
* represented by this object followed by the operation represented by
|
||||
* the other {@code BiConsumer}.
|
||||
*
|
||||
* <p>Any exceptions thrown by either {@code accept} method are relayed
|
||||
* to the caller; if performing this operation throws an exception, the
|
||||
* other operation will not be performed.
|
||||
*
|
||||
* @param other a BiConsumer which will be chained after this BiConsumer
|
||||
* @return a BiConsumer which performs in sequence the {@code accept} method
|
||||
* of this BiConsumer and the {@code accept} method of the specified
|
||||
* BiConsumer operation
|
||||
* @throws NullPointerException if other is null
|
||||
*/
|
||||
default BiConsumer<T, U> chain(BiConsumer<? super T, ? super U> other) {
|
||||
Objects.requireNonNull(other);
|
||||
|
||||
return (l, r) -> {
|
||||
accept(l, r);
|
||||
other.accept(l, r);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,15 +24,17 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Apply a function to the input arguments, yielding an appropriate result. This
|
||||
* is the two-arity specialization of {@link Function}. A function may
|
||||
* variously provide a mapping between types, object instances or keys and
|
||||
* values or any other form of transformation upon the input.
|
||||
*
|
||||
* @param <T> the type of the first argument to the {@code apply} operation.
|
||||
* @param <U> the type of the second argument to the {@code apply} operation.
|
||||
* @param <R> the type of results returned by the {@code apply} operation.
|
||||
* @param <T> the type of the first argument to the {@code apply} operation
|
||||
* @param <U> the type of the second argument to the {@code apply} operation
|
||||
* @param <R> the type of results returned by the {@code apply} operation
|
||||
*
|
||||
* @see Function
|
||||
* @since 1.8
|
||||
@ -48,4 +50,22 @@ public interface BiFunction<T, U, R> {
|
||||
* @return the function result
|
||||
*/
|
||||
R apply(T t, U u);
|
||||
|
||||
/**
|
||||
* Returns a new function which applies this function followed by the
|
||||
* provided function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param <V> Type of output objects to the combined function. May be the
|
||||
* same type as {@code <T>}, {@code <U>} or {@code <R>}
|
||||
* @param after An additional function to be applied after this function is
|
||||
* applied
|
||||
* @return A function which performs this function followed by the provided
|
||||
* function
|
||||
* @throws NullPointerException if after is null
|
||||
*/
|
||||
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t, U u) -> after.apply(apply(t, u));
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,8 +30,8 @@ import java.util.Objects;
|
||||
* Determines if the input objects match some criteria. This is the two-arity
|
||||
* specialization of {@link Predicate}.
|
||||
*
|
||||
* @param <T> the type of the first argument to {@code test}.
|
||||
* @param <U> the type of the second argument to {@code test}.
|
||||
* @param <T> the type of the first argument to {@code test}
|
||||
* @param <U> the type of the second argument to {@code test}
|
||||
*
|
||||
* @see Predicate
|
||||
* @since 1.8
|
||||
@ -42,9 +42,9 @@ public interface BiPredicate<T, U> {
|
||||
/**
|
||||
* Return {@code true} if the inputs match some criteria.
|
||||
*
|
||||
* @param t an input object.
|
||||
* @param u an input object.
|
||||
* @return {@code true} if the inputs match some criteria.
|
||||
* @param t an input object
|
||||
* @param u an input object
|
||||
* @return {@code true} if the inputs match some criteria
|
||||
*/
|
||||
boolean test(T t, U u);
|
||||
|
||||
@ -54,11 +54,12 @@ public interface BiPredicate<T, U> {
|
||||
* this predicate returns {@code false} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} only if both
|
||||
* predicates return {@code true}.
|
||||
* predicates return {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
|
||||
default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (T t, U u) -> test(t, u) && p.test(t, u);
|
||||
}
|
||||
@ -67,9 +68,9 @@ public interface BiPredicate<T, U> {
|
||||
* Returns a predicate which negates the result of this predicate.
|
||||
*
|
||||
* @return a new predicate who's result is always the opposite of this
|
||||
* predicate.
|
||||
* predicate
|
||||
*/
|
||||
public default BiPredicate<T, U> negate() {
|
||||
default BiPredicate<T, U> negate() {
|
||||
return (T t, U u) -> !test(t, u);
|
||||
}
|
||||
|
||||
@ -79,25 +80,13 @@ public interface BiPredicate<T, U> {
|
||||
* predicate returns {@code true} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate.
|
||||
* @param p a predicate which will be logically-ORed with this predicate
|
||||
* @return a new predicate which returns {@code true} if either predicate
|
||||
* returns {@code true}.
|
||||
* returns {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
|
||||
default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (T t, U u) -> test(t, u) || p.test(t, u);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*
|
||||
* @param p a predicate which will be logically-XORed with this predicate.
|
||||
* @return a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*/
|
||||
public default BiPredicate<T, U> xor(BiPredicate<? super T, ? super U> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (T t, U u) -> test(t, u) ^ p.test(t, u);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,5 +40,5 @@ public interface BooleanSupplier {
|
||||
*
|
||||
* @return a {@code boolean} value
|
||||
*/
|
||||
public boolean getAsBoolean();
|
||||
boolean getAsBoolean();
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation which accepts a single input argument and returns no result.
|
||||
* Unlike most other functional interfaces, {@code Consumer} is expected to
|
||||
@ -41,5 +43,25 @@ public interface Consumer<T> {
|
||||
*
|
||||
* @param t the input object
|
||||
*/
|
||||
public void accept(T t);
|
||||
void accept(T t);
|
||||
|
||||
/**
|
||||
* Returns a {@code Consumer} which performs, in sequence, the operation
|
||||
* represented by this object followed by the operation represented by
|
||||
* the other {@code Consumer}.
|
||||
*
|
||||
* <p>Any exceptions thrown by either {@code accept} method are relayed
|
||||
* to the caller; if performing this operation throws an exception, the
|
||||
* other operation will not be performed.
|
||||
*
|
||||
* @param other a Consumer which will be chained after this Consumer
|
||||
* @return a Consumer which performs in sequence the {@code accept} method
|
||||
* of this Consumer and the {@code accept} method of the specified Consumer
|
||||
* operation
|
||||
* @throws NullPointerException if other is null
|
||||
*/
|
||||
default Consumer<T> chain(Consumer<? super T> other) {
|
||||
Objects.requireNonNull(other);
|
||||
return (T t) -> { accept(t); other.accept(t); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,5 +43,5 @@ public interface DoubleBinaryOperator {
|
||||
* @param right the right operand value
|
||||
* @return the result of the operation
|
||||
*/
|
||||
public double applyAsDouble(double left, double right);
|
||||
double applyAsDouble(double left, double right);
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation which accepts a single double argument and returns no result.
|
||||
* This is the primitive type specialization of {@link Consumer} for
|
||||
@ -41,5 +43,26 @@ public interface DoubleConsumer {
|
||||
*
|
||||
* @param value the input value
|
||||
*/
|
||||
public void accept(double value);
|
||||
void accept(double value);
|
||||
|
||||
/**
|
||||
* Returns a {@code DoubleConsumer} which performs, in sequence, the operation
|
||||
* represented by this object followed by the operation represented by
|
||||
* another {@code DoubleConsumer}.
|
||||
*
|
||||
* <p>Any exceptions thrown by either {@code accept} method are relayed
|
||||
* to the caller; if performing this operation throws an exception, the
|
||||
* other operation will not be performed.
|
||||
*
|
||||
* @param other a DoubleConsumer which will be chained after this
|
||||
* DoubleConsumer
|
||||
* @return an DoubleConsumer which performs in sequence the {@code accept} method
|
||||
* of this DoubleConsumer and the {@code accept} method of the specified IntConsumer
|
||||
* operation
|
||||
* @throws NullPointerException if other is null
|
||||
*/
|
||||
default DoubleConsumer chain(DoubleConsumer other) {
|
||||
Objects.requireNonNull(other);
|
||||
return (double t) -> { accept(t); other.accept(t); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,5 +43,5 @@ public interface DoubleFunction<R> {
|
||||
* @param value the input value
|
||||
* @return the function result
|
||||
*/
|
||||
public R apply(double value);
|
||||
R apply(double value);
|
||||
}
|
||||
|
||||
@ -40,11 +40,11 @@ public interface DoublePredicate {
|
||||
/**
|
||||
* Returns {@code true} if the input value matches some criteria.
|
||||
*
|
||||
* @param value the value to be tested.
|
||||
* @param value the value to be tested
|
||||
* @return {@code true} if the input value matches some criteria, otherwise
|
||||
* {@code false}.
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean test(double value);
|
||||
boolean test(double value);
|
||||
|
||||
/**
|
||||
* Returns a predicate which evaluates to {@code true} only if this
|
||||
@ -52,11 +52,16 @@ public interface DoublePredicate {
|
||||
* this predicate returns {@code false} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} only if both
|
||||
* predicates return {@code true}.
|
||||
* predicates return {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default DoublePredicate and(DoublePredicate p) {
|
||||
default DoublePredicate and(DoublePredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) && p.test(value);
|
||||
}
|
||||
@ -65,9 +70,9 @@ public interface DoublePredicate {
|
||||
* Returns a predicate which negates the result of this predicate.
|
||||
*
|
||||
* @return a new predicate who's result is always the opposite of this
|
||||
* predicate.
|
||||
* predicate
|
||||
*/
|
||||
public default DoublePredicate negate() {
|
||||
default DoublePredicate negate() {
|
||||
return (value) -> !test(value);
|
||||
}
|
||||
|
||||
@ -77,25 +82,17 @@ public interface DoublePredicate {
|
||||
* predicate returns {@code true} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} if either predicate
|
||||
* returns {@code true}.
|
||||
* returns {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default DoublePredicate or(DoublePredicate p) {
|
||||
default DoublePredicate or(DoublePredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) || p.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*
|
||||
* @param p a predicate which will be logically-XORed with this predicate.
|
||||
* @return a predicate that evaluates to {@code true} if all or none of the
|
||||
* component predicates evaluate to {@code true}.
|
||||
*/
|
||||
public default DoublePredicate xor(DoublePredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) ^ p.test(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,5 +39,5 @@ public interface DoubleSupplier {
|
||||
*
|
||||
* @return a {@code double} value
|
||||
*/
|
||||
public double getAsDouble();
|
||||
double getAsDouble();
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation on a {@code double} operand yielding a {@code double}
|
||||
* result. This is the primitive type specialization of {@link UnaryOperator}
|
||||
@ -42,5 +44,46 @@ public interface DoubleUnaryOperator {
|
||||
* @param operand the operand value
|
||||
* @return the operation result value
|
||||
*/
|
||||
public double applyAsDouble(double operand);
|
||||
double applyAsDouble(double operand);
|
||||
|
||||
/**
|
||||
* Compose a new function which applies the provided function followed by
|
||||
* this function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param before An additional function to be applied before this function
|
||||
* is applied
|
||||
* @return A function which performs the provided function followed by this
|
||||
* function
|
||||
* @throws NullPointerException if before is null
|
||||
*/
|
||||
default DoubleUnaryOperator compose(DoubleUnaryOperator before) {
|
||||
Objects.requireNonNull(before);
|
||||
return (double v) -> applyAsDouble(before.applyAsDouble(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new function which applies this function followed by the
|
||||
* provided function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param after An additional function to be applied after this function is
|
||||
* applied
|
||||
* @return A function which performs this function followed by the provided
|
||||
* function followed
|
||||
* @throws NullPointerException if after is null
|
||||
*/
|
||||
default DoubleUnaryOperator andThen(DoubleUnaryOperator after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (double t) -> after.applyAsDouble(applyAsDouble(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unary operator that provides its input value as the result.
|
||||
*
|
||||
* @return a unary operator that provides its input value as the result
|
||||
*/
|
||||
static DoubleUnaryOperator identity() {
|
||||
return t -> t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,14 +24,15 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Apply a function to the input argument, yielding an appropriate result. A
|
||||
* function may variously provide a mapping between types, object instances or
|
||||
* keys and values or any other form of transformation upon the input.
|
||||
*
|
||||
* @param <T> the type of the input to the {@code apply} operation.
|
||||
* @param <R> the type of the result of the {@code apply} operation.
|
||||
* @param <T> the type of the input to the {@code apply} operation
|
||||
* @param <R> the type of the result of the {@code apply} operation
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@ -44,5 +45,50 @@ public interface Function<T, R> {
|
||||
* @param t the input object
|
||||
* @return the function result
|
||||
*/
|
||||
public R apply(T t);
|
||||
R apply(T t);
|
||||
|
||||
/**
|
||||
* Returns a new function which applies the provided function followed by
|
||||
* this function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param <V> type of input objects to the combined function. May be the
|
||||
* same type as {@code <T>} or {@code <R>}
|
||||
* @param before an additional function to be applied before this function
|
||||
* is applied
|
||||
* @return a function which performs the provided function followed by this
|
||||
* function
|
||||
* @throws NullPointerException if before is null
|
||||
*/
|
||||
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
|
||||
Objects.requireNonNull(before);
|
||||
return (V v) -> apply(before.apply(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new function which applies this function followed by the
|
||||
* provided function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param <V> type of output objects to the combined function. May be the
|
||||
* same type as {@code <T>} or {@code <R>}
|
||||
* @param after an additional function to be applied after this function is
|
||||
* applied
|
||||
* @return a function which performs this function followed by the provided
|
||||
* function
|
||||
* @throws NullPointerException if after is null
|
||||
*/
|
||||
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (T t) -> after.apply(apply(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code Function} whose {@code apply} method returns its input.
|
||||
*
|
||||
* @param <T> the type of the input and output objects to the function
|
||||
*/
|
||||
static <T> Function<T, T> identity() {
|
||||
return t -> t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,5 +44,5 @@ public interface IntBinaryOperator {
|
||||
* @param right the right operand value
|
||||
* @return the result of the operation
|
||||
*/
|
||||
public int applyAsInt(int left, int right);
|
||||
int applyAsInt(int left, int right);
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation which accepts a single integer argument and returns no result.
|
||||
* This is the primitive type specialization of {@link Consumer} for {@code int}.
|
||||
@ -41,5 +43,26 @@ public interface IntConsumer {
|
||||
*
|
||||
* @param value the input value
|
||||
*/
|
||||
public void accept(int value);
|
||||
void accept(int value);
|
||||
|
||||
/**
|
||||
* Returns an {@code IntConsumer} which performs, in sequence, the operation
|
||||
* represented by this object followed by the operation represented by
|
||||
* another {@code IntConsumer}.
|
||||
*
|
||||
* <p>Any exceptions thrown by either {@code accept} method are relayed
|
||||
* to the caller; if performing this operation throws an exception, the
|
||||
* other operation will not be performed.
|
||||
*
|
||||
* @param other an IntConsumer which will be chained after this
|
||||
* IntConsumer
|
||||
* @return an IntConsumer which performs in sequence the {@code accept} method
|
||||
* of this IntConsumer and the {@code accept} method of the specified IntConsumer
|
||||
* operation
|
||||
* @throws NullPointerException if other is null
|
||||
*/
|
||||
default IntConsumer chain(IntConsumer other) {
|
||||
Objects.requireNonNull(other);
|
||||
return (int t) -> { accept(t); other.accept(t); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,5 +43,5 @@ public interface IntFunction<R> {
|
||||
* @param value the input value
|
||||
* @return the function result
|
||||
*/
|
||||
public R apply(int value);
|
||||
R apply(int value);
|
||||
}
|
||||
|
||||
@ -39,11 +39,11 @@ public interface IntPredicate {
|
||||
/**
|
||||
* Returns {@code true} if the input value matches some criteria.
|
||||
*
|
||||
* @param value the value to be tested.
|
||||
* @param value the value to be tested
|
||||
* @return {@code true} if the input value matches some criteria, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean test(int value);
|
||||
boolean test(int value);
|
||||
|
||||
/**
|
||||
* Returns a predicate which evaluates to {@code true} only if this
|
||||
@ -51,11 +51,16 @@ public interface IntPredicate {
|
||||
* this predicate returns {@code false} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} only if both
|
||||
* predicates return {@code true}.
|
||||
* predicates return {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default IntPredicate and(IntPredicate p) {
|
||||
default IntPredicate and(IntPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) && p.test(value);
|
||||
}
|
||||
@ -64,9 +69,9 @@ public interface IntPredicate {
|
||||
* Returns a predicate which negates the result of this predicate.
|
||||
*
|
||||
* @return a new predicate who's result is always the opposite of this
|
||||
* predicate.
|
||||
* predicate
|
||||
*/
|
||||
public default IntPredicate negate() {
|
||||
default IntPredicate negate() {
|
||||
return (value) -> !test(value);
|
||||
}
|
||||
|
||||
@ -76,25 +81,17 @@ public interface IntPredicate {
|
||||
* predicate returns {@code true} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate
|
||||
* @return a new predicate which returns {@code true} if either predicate
|
||||
* returns {@code true}.
|
||||
* returns {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default IntPredicate or(IntPredicate p) {
|
||||
default IntPredicate or(IntPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) || p.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*
|
||||
* @param p a predicate which will be logically-XORed with this predicate.
|
||||
* @return a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}
|
||||
*/
|
||||
public default IntPredicate xor(IntPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) ^ p.test(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,5 +39,5 @@ public interface IntSupplier {
|
||||
*
|
||||
* @return an {@code int} value
|
||||
*/
|
||||
public int getAsInt();
|
||||
int getAsInt();
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation on a single {@code int} operand yielding an {@code int} result.
|
||||
* This is the primitive type specialization of {@link UnaryOperator} for
|
||||
@ -37,10 +39,51 @@ public interface IntUnaryOperator {
|
||||
|
||||
/**
|
||||
* Returns the {@code int} value result of the operation upon the
|
||||
* {@code int} operand.
|
||||
* {@code int} operand.
|
||||
*
|
||||
* @param operand the operand value
|
||||
* @return the operation result value
|
||||
*/
|
||||
public int applyAsInt(int operand);
|
||||
int applyAsInt(int operand);
|
||||
|
||||
/**
|
||||
* Compose a new function which applies the provided function followed by
|
||||
* this function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param before an additional function to be applied before this function
|
||||
* is applied
|
||||
* @return a function which performs the provided function followed by this
|
||||
* function
|
||||
* @throws NullPointerException if before is null
|
||||
*/
|
||||
default IntUnaryOperator compose(IntUnaryOperator before) {
|
||||
Objects.requireNonNull(before);
|
||||
return (int v) -> applyAsInt(before.applyAsInt(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new function which applies this function followed by the
|
||||
* provided function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param after an additional function to be applied after this function is
|
||||
* applied
|
||||
* @return a function which performs this function followed by the provided
|
||||
* function followed
|
||||
* @throws NullPointerException if after is null
|
||||
*/
|
||||
default IntUnaryOperator andThen(IntUnaryOperator after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (int t) -> after.applyAsInt(applyAsInt(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unary operator that provides its input value as the result.
|
||||
*
|
||||
* @return a unary operator that provides its input value as the result
|
||||
*/
|
||||
static IntUnaryOperator identity() {
|
||||
return t -> t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,5 +44,5 @@ public interface LongBinaryOperator {
|
||||
* @param right the right operand value
|
||||
* @return the result of the operation
|
||||
*/
|
||||
public long applyAsLong(long left, long right);
|
||||
long applyAsLong(long left, long right);
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation which accepts a single long argument and returns no result.
|
||||
* This is the {@code long}-consuming primitive type specialization of
|
||||
@ -41,5 +43,26 @@ public interface LongConsumer {
|
||||
*
|
||||
* @param value the input value
|
||||
*/
|
||||
public void accept(long value);
|
||||
void accept(long value);
|
||||
|
||||
/**
|
||||
* Returns a {@code LongConsumer} which performs, in sequence, the operation
|
||||
* represented by this object followed by the operation represented by
|
||||
* another {@code LongConsumer}.
|
||||
*
|
||||
* <p>Any exceptions thrown by either {@code accept} method are relayed
|
||||
* to the caller; if performing this operation throws an exception, the
|
||||
* other operation will not be performed.
|
||||
*
|
||||
* @param other a LongConsumer which will be chained after this
|
||||
* LongConsumer
|
||||
* @return a LongConsumer which performs in sequence the {@code accept} method
|
||||
* of this LongConsumer and the {@code accept} method of the specified LongConsumer
|
||||
* operation
|
||||
* @throws NullPointerException if other is null
|
||||
*/
|
||||
default LongConsumer chain(LongConsumer other) {
|
||||
Objects.requireNonNull(other);
|
||||
return (long t) -> { accept(t); other.accept(t); };
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,5 +43,5 @@ public interface LongFunction<R> {
|
||||
* @param value the input value
|
||||
* @return the function result
|
||||
*/
|
||||
public R apply(long value);
|
||||
R apply(long value);
|
||||
}
|
||||
|
||||
@ -39,11 +39,11 @@ public interface LongPredicate {
|
||||
/**
|
||||
* Returns {@code true} if the input value matches some criteria.
|
||||
*
|
||||
* @param value the value to be tested.
|
||||
* @param value the value to be tested
|
||||
* @return {@code true} if the input value matches some criteria, otherwise
|
||||
* {@code false}.
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean test(long value);
|
||||
boolean test(long value);
|
||||
|
||||
/**
|
||||
* Returns a predicate which evaluates to {@code true} only if this
|
||||
@ -51,11 +51,15 @@ public interface LongPredicate {
|
||||
* this predicate returns {@code false} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} only if both
|
||||
* predicates return {@code true}.
|
||||
* predicates return {@code true}
|
||||
*/
|
||||
public default LongPredicate and(LongPredicate p) {
|
||||
default LongPredicate and(LongPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) && p.test(value);
|
||||
}
|
||||
@ -64,9 +68,9 @@ public interface LongPredicate {
|
||||
* Returns a predicate which negates the result of this predicate.
|
||||
*
|
||||
* @return a new predicate who's result is always the opposite of this
|
||||
* predicate.
|
||||
* predicate
|
||||
*/
|
||||
public default LongPredicate negate() {
|
||||
default LongPredicate negate() {
|
||||
return (value) -> !test(value);
|
||||
}
|
||||
|
||||
@ -76,25 +80,17 @@ public interface LongPredicate {
|
||||
* predicate returns {@code true} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate
|
||||
* @return a new predicate which returns {@code true} if either predicate
|
||||
* returns {@code true}.
|
||||
* returns {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default LongPredicate or(LongPredicate p) {
|
||||
default LongPredicate or(LongPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) || p.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*
|
||||
* @param p a predicate which will be logically-XORed with this predicate.
|
||||
* @return a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
*/
|
||||
public default LongPredicate xor(LongPredicate p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (value) -> test(value) ^ p.test(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,5 +39,5 @@ public interface LongSupplier {
|
||||
*
|
||||
* @return a {@code long} value
|
||||
*/
|
||||
public long getAsLong();
|
||||
long getAsLong();
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
*/
|
||||
package java.util.function;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An operation on a single {@code long} operand yielding a {@code long} result.
|
||||
* This is the primitive type specialization of {@link UnaryOperator} for
|
||||
@ -42,5 +44,46 @@ public interface LongUnaryOperator {
|
||||
* @param operand the operand value
|
||||
* @return the operation result value
|
||||
*/
|
||||
public long applyAsLong(long operand);
|
||||
long applyAsLong(long operand);
|
||||
|
||||
/**
|
||||
* Compose a new function which applies the provided function followed by
|
||||
* this function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param before An additional function to be applied before this function
|
||||
* is applied
|
||||
* @return A function which performs the provided function followed by this
|
||||
* function
|
||||
* @throws NullPointerException if before is null
|
||||
*/
|
||||
default LongUnaryOperator compose(LongUnaryOperator before) {
|
||||
Objects.requireNonNull(before);
|
||||
return (long v) -> applyAsLong(before.applyAsLong(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose a new function which applies this function followed by the
|
||||
* provided function. If either function throws an exception, it is relayed
|
||||
* to the caller.
|
||||
*
|
||||
* @param after An additional function to be applied after this function is
|
||||
* applied
|
||||
* @return A function which performs this function followed by the provided
|
||||
* function followed
|
||||
* @throws NullPointerException if after is null
|
||||
*/
|
||||
default LongUnaryOperator andThen(LongUnaryOperator after) {
|
||||
Objects.requireNonNull(after);
|
||||
return (long t) -> after.applyAsLong(applyAsLong(t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unary operator that provides its input value as the result.
|
||||
*
|
||||
* @return a unary operator that provides its input value as the result
|
||||
*/
|
||||
static LongUnaryOperator identity() {
|
||||
return t -> t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,5 +44,5 @@ public interface ObjDoubleConsumer<T> {
|
||||
* @param t an input object
|
||||
* @param value an input value
|
||||
*/
|
||||
public void accept(T t, double value);
|
||||
void accept(T t, double value);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ package java.util.function;
|
||||
* {@link BiConsumer}. Unlike most other functional interfaces,
|
||||
* {@code ObjIntConsumer} is expected to operate via side-effects.
|
||||
*
|
||||
* @param <T> Type of reference argument to {@code accept()}.
|
||||
* @param <T> Type of reference argument to {@code accept()}
|
||||
*
|
||||
* @see BiConsumer
|
||||
* @since 1.8
|
||||
@ -44,5 +44,5 @@ public interface ObjIntConsumer<T> {
|
||||
* @param t an input object
|
||||
* @param value an input value
|
||||
*/
|
||||
public void accept(T t, int value);
|
||||
void accept(T t, int value);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ package java.util.function;
|
||||
* {@link BiConsumer}. Unlike most other functional interfaces,
|
||||
* {@code ObjLongConsumer} is expected to operate via side-effects.
|
||||
*
|
||||
* @param <T> Type of reference argument to {@code accept()}.
|
||||
* @param <T> Type of reference argument to {@code accept()}
|
||||
*
|
||||
* @see BiConsumer
|
||||
* @since 1.8
|
||||
@ -44,5 +44,5 @@ public interface ObjLongConsumer<T> {
|
||||
* @param t an input object
|
||||
* @param value an input value
|
||||
*/
|
||||
public void accept(T t, long value);
|
||||
void accept(T t, long value);
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ public interface Predicate<T> {
|
||||
* @return {@code true} if the input object matches some criteria, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean test(T t);
|
||||
boolean test(T t);
|
||||
|
||||
/**
|
||||
* Returns a predicate which evaluates to {@code true} only if this
|
||||
@ -51,11 +51,16 @@ public interface Predicate<T> {
|
||||
* this predicate returns {@code false} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ANDed with this predicate
|
||||
* @return a new predicate which returns {@code true} only if both
|
||||
* predicates return {@code true}.
|
||||
* predicates return {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default Predicate<T> and(Predicate<? super T> p) {
|
||||
default Predicate<T> and(Predicate<? super T> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (t) -> test(t) && p.test(t);
|
||||
}
|
||||
@ -66,7 +71,7 @@ public interface Predicate<T> {
|
||||
* @return a new predicate who's result is always the opposite of this
|
||||
* predicate.
|
||||
*/
|
||||
public default Predicate<T> negate() {
|
||||
default Predicate<T> negate() {
|
||||
return (t) -> !test(t);
|
||||
}
|
||||
|
||||
@ -76,25 +81,32 @@ public interface Predicate<T> {
|
||||
* predicate returns {@code true} then the remaining predicate is not
|
||||
* evaluated.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate.
|
||||
* <p>Any exceptions thrown by either {@code test} method are relayed
|
||||
* to the caller; if performing first operation throws an exception, the
|
||||
* second operation will not be performed.
|
||||
*
|
||||
* @param p a predicate which will be logically-ORed with this predicate
|
||||
* @return a new predicate which returns {@code true} if either predicate
|
||||
* returns {@code true}.
|
||||
* returns {@code true}
|
||||
* @throws NullPointerException if p is null
|
||||
*/
|
||||
public default Predicate<T> or(Predicate<? super T> p) {
|
||||
default Predicate<T> or(Predicate<? super T> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (t) -> test(t) || p.test(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
* Returns a predicate who's result matches
|
||||
* {@code Objects.equals(target, t)}.
|
||||
*
|
||||
* @param p a predicate which will be logically-XORed with this predicte.
|
||||
* @return a predicate that evaluates to {@code true} if both or neither of
|
||||
* the component predicates evaluate to {@code true}.
|
||||
* @param <T> the type of values evaluated by the predicate
|
||||
* @param target the target value to be compared for equality
|
||||
* @return a predicate who's result matches
|
||||
* {@code Objects.equals(target, t)}
|
||||
*/
|
||||
public default Predicate<T> xor(Predicate<? super T> p) {
|
||||
Objects.requireNonNull(p);
|
||||
return (t) -> test(t) ^ p.test(t);
|
||||
static <T> Predicate<T> isEqual(Object target) {
|
||||
return (null == target)
|
||||
? Objects::isNull
|
||||
: object -> target.equals(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,5 +40,5 @@ public interface Supplier<T> {
|
||||
*
|
||||
* @return an object
|
||||
*/
|
||||
public T get();
|
||||
T get();
|
||||
}
|
||||
|
||||
@ -46,5 +46,5 @@ public interface ToDoubleBiFunction<T, U> {
|
||||
* @param u an input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public double applyAsDouble(T t, U u);
|
||||
double applyAsDouble(T t, U u);
|
||||
}
|
||||
|
||||
@ -42,5 +42,5 @@ public interface ToDoubleFunction<T> {
|
||||
* @param t the input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public double applyAsDouble(T t);
|
||||
double applyAsDouble(T t);
|
||||
}
|
||||
|
||||
@ -28,10 +28,10 @@ package java.util.function;
|
||||
* Apply a function to the input arguments, yielding an appropriate result.
|
||||
* This is the {@code int}-bearing specialization for {@link BiFunction}.
|
||||
*
|
||||
* @param <T> the type of the first argument to the {@code applyAsLong}
|
||||
* operation.
|
||||
* @param <U> the type of the second argument to the {@code applyAsLong}
|
||||
* operation.
|
||||
* @param <T> the type of the first argument to the {@code applyAsInt}
|
||||
* operation
|
||||
* @param <U> the type of the second argument to the {@code applyAsInt}
|
||||
* operation
|
||||
*
|
||||
* @see BiFunction
|
||||
* @since 1.8
|
||||
@ -46,5 +46,5 @@ public interface ToIntBiFunction<T, U> {
|
||||
* @param u an input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public int applyAsInt(T t, U u);
|
||||
int applyAsInt(T t, U u);
|
||||
}
|
||||
|
||||
@ -42,5 +42,5 @@ public interface ToIntFunction<T> {
|
||||
* @param t the input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public int applyAsInt(T t);
|
||||
int applyAsInt(T t);
|
||||
}
|
||||
|
||||
@ -46,5 +46,5 @@ public interface ToLongBiFunction<T, U> {
|
||||
* @param u an input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public long applyAsLong(T t, U u);
|
||||
long applyAsLong(T t, U u);
|
||||
}
|
||||
|
||||
@ -42,5 +42,5 @@ public interface ToLongFunction<T> {
|
||||
* @param t the input object
|
||||
* @return the function result value
|
||||
*/
|
||||
public long applyAsLong(T t);
|
||||
long applyAsLong(T t);
|
||||
}
|
||||
|
||||
@ -36,4 +36,13 @@ package java.util.function;
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UnaryOperator<T> extends Function<T, T> {
|
||||
|
||||
/**
|
||||
* Returns a unary operator that provides its input value as the result.
|
||||
*
|
||||
* @return a unary operator that provides its input value as the result
|
||||
*/
|
||||
static <T> UnaryOperator<T> identity() {
|
||||
return t -> t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ public class Agent {
|
||||
private static final String SNMP_ADAPTOR_BOOTSTRAP_CLASS_NAME =
|
||||
"sun.management.snmp.AdaptorBootstrap";
|
||||
|
||||
private static final String JDP_DEFAULT_ADDRESS = "239.255.255.225";
|
||||
private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
|
||||
private static final int JDP_DEFAULT_PORT = 7095;
|
||||
|
||||
// The only active agent allowed
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
*
|
||||
* - `INSTANCE_NAME` -- The user-provided name of the running instance
|
||||
*
|
||||
* The protocol sends packets to 239.255.255.225:7095 by default.
|
||||
* The protocol sends packets to 224.0.23.178:7095 by default.
|
||||
*
|
||||
* The protocol uses system properties to control it's behaviour:
|
||||
* - `com.sun.management.jdp.port` -- override default port
|
||||
|
||||
@ -682,6 +682,11 @@ class UTF_8 extends Unicode
|
||||
return encodeBufferLoop(src, dst);
|
||||
}
|
||||
|
||||
private byte repl = (byte)'?';
|
||||
protected void implReplaceWith(byte[] newReplacement) {
|
||||
repl = newReplacement[0];
|
||||
}
|
||||
|
||||
// returns -1 if there is malformed char(s) and the
|
||||
// "action" for malformed input is not REPLACE.
|
||||
public int encode(char[] sa, int sp, int len, byte[] da) {
|
||||
@ -709,7 +714,7 @@ class UTF_8 extends Unicode
|
||||
if (uc < 0) {
|
||||
if (malformedInputAction() != CodingErrorAction.REPLACE)
|
||||
return -1;
|
||||
da[dp++] = replacement()[0];
|
||||
da[dp++] = repl;
|
||||
} else {
|
||||
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
|
||||
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
|
||||
|
||||
@ -610,6 +610,11 @@ public class DoubleByte {
|
||||
return encodeBufferLoop(src, dst);
|
||||
}
|
||||
|
||||
protected byte[] repl = replacement();
|
||||
protected void implReplaceWith(byte[] newReplacement) {
|
||||
repl = newReplacement;
|
||||
}
|
||||
|
||||
public int encode(char[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -622,7 +627,6 @@ public class DoubleByte {
|
||||
Character.isLowSurrogate(src[sp])) {
|
||||
sp++;
|
||||
}
|
||||
byte[] repl = replacement();
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
@ -877,7 +881,6 @@ public class DoubleByte {
|
||||
Character.isLowSurrogate(src[sp])) {
|
||||
sp++;
|
||||
}
|
||||
byte[] repl = replacement();
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
|
||||
@ -356,6 +356,11 @@ public class HKSCS {
|
||||
return encodeBufferLoop(src, dst);
|
||||
}
|
||||
|
||||
private byte[] repl = replacement();
|
||||
protected void implReplaceWith(byte[] newReplacement) {
|
||||
repl = newReplacement;
|
||||
}
|
||||
|
||||
public int encode(char[] src, int sp, int len, byte[] dst) {
|
||||
int dp = 0;
|
||||
int sl = sp + len;
|
||||
@ -367,7 +372,6 @@ public class HKSCS {
|
||||
!Character.isLowSurrogate(src[sp]) ||
|
||||
(bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
|
||||
== UNMAPPABLE_ENCODING) {
|
||||
byte[] repl = replacement();
|
||||
dst[dp++] = repl[0];
|
||||
if (repl.length > 1)
|
||||
dst[dp++] = repl[1];
|
||||
|
||||
@ -78,7 +78,7 @@ public class KeyTab implements KeyTabConstants {
|
||||
|
||||
private final String tabName;
|
||||
private long lastModified;
|
||||
private int kt_vno;
|
||||
private int kt_vno = KRB5_KT_VNO;
|
||||
|
||||
private Vector<KeyTabEntry> entries = new Vector<>();
|
||||
|
||||
|
||||
@ -552,7 +552,7 @@ public final class OCSPResponse {
|
||||
|
||||
try {
|
||||
Signature respSignature = Signature.getInstance(sigAlgId.getName());
|
||||
respSignature.initVerify(cert);
|
||||
respSignature.initVerify(cert.getPublicKey());
|
||||
respSignature.update(tbsResponseData);
|
||||
|
||||
if (respSignature.verify(signature)) {
|
||||
|
||||
@ -1447,6 +1447,7 @@ class ToolDialog extends Dialog {
|
||||
PERM_ARRAY.add(new AWTPerm());
|
||||
PERM_ARRAY.add(new DelegationPerm());
|
||||
PERM_ARRAY.add(new FilePerm());
|
||||
PERM_ARRAY.add(new HttpURLPerm());
|
||||
PERM_ARRAY.add(new InqSecContextPerm());
|
||||
PERM_ARRAY.add(new LogPerm());
|
||||
PERM_ARRAY.add(new MgmtPerm());
|
||||
@ -3842,6 +3843,20 @@ class FilePerm extends Perm {
|
||||
}
|
||||
}
|
||||
|
||||
class HttpURLPerm extends Perm {
|
||||
public HttpURLPerm() {
|
||||
super("HttpURLPermission",
|
||||
"java.net.HttpURLPermission",
|
||||
new String[] {
|
||||
"<"+ PolicyTool.rb.getString("url") + ">",
|
||||
},
|
||||
new String[] {
|
||||
"<" + PolicyTool.rb.getString("method.list") + ">:<"
|
||||
+ PolicyTool.rb.getString("request.headers.list") + ">",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class InqSecContextPerm extends Perm {
|
||||
public InqSecContextPerm() {
|
||||
super("InquireSecContextPermission",
|
||||
|
||||
@ -139,6 +139,9 @@ public class Resources extends java.util.ListResourceBundle {
|
||||
{"policy.type", "policy type"},
|
||||
{"property.name", "property name"},
|
||||
{"provider.name", "provider name"},
|
||||
{"url", "url"},
|
||||
{"method.list", "method list"},
|
||||
{"request.headers.list", "request headers list"},
|
||||
{"Principal.List", "Principal List"},
|
||||
{"Permission.List", "Permission List"},
|
||||
{"Code.Base", "Code Base"},
|
||||
|
||||
@ -54,7 +54,7 @@ public class FormatData_mt extends ParallelListResourceBundle {
|
||||
"Mejju",
|
||||
"\u0120unju",
|
||||
"Lulju",
|
||||
"Awissu",
|
||||
"Awwissu",
|
||||
"Settembru",
|
||||
"Ottubru",
|
||||
"Novembru",
|
||||
@ -71,7 +71,7 @@ public class FormatData_mt extends ParallelListResourceBundle {
|
||||
"Mej",
|
||||
"\u0120un",
|
||||
"Lul",
|
||||
"Awi",
|
||||
"Aww",
|
||||
"Set",
|
||||
"Ott",
|
||||
"Nov",
|
||||
|
||||
@ -34,6 +34,7 @@ import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
import static sun.misc.Version.jdkMinorVersion;
|
||||
|
||||
import static java.awt.BorderLayout.*;
|
||||
import static sun.tools.jconsole.Utilities.*;
|
||||
@ -73,7 +74,7 @@ public class AboutDialog extends InternalDialog {
|
||||
String jConsoleVersion = Version.getVersion();
|
||||
String vmName = System.getProperty("java.vm.name");
|
||||
String vmVersion = System.getProperty("java.vm.version");
|
||||
String urlStr = Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
|
||||
String urlStr = getOnlineDocUrl();
|
||||
if (isBrowseSupported()) {
|
||||
urlStr = "<a style='color:#35556b' href=\"" + urlStr + "\">" + urlStr + "</a>";
|
||||
}
|
||||
@ -86,8 +87,7 @@ public class AboutDialog extends InternalDialog {
|
||||
"<html><font color=#"+ colorStr + ">" +
|
||||
Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
|
||||
"<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_JAVA_VERSION, (vmName +", "+ vmVersion)) +
|
||||
"<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK, urlStr) +
|
||||
"</html>");
|
||||
"<p>" + urlStr + "</html>");
|
||||
helpLink.setOpaque(false);
|
||||
helpLink.setEditable(false);
|
||||
helpLink.setForeground(textColor);
|
||||
@ -153,7 +153,7 @@ public class AboutDialog extends InternalDialog {
|
||||
}
|
||||
|
||||
static void browseUserGuide(JConsole jConsole) {
|
||||
getAboutDialog(jConsole).browse(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL);
|
||||
getAboutDialog(jConsole).browse(getOnlineDocUrl());
|
||||
}
|
||||
|
||||
static boolean isBrowseSupported() {
|
||||
@ -182,6 +182,12 @@ public class AboutDialog extends InternalDialog {
|
||||
};
|
||||
}
|
||||
|
||||
private static String getOnlineDocUrl() {
|
||||
String version = Integer.toString(jdkMinorVersion());
|
||||
return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL,
|
||||
version);
|
||||
}
|
||||
|
||||
private static class TPanel extends JPanel {
|
||||
TPanel(int hgap, int vgap) {
|
||||
super(new BorderLayout(hgap, vgap));
|
||||
|
||||
@ -55,6 +55,7 @@ public class VMPanel extends JTabbedPane implements PropertyChangeListener {
|
||||
private VMInternalFrame vmIF = null;
|
||||
private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
|
||||
private boolean wasConnected = false;
|
||||
private boolean userDisconnected = false;
|
||||
|
||||
// The everConnected flag keeps track of whether the window can be
|
||||
// closed if the user clicks Cancel after a failed connection attempt.
|
||||
@ -125,6 +126,7 @@ public class VMPanel extends JTabbedPane implements PropertyChangeListener {
|
||||
if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
|
||||
|
||||
if (isConnected()) {
|
||||
userDisconnected = true;
|
||||
disconnect();
|
||||
wasConnected = false;
|
||||
} else {
|
||||
@ -452,6 +454,11 @@ public class VMPanel extends JTabbedPane implements PropertyChangeListener {
|
||||
private void vmPanelDied() {
|
||||
disconnect();
|
||||
|
||||
if (userDisconnected) {
|
||||
userDisconnected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
JOptionPane optionPane;
|
||||
String msgTitle, msgExplanation, buttonStr;
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=Masthead Graphic
|
||||
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole
|
||||
HELP_ABOUT_DIALOG_TITLE=JConsole: About
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:<br>{0}
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
|
||||
HELP_MENU_ABOUT_TITLE=&About JConsole
|
||||
HELP_MENU_USER_GUIDE_TITLE=Online &User Guide
|
||||
HELP_MENU_TITLE=&Help
|
||||
|
||||
@ -105,7 +105,7 @@ HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u30DE\u30B9\u30C8\u30D8\u30C3\u30C9\
|
||||
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066
|
||||
HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):<br>{0}
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
|
||||
HELP_MENU_ABOUT_TITLE=JConsole\u306B\u3064\u3044\u3066(&A)
|
||||
HELP_MENU_USER_GUIDE_TITLE=\u30AA\u30F3\u30E9\u30A4\u30F3\u30FB\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U)
|
||||
HELP_MENU_TITLE=\u30D8\u30EB\u30D7(&H)
|
||||
|
||||
@ -105,7 +105,7 @@ HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u62A5\u5934\u56FE
|
||||
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole
|
||||
HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):<br>{0}
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://java.sun.com/javase/6/docs/technotes/guides/management/jconsole.html
|
||||
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
|
||||
HELP_MENU_ABOUT_TITLE=\u5173\u4E8E JConsole(&A)
|
||||
HELP_MENU_USER_GUIDE_TITLE=\u8054\u673A\u7528\u6237\u6307\u5357(&U)
|
||||
HELP_MENU_TITLE=\u5E2E\u52A9(&H)
|
||||
|
||||
@ -1085,13 +1085,13 @@ public class ZipFileSystem extends FileSystem {
|
||||
}
|
||||
|
||||
// Creates a new empty temporary file in the same directory as the
|
||||
// specified file. A variant of File.createTempFile.
|
||||
// specified file. A variant of Files.createTempFile.
|
||||
private Path createTempFileInSameDirectoryAs(Path path)
|
||||
throws IOException
|
||||
{
|
||||
Path parent = path.toAbsolutePath().getParent();
|
||||
String dir = (parent == null)? "." : parent.toString();
|
||||
Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath();
|
||||
Path dir = (parent == null) ? path.getFileSystem().getPath(".") : parent;
|
||||
Path tmpPath = Files.createTempFile(dir, "zipfstmp", null);
|
||||
tmppaths.add(tmpPath);
|
||||
return tmpPath;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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
|
||||
@ -100,6 +100,8 @@ Java_java_io_FileInputStream_available(JNIEnv *env, jobject this) {
|
||||
if (IO_Available(fd, &ret)) {
|
||||
if (ret > INT_MAX) {
|
||||
ret = (jlong) INT_MAX;
|
||||
} else if (ret < 0) {
|
||||
ret = 0;
|
||||
}
|
||||
return jlong_to_jint(ret);
|
||||
}
|
||||
|
||||
@ -30,6 +30,6 @@
|
||||
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
|
||||
# and may not be available in a future release.
|
||||
#
|
||||
-client KNOWN
|
||||
-client IF_SERVER_CLASS -server
|
||||
-server KNOWN
|
||||
-minimal KNOWN
|
||||
|
||||
@ -128,7 +128,9 @@ static char* next_arg(char* cmdline, char* arg, jboolean* wildcard) {
|
||||
*wildcard = JNI_TRUE;
|
||||
}
|
||||
if (prev == '\\') {
|
||||
*dest++ = prev;
|
||||
for (i = 0 ; i < slashes ; i++) {
|
||||
*dest++ = prev;
|
||||
}
|
||||
}
|
||||
*dest++ = ch;
|
||||
break;
|
||||
@ -184,7 +186,7 @@ void JLI_CmdToArgs(char* cmdline) {
|
||||
argv = (StdArg*) JLI_MemRealloc(argv, (nargs+1) * sizeof(StdArg));
|
||||
argv[nargs].arg = JLI_StringDup(arg);
|
||||
argv[nargs].has_wildcard = wildcard;
|
||||
|
||||
*arg = NULL;
|
||||
nargs++;
|
||||
} while (src != NULL);
|
||||
|
||||
@ -602,6 +604,14 @@ int main(int argc, char* argv[]) {
|
||||
v->add("d", FALSE);
|
||||
vectors[i++] = v;
|
||||
|
||||
v= new Vector(argv[0], "\\\\?");
|
||||
v->add("\\\\?", TRUE);
|
||||
vectors[i++] = v;
|
||||
|
||||
v= new Vector(argv[0], "\\\\*");
|
||||
v->add("\\\\*", TRUE);
|
||||
vectors[i++] = v;
|
||||
|
||||
dotest(vectors);
|
||||
printf("All tests pass [%d]\n", i);
|
||||
doexit(0);
|
||||
|
||||
@ -100,6 +100,7 @@ class WindowsConstants {
|
||||
public static final int ERROR_INVALID_LEVEL = 124;
|
||||
public static final int ERROR_DIR_NOT_EMPTY = 145;
|
||||
public static final int ERROR_ALREADY_EXISTS = 183;
|
||||
public static final int ERROR_MORE_DATA = 234;
|
||||
public static final int ERROR_DIRECTORY = 267;
|
||||
public static final int ERROR_NOTIFY_ENUM_DIR = 1022;
|
||||
public static final int ERROR_NONE_MAPPED = 1332;
|
||||
|
||||
@ -973,19 +973,19 @@ class WindowsNativeDispatcher {
|
||||
* HANDLE CreateIoCompletionPort (
|
||||
* HANDLE FileHandle,
|
||||
* HANDLE ExistingCompletionPort,
|
||||
* DWORD CompletionKey,
|
||||
* ULONG_PTR CompletionKey,
|
||||
* DWORD NumberOfConcurrentThreads
|
||||
* )
|
||||
*/
|
||||
static native long CreateIoCompletionPort(long fileHandle, long existingPort,
|
||||
int completionKey) throws WindowsException;
|
||||
long completionKey) throws WindowsException;
|
||||
|
||||
|
||||
/**
|
||||
* GetQueuedCompletionStatus(
|
||||
* HANDLE CompletionPort,
|
||||
* LPDWORD lpNumberOfBytesTransferred,
|
||||
* LPDWORD lpCompletionKey,
|
||||
* PULONG_PTR lpCompletionKey,
|
||||
* LPOVERLAPPED *lpOverlapped,
|
||||
* DWORD dwMilliseconds
|
||||
*/
|
||||
@ -999,12 +999,12 @@ class WindowsNativeDispatcher {
|
||||
static class CompletionStatus {
|
||||
private int error;
|
||||
private int bytesTransferred;
|
||||
private int completionKey;
|
||||
private long completionKey;
|
||||
private CompletionStatus() { }
|
||||
|
||||
int error() { return error; }
|
||||
int bytesTransferred() { return bytesTransferred; }
|
||||
int completionKey() { return completionKey; }
|
||||
long completionKey() { return completionKey; }
|
||||
}
|
||||
private static native void GetQueuedCompletionStatus0(long completionPort,
|
||||
CompletionStatus status) throws WindowsException;
|
||||
@ -1013,12 +1013,12 @@ class WindowsNativeDispatcher {
|
||||
* PostQueuedCompletionStatus(
|
||||
* HANDLE CompletionPort,
|
||||
* DWORD dwNumberOfBytesTransferred,
|
||||
* DWORD dwCompletionKey,
|
||||
* ULONG_PTR dwCompletionKey,
|
||||
* LPOVERLAPPED lpOverlapped
|
||||
* )
|
||||
*/
|
||||
static native void PostQueuedCompletionStatus(long completionPort,
|
||||
int completionKey) throws WindowsException;
|
||||
long completionKey) throws WindowsException;
|
||||
|
||||
/**
|
||||
* ReadDirectoryChangesW(
|
||||
|
||||
@ -41,6 +41,7 @@ import static sun.nio.fs.WindowsConstants.*;
|
||||
class WindowsWatchService
|
||||
extends AbstractWatchService
|
||||
{
|
||||
private final static int WAKEUP_COMPLETION_KEY = 0;
|
||||
private final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
// background thread to service I/O completion port
|
||||
@ -83,7 +84,7 @@ class WindowsWatchService
|
||||
*/
|
||||
private class WindowsWatchKey extends AbstractWatchKey {
|
||||
// file key (used to detect existing registrations)
|
||||
private FileKey fileKey;
|
||||
private final FileKey fileKey;
|
||||
|
||||
// handle to directory
|
||||
private volatile long handle = INVALID_HANDLE_VALUE;
|
||||
@ -223,8 +224,7 @@ class WindowsWatchService
|
||||
FileKey other = (FileKey)obj;
|
||||
if (this.volSerialNumber != other.volSerialNumber) return false;
|
||||
if (this.fileIndexHigh != other.fileIndexHigh) return false;
|
||||
if (this.fileIndexLow != other.fileIndexLow) return false;
|
||||
return true;
|
||||
return this.fileIndexLow == other.fileIndexLow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,6 +268,7 @@ class WindowsWatchService
|
||||
private static final short OFFSETOF_FILENAME = 12;
|
||||
|
||||
// size of per-directory buffer for events (FIXME - make this configurable)
|
||||
// Need to be less than 4*16384 = 65536. DWORD align.
|
||||
private static final int CHANGES_BUFFER_SIZE = 16 * 1024;
|
||||
|
||||
private final WindowsFileSystem fs;
|
||||
@ -275,27 +276,28 @@ class WindowsWatchService
|
||||
private final long port;
|
||||
|
||||
// maps completion key to WatchKey
|
||||
private final Map<Integer,WindowsWatchKey> int2key;
|
||||
private final Map<Integer,WindowsWatchKey> ck2key;
|
||||
|
||||
// maps file key to WatchKey
|
||||
private final Map<FileKey,WindowsWatchKey> fk2key;
|
||||
|
||||
// unique completion key for each directory
|
||||
// native completion key capacity is 64 bits on Win64.
|
||||
private int lastCompletionKey;
|
||||
|
||||
Poller(WindowsFileSystem fs, WindowsWatchService watcher, long port) {
|
||||
this.fs = fs;
|
||||
this.watcher = watcher;
|
||||
this.port = port;
|
||||
this.int2key = new HashMap<Integer,WindowsWatchKey>();
|
||||
this.fk2key = new HashMap<FileKey,WindowsWatchKey>();
|
||||
this.ck2key = new HashMap<>();
|
||||
this.fk2key = new HashMap<>();
|
||||
this.lastCompletionKey = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void wakeup() throws IOException {
|
||||
try {
|
||||
PostQueuedCompletionStatus(port, 0);
|
||||
PostQueuedCompletionStatus(port, WAKEUP_COMPLETION_KEY);
|
||||
} catch (WindowsException x) {
|
||||
throw new IOException(x.getMessage());
|
||||
}
|
||||
@ -322,7 +324,6 @@ class WindowsWatchService
|
||||
for (WatchEvent.Modifier modifier: modifiers) {
|
||||
if (modifier == ExtendedWatchEventModifier.FILE_TREE) {
|
||||
watchSubtree = true;
|
||||
continue;
|
||||
} else {
|
||||
if (modifier == null)
|
||||
return new NullPointerException();
|
||||
@ -333,7 +334,7 @@ class WindowsWatchService
|
||||
}
|
||||
|
||||
// open directory
|
||||
long handle = -1L;
|
||||
long handle;
|
||||
try {
|
||||
handle = CreateFile(dir.getPathForWin32Calls(),
|
||||
FILE_LIST_DIRECTORY,
|
||||
@ -347,7 +348,7 @@ class WindowsWatchService
|
||||
boolean registered = false;
|
||||
try {
|
||||
// read attributes and check file is a directory
|
||||
WindowsFileAttributes attrs = null;
|
||||
WindowsFileAttributes attrs;
|
||||
try {
|
||||
attrs = WindowsFileAttributes.readAttributes(handle);
|
||||
} catch (WindowsException x) {
|
||||
@ -370,9 +371,10 @@ class WindowsWatchService
|
||||
return existing;
|
||||
}
|
||||
|
||||
// unique completion key (skip 0)
|
||||
// Can overflow the int type capacity.
|
||||
// Skip WAKEUP_COMPLETION_KEY value.
|
||||
int completionKey = ++lastCompletionKey;
|
||||
if (completionKey == 0)
|
||||
if (completionKey == WAKEUP_COMPLETION_KEY)
|
||||
completionKey = ++lastCompletionKey;
|
||||
|
||||
// associate handle with completion port
|
||||
@ -418,13 +420,13 @@ class WindowsWatchService
|
||||
// 1. remove mapping from old completion key to existing watch key
|
||||
// 2. release existing key's resources (handle/buffer)
|
||||
// 3. re-initialize key with new handle/buffer
|
||||
int2key.remove(existing.completionKey());
|
||||
ck2key.remove(existing.completionKey());
|
||||
existing.releaseResources();
|
||||
watchKey = existing.init(handle, events, watchSubtree, buffer,
|
||||
countAddress, overlappedAddress, completionKey);
|
||||
}
|
||||
// map completion map to watch key
|
||||
int2key.put(completionKey, watchKey);
|
||||
ck2key.put(completionKey, watchKey);
|
||||
|
||||
registered = true;
|
||||
return watchKey;
|
||||
@ -440,7 +442,7 @@ class WindowsWatchService
|
||||
WindowsWatchKey key = (WindowsWatchKey)obj;
|
||||
if (key.isValid()) {
|
||||
fk2key.remove(key.fileKey());
|
||||
int2key.remove(key.completionKey());
|
||||
ck2key.remove(key.completionKey());
|
||||
key.invalidate();
|
||||
}
|
||||
}
|
||||
@ -449,11 +451,11 @@ class WindowsWatchService
|
||||
@Override
|
||||
void implCloseAll() {
|
||||
// cancel all keys
|
||||
for (Map.Entry<Integer,WindowsWatchKey> entry: int2key.entrySet()) {
|
||||
for (Map.Entry<Integer, WindowsWatchKey> entry: ck2key.entrySet()) {
|
||||
entry.getValue().invalidate();
|
||||
}
|
||||
fk2key.clear();
|
||||
int2key.clear();
|
||||
ck2key.clear();
|
||||
|
||||
// close I/O completion port
|
||||
CloseHandle(port);
|
||||
@ -517,7 +519,7 @@ class WindowsWatchService
|
||||
@Override
|
||||
public void run() {
|
||||
for (;;) {
|
||||
CompletionStatus info = null;
|
||||
CompletionStatus info;
|
||||
try {
|
||||
info = GetQueuedCompletionStatus(port);
|
||||
} catch (WindowsException x) {
|
||||
@ -527,7 +529,7 @@ class WindowsWatchService
|
||||
}
|
||||
|
||||
// wakeup
|
||||
if (info.completionKey() == 0) {
|
||||
if (info.completionKey() == WAKEUP_COMPLETION_KEY) {
|
||||
boolean shutdown = processRequests();
|
||||
if (shutdown) {
|
||||
return;
|
||||
@ -536,7 +538,7 @@ class WindowsWatchService
|
||||
}
|
||||
|
||||
// map completionKey to get WatchKey
|
||||
WindowsWatchKey key = int2key.get(info.completionKey());
|
||||
WindowsWatchKey key = ck2key.get((int)info.completionKey());
|
||||
if (key == null) {
|
||||
// We get here when a registration is changed. In that case
|
||||
// the directory is closed which causes an event with the
|
||||
@ -544,38 +546,44 @@ class WindowsWatchService
|
||||
continue;
|
||||
}
|
||||
|
||||
// ReadDirectoryChangesW failed
|
||||
if (info.error() != 0) {
|
||||
boolean criticalError = false;
|
||||
int errorCode = info.error();
|
||||
int messageSize = info.bytesTransferred();
|
||||
if (errorCode == ERROR_NOTIFY_ENUM_DIR) {
|
||||
// buffer overflow
|
||||
if (info.error() == ERROR_NOTIFY_ENUM_DIR) {
|
||||
key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
|
||||
} else {
|
||||
// other error so cancel key
|
||||
implCancelKey(key);
|
||||
key.signal();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// process the events
|
||||
if (info.bytesTransferred() > 0) {
|
||||
processEvents(key, info.bytesTransferred());
|
||||
} else {
|
||||
// insufficient buffer size
|
||||
key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
|
||||
}
|
||||
} else if (errorCode != 0 && errorCode != ERROR_MORE_DATA) {
|
||||
// ReadDirectoryChangesW failed
|
||||
criticalError = true;
|
||||
} else {
|
||||
// ERROR_MORE_DATA is a warning about incomplite
|
||||
// data transfer over TCP/UDP stack. For the case
|
||||
// [messageSize] is zero in the most of cases.
|
||||
|
||||
// start read for next batch of changes
|
||||
try {
|
||||
ReadDirectoryChangesW(key.handle(),
|
||||
key.buffer().address(),
|
||||
CHANGES_BUFFER_SIZE,
|
||||
key.watchSubtree(),
|
||||
ALL_FILE_NOTIFY_EVENTS,
|
||||
key.countAddress(),
|
||||
key.overlappedAddress());
|
||||
} catch (WindowsException x) {
|
||||
// no choice but to cancel key
|
||||
if (messageSize > 0) {
|
||||
// process non-empty events.
|
||||
processEvents(key, messageSize);
|
||||
} else if (errorCode == 0) {
|
||||
// insufficient buffer size
|
||||
// not described, but can happen.
|
||||
key.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
|
||||
}
|
||||
|
||||
// start read for next batch of changes
|
||||
try {
|
||||
ReadDirectoryChangesW(key.handle(),
|
||||
key.buffer().address(),
|
||||
CHANGES_BUFFER_SIZE,
|
||||
key.watchSubtree(),
|
||||
ALL_FILE_NOTIFY_EVENTS,
|
||||
key.countAddress(),
|
||||
key.overlappedAddress());
|
||||
} catch (WindowsException x) {
|
||||
// no choice but to cancel key
|
||||
criticalError = true;
|
||||
}
|
||||
}
|
||||
if (criticalError) {
|
||||
implCancelKey(key);
|
||||
key.signal();
|
||||
}
|
||||
|
||||
@ -80,42 +80,24 @@ public class Ktab {
|
||||
} else {
|
||||
ktab.processArgs(args);
|
||||
}
|
||||
try {
|
||||
ktab.table = KeyTab.getInstance(ktab.name);
|
||||
if (ktab.table.isMissing() && ktab.action != 'a') {
|
||||
if (ktab.name == null) {
|
||||
// ktab.admin = new KeyTabAdmin(); // use the default keytab.
|
||||
ktab.table = KeyTab.getInstance();
|
||||
if (ktab.table == null) {
|
||||
if (ktab.action == 'a') {
|
||||
ktab.table = KeyTab.create();
|
||||
} else {
|
||||
System.out.println("No default key table exists.");
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
System.out.println("No default key table exists.");
|
||||
} else {
|
||||
if ((ktab.action != 'a') &&
|
||||
!(new File(ktab.name)).exists()) {
|
||||
System.out.println("Key table " +
|
||||
ktab.name + " does not exist.");
|
||||
System.exit(-1);
|
||||
} else {
|
||||
ktab.table = KeyTab.getInstance(ktab.name);
|
||||
}
|
||||
if (ktab.table == null) {
|
||||
if (ktab.action == 'a') {
|
||||
ktab.table = KeyTab.create(ktab.name);
|
||||
} else {
|
||||
System.out.println("The format of key table " +
|
||||
ktab.name + " is incorrect.");
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
System.out.println("Key table " +
|
||||
ktab.name + " does not exist.");
|
||||
}
|
||||
} catch (RealmException e) {
|
||||
System.err.println("Error loading key table.");
|
||||
System.exit(-1);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error loading key table.");
|
||||
}
|
||||
if (!ktab.table.isValid()) {
|
||||
if (ktab.name == null) {
|
||||
System.out.println("The format of the default key table " +
|
||||
" is incorrect.");
|
||||
} else {
|
||||
System.out.println("The format of key table " +
|
||||
ktab.name + " is incorrect.");
|
||||
}
|
||||
System.exit(-1);
|
||||
}
|
||||
switch (ktab.action) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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
|
||||
@ -199,7 +199,7 @@ static BOOL getFileInformation(const WCHAR *path,
|
||||
|
||||
/**
|
||||
* If the given attributes are the attributes of a reparse point, then
|
||||
* read and return the attributes of the final target.
|
||||
* read and return the attributes of the special cases.
|
||||
*/
|
||||
DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
|
||||
{
|
||||
@ -213,6 +213,28 @@ DWORD getFinalAttributesIfReparsePoint(WCHAR *path, DWORD a)
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take special cases into account when retrieving the attributes
|
||||
* of path
|
||||
*/
|
||||
DWORD getFinalAttributes(WCHAR *path)
|
||||
{
|
||||
DWORD attr = INVALID_FILE_ATTRIBUTES;
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA wfad;
|
||||
WIN32_FIND_DATAW wfd;
|
||||
HANDLE h;
|
||||
|
||||
if (GetFileAttributesExW(path, GetFileExInfoStandard, &wfad)) {
|
||||
attr = getFinalAttributesIfReparsePoint(path, wfad.dwFileAttributes);
|
||||
} else if (GetLastError() == ERROR_SHARING_VIOLATION &&
|
||||
(h = FindFirstFileW(path, &wfd)) != INVALID_HANDLE_VALUE) {
|
||||
attr = getFinalAttributesIfReparsePoint(path, wfd.dwFileAttributes);
|
||||
CloseHandle(h);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this,
|
||||
jstring pathname)
|
||||
@ -337,38 +359,21 @@ JNIEXPORT jint JNICALL
|
||||
Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this,
|
||||
jobject file)
|
||||
{
|
||||
|
||||
jint rv = 0;
|
||||
jint pathlen;
|
||||
|
||||
/* both pagefile.sys and hiberfil.sys have length 12 */
|
||||
#define SPECIALFILE_NAMELEN 12
|
||||
|
||||
WCHAR *pathbuf = fileToNTPath(env, file, ids.path);
|
||||
WIN32_FILE_ATTRIBUTE_DATA wfad;
|
||||
if (pathbuf == NULL)
|
||||
return rv;
|
||||
if (!isReservedDeviceNameW(pathbuf)) {
|
||||
if (GetFileAttributesExW(pathbuf, GetFileExInfoStandard, &wfad)) {
|
||||
DWORD a = getFinalAttributesIfReparsePoint(pathbuf, wfad.dwFileAttributes);
|
||||
if (a != INVALID_FILE_ATTRIBUTES) {
|
||||
rv = (java_io_FileSystem_BA_EXISTS
|
||||
| ((a & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? java_io_FileSystem_BA_DIRECTORY
|
||||
: java_io_FileSystem_BA_REGULAR)
|
||||
| ((a & FILE_ATTRIBUTE_HIDDEN)
|
||||
? java_io_FileSystem_BA_HIDDEN : 0));
|
||||
}
|
||||
} else { /* pagefile.sys is a special case */
|
||||
if (GetLastError() == ERROR_SHARING_VIOLATION) {
|
||||
rv = java_io_FileSystem_BA_EXISTS;
|
||||
if ((pathlen = (jint)wcslen(pathbuf)) >= SPECIALFILE_NAMELEN &&
|
||||
(_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
|
||||
L"pagefile.sys") == 0) ||
|
||||
(_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN,
|
||||
L"hiberfil.sys") == 0))
|
||||
rv |= java_io_FileSystem_BA_REGULAR;
|
||||
}
|
||||
DWORD a = getFinalAttributes(pathbuf);
|
||||
if (a != INVALID_FILE_ATTRIBUTES) {
|
||||
rv = (java_io_FileSystem_BA_EXISTS
|
||||
| ((a & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? java_io_FileSystem_BA_DIRECTORY
|
||||
: java_io_FileSystem_BA_REGULAR)
|
||||
| ((a & FILE_ATTRIBUTE_HIDDEN)
|
||||
? java_io_FileSystem_BA_HIDDEN : 0));
|
||||
}
|
||||
}
|
||||
free(pathbuf);
|
||||
|
||||
@ -162,7 +162,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this)
|
||||
}
|
||||
completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
|
||||
completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
|
||||
completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
|
||||
completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "J");
|
||||
|
||||
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$BackupResult");
|
||||
if (clazz == NULL) {
|
||||
@ -1169,12 +1169,11 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetFinalPathNameByHandle(JNIEnv* env,
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this,
|
||||
jlong fileHandle, jlong existingPort, jint completionKey)
|
||||
jlong fileHandle, jlong existingPort, jlong completionKey)
|
||||
{
|
||||
ULONG_PTR ck = completionKey;
|
||||
HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle),
|
||||
(HANDLE)jlong_to_ptr(existingPort),
|
||||
ck,
|
||||
(ULONG_PTR)completionKey,
|
||||
0);
|
||||
if (port == NULL) {
|
||||
throwWindowsException(env, GetLastError());
|
||||
@ -1203,21 +1202,20 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env,
|
||||
(*env)->SetIntField(env, obj, completionStatus_error, ioResult);
|
||||
(*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
|
||||
(jint)bytesTransferred);
|
||||
(*env)->SetIntField(env, obj, completionStatus_completionKey,
|
||||
(jint)completionKey);
|
||||
|
||||
(*env)->SetLongField(env, obj, completionStatus_completionKey,
|
||||
(jlong)completionKey);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, jclass this,
|
||||
jlong completionPort, jint completionKey)
|
||||
jlong completionPort, jlong completionKey)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
|
||||
(DWORD)0, /* dwNumberOfBytesTransferred */
|
||||
(DWORD)completionKey,
|
||||
(ULONG_PTR)completionKey,
|
||||
NULL); /* lpOverlapped */
|
||||
if (res == 0) {
|
||||
throwWindowsException(env, GetLastError());
|
||||
@ -1232,7 +1230,17 @@ Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclas
|
||||
BOOL res;
|
||||
BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE;
|
||||
|
||||
((LPOVERLAPPED)jlong_to_ptr(pOverlapped))->hEvent = NULL;
|
||||
/* Any unused members of [OVERLAPPED] structure should always be initialized to zero
|
||||
before the structure is used in a function call.
|
||||
Otherwise, the function may fail and return ERROR_INVALID_PARAMETER.
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx
|
||||
|
||||
The [Offset] and [OffsetHigh] members of this structure are not used.
|
||||
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx
|
||||
|
||||
[hEvent] should be zero, other fields are the return values. */
|
||||
ZeroMemory((LPOVERLAPPED)jlong_to_ptr(pOverlapped), sizeof(OVERLAPPED));
|
||||
|
||||
res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory),
|
||||
(LPVOID)jlong_to_ptr(bufferAddress),
|
||||
(DWORD)bufferLength,
|
||||
|
||||
@ -657,9 +657,12 @@ JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION)
|
||||
# Multiple by 4 the timeout numbers
|
||||
JTREG_TIMEOUT_OPTION = -timeoutFactor:4
|
||||
JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION)
|
||||
# Boost the max memory for jtreg to avoid gc thrashing
|
||||
# Set the max memory for jtreg control vm
|
||||
JTREG_MEMORY_OPTION = -J-Xmx512m
|
||||
JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION)
|
||||
# Set the max memory for jtreg target test vms
|
||||
JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m
|
||||
JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION)
|
||||
|
||||
# Make sure jtreg exists
|
||||
$(JTREG): $(JT_HOME)
|
||||
|
||||
@ -137,15 +137,12 @@ java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all
|
||||
# 8008200
|
||||
java/lang/Class/asSubclass/BasicUnit.java generic-all
|
||||
|
||||
# 8009552
|
||||
vm/verifier/TestStaticIF.java generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_management
|
||||
|
||||
# 8010897
|
||||
sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
|
||||
sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
|
||||
|
||||
############################################################################
|
||||
|
||||
@ -154,9 +151,6 @@ sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java macosx-all
|
||||
# 6959636
|
||||
javax/management/loading/LibraryLoader/LibraryLoaderTest.java windows-all
|
||||
|
||||
# 8005472
|
||||
com/sun/jmx/remote/NotificationMarshalVersions/TestSerializationMismatch.sh windows-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_math
|
||||
@ -305,9 +299,6 @@ sun/security/krb5/auto/BadKdc4.java solaris-sparcv9
|
||||
# 7194428
|
||||
sun/security/mscapi/ShortRSAKey1024.sh windows-all
|
||||
|
||||
# 8000897, vm crash
|
||||
sun/security/provider/DSA/TestAlgParameterGenerator.java generic-all
|
||||
|
||||
# 7144048, performance issue
|
||||
sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineDeadlock.java generic-all
|
||||
|
||||
@ -338,12 +329,9 @@ sun/tools/jconsole/ImmutableResourceTest.sh generic-all
|
||||
sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
|
||||
|
||||
# Tests take too long, on sparcs see 7143279
|
||||
tools/pack200/CommandLineTests.java solaris-all, macosx-all
|
||||
tools/pack200/CommandLineTests.java solaris-all, macosx-all
|
||||
tools/pack200/Pack200Test.java solaris-all, macosx-all
|
||||
|
||||
# 7150569
|
||||
tools/launcher/UnicodeTest.java macosx-all
|
||||
|
||||
# 8007410
|
||||
tools/launcher/FXLauncherTest.java linux-all
|
||||
|
||||
|
||||
@ -1,47 +1,78 @@
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardWatchEventKinds;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.nio.file.WatchService;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnectionNotification;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
public class Client {
|
||||
public static void main(String[] argv) throws Exception {
|
||||
if (argv.length != 1) throw new IllegalArgumentException("Expecting exactly one jmx url argument");
|
||||
public static void run(String url) throws Exception {
|
||||
final int notifEmittedCnt = 10;
|
||||
final CountDownLatch counter = new CountDownLatch(notifEmittedCnt);
|
||||
final Set<Long> seqSet = Collections.synchronizedSet(new HashSet<Long>());
|
||||
final AtomicBoolean duplNotification = new AtomicBoolean();
|
||||
|
||||
JMXServiceURL serverUrl = new JMXServiceURL(argv[0]);
|
||||
JMXServiceURL serverUrl = new JMXServiceURL(url);
|
||||
|
||||
ObjectName name = new ObjectName("test", "foo", "bar");
|
||||
JMXConnector jmxConnector = JMXConnectorFactory.connect(serverUrl);
|
||||
System.out.println("client connected");
|
||||
jmxConnector.addConnectionNotificationListener(new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(Notification notification, Object handback) {
|
||||
System.err.println("no!" + notification);
|
||||
System.out.println("connection notification: " + notification);
|
||||
if (!seqSet.add(notification.getSequenceNumber())) {
|
||||
duplNotification.set(true);
|
||||
}
|
||||
if (notification.getType().equals(JMXConnectionNotification.NOTIFS_LOST)) {
|
||||
long lostNotifs = ((Long)((JMXConnectionNotification)notification).getUserData()).longValue();
|
||||
for(int i=0;i<lostNotifs;i++) {
|
||||
counter.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null, null);
|
||||
MBeanServerConnection jmxServer = jmxConnector.getMBeanServerConnection();
|
||||
|
||||
jmxServer.addNotificationListener(name, new NotificationListener() {
|
||||
@Override
|
||||
public void handleNotification(Notification notification, Object handback) {
|
||||
System.out.println("client got:" + notification);
|
||||
System.out.println("client got: " + notification);
|
||||
if (!seqSet.add(notification.getSequenceNumber())) {
|
||||
duplNotification.set(true);
|
||||
}
|
||||
counter.countDown();
|
||||
}
|
||||
}, null, null);
|
||||
|
||||
for(int i=0;i<10;i++) {
|
||||
System.out.println("client invoking foo");
|
||||
System.out.println("client invoking foo (" + notifEmittedCnt + " times)");
|
||||
for(int i=0;i<notifEmittedCnt;i++) {
|
||||
System.out.print(".");
|
||||
jmxServer.invoke(name, "foo", new Object[]{}, new String[]{});
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
System.err.println("happy!");
|
||||
System.out.println();
|
||||
try {
|
||||
System.out.println("waiting for " + notifEmittedCnt + " notifications to arrive");
|
||||
if (!counter.await(30, TimeUnit.SECONDS)) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
if (duplNotification.get()) {
|
||||
System.out.println("ERROR: received duplicated notifications");
|
||||
throw new Error("received duplicated notifications");
|
||||
}
|
||||
System.out.println("\nshutting down client");
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("ERROR: notification processing thread interrupted");
|
||||
throw new Error("notification thread interrupted unexpectedly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.BindException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.server.ExportException;
|
||||
import java.util.Random;
|
||||
@ -16,7 +11,7 @@ import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
public class Server {
|
||||
public static void main(String[] argv) throws Exception {
|
||||
public static String start() throws Exception {
|
||||
int serverPort = 12345;
|
||||
ObjectName name = new ObjectName("test", "foo", "bar");
|
||||
MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
|
||||
@ -40,7 +35,7 @@ public class Server {
|
||||
JMXServiceURL serverUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + serverPort + "/test");
|
||||
JMXConnectorServer jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(serverUrl, null, jmxServer);
|
||||
jmxConnector.start();
|
||||
System.out.println(serverUrl);
|
||||
System.err.println("server listening on " + serverUrl);
|
||||
|
||||
return serverUrl.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Tests for the RMI unmarshalling errors not to cause silent failure.
|
||||
* @author Jaroslav Bachorik
|
||||
* @bug 6937053 8005472
|
||||
*
|
||||
* @run clean TestSerializationMismatch
|
||||
* @run main TestSerializationMismatch
|
||||
*
|
||||
*/
|
||||
public class TestSerializationMismatch {
|
||||
static final String clientDir = "Client";
|
||||
static final String serverDir = "Server";
|
||||
static final String testSrc = System.getProperty("test.src");
|
||||
static final String testSrcDir = testSrc != null ? testSrc : ".";
|
||||
static final String testSrcClientDir = testSrcDir + File.separator + clientDir + File.separator;
|
||||
static final String testSrcServerDir = testSrcDir + File.separator + serverDir + File.separator;
|
||||
static final String testClasses = System.getProperty("test.classes");
|
||||
static final String testClassesDir = testClasses != null ? testClasses : ".";
|
||||
static final String testClassesClientDir = testClassesDir + File.separator + clientDir + File.separator;
|
||||
static final String testClassesServerDir = testClassesDir + File.separator + serverDir + File.separator;
|
||||
|
||||
static final boolean debug = true;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
setup();
|
||||
|
||||
compileClient();
|
||||
compileServer();
|
||||
|
||||
debug("starting server");
|
||||
String url = startServer();
|
||||
debug("server started and listening on " + url);
|
||||
debug("starting client");
|
||||
startClient(url);
|
||||
}
|
||||
|
||||
static void setup() {
|
||||
debug("setting up the output dirs");
|
||||
cleanupDir(testClassesClientDir);
|
||||
cleanupDir(testClassesServerDir);
|
||||
}
|
||||
|
||||
static void cleanupDir(String path) {
|
||||
debug("cleaning " + path);
|
||||
File dir = new File(path);
|
||||
if (dir.exists()) {
|
||||
for(File src : dir.listFiles()) {
|
||||
boolean rslt = src.delete();
|
||||
debug((rslt == false ? "not " : "") + "deleted " + src);
|
||||
}
|
||||
} else {
|
||||
dir.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
static void compileClient() {
|
||||
debug("compiling client");
|
||||
compile("-d" , testClassesClientDir,
|
||||
"-sourcepath", testSrcClientDir,
|
||||
testSrcClientDir + "Client.java",
|
||||
testSrcClientDir + "ConfigKey.java",
|
||||
testSrcClientDir + "TestNotification.java");
|
||||
}
|
||||
|
||||
static void compileServer() {
|
||||
debug("compiling server");
|
||||
compile("-d" , testClassesServerDir,
|
||||
"-sourcepath", testSrcServerDir,
|
||||
testSrcServerDir + "Server.java",
|
||||
testSrcServerDir + "ConfigKey.java",
|
||||
testSrcServerDir + "TestNotification.java",
|
||||
testSrcServerDir + "Ste.java",
|
||||
testSrcServerDir + "SteMBean.java");
|
||||
}
|
||||
|
||||
static String startServer() throws Exception {
|
||||
ClassLoader serverCL = customCL(testClassesServerDir);
|
||||
|
||||
Class serverClz = serverCL.loadClass("Server");
|
||||
Method startMethod = serverClz.getMethod("start");
|
||||
return (String)startMethod.invoke(null);
|
||||
}
|
||||
|
||||
static void startClient(String url) throws Exception {
|
||||
ClassLoader clientCL = customCL(testClassesClientDir);
|
||||
|
||||
Thread.currentThread().setContextClassLoader(clientCL);
|
||||
Class clientClz = clientCL.loadClass("Client");
|
||||
Method runMethod = clientClz.getMethod("run", String.class);
|
||||
runMethod.invoke(null, url);
|
||||
}
|
||||
|
||||
static ClassLoader customCL(String classDir) throws Exception {
|
||||
return new URLClassLoader(
|
||||
new URL[]{
|
||||
new File(classDir).toURI().toURL()
|
||||
},
|
||||
TestSerializationMismatch.class.getClassLoader()
|
||||
);
|
||||
}
|
||||
|
||||
static void debug(Object message) {
|
||||
if (debug) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
|
||||
/* run javac <args> */
|
||||
static void compile(String... args) {
|
||||
debug("Running: javac " + Arrays.toString(args));
|
||||
if (com.sun.tools.javac.Main.compile(args) != 0) {
|
||||
throw new RuntimeException("javac failed: args=" + Arrays.toString(args));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# @test
|
||||
# @summary Tests for the RMI unmarshalling errors not to cause silent failure.
|
||||
# @author Jaroslav Bachorik
|
||||
# @bug 6937053
|
||||
#
|
||||
# @run shell TestSerializationMismatch.sh
|
||||
#
|
||||
|
||||
#set -x
|
||||
|
||||
#Set appropriate jdk
|
||||
#
|
||||
|
||||
if [ ! -z "${TESTJAVA}" ] ; then
|
||||
jdk="$TESTJAVA"
|
||||
else
|
||||
echo "--Error: TESTJAVA must be defined as the pathname of a jdk to test."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER_TESTCLASSES=$TESTCLASSES/Server
|
||||
CLIENT_TESTCLASSES=$TESTCLASSES/Client
|
||||
|
||||
URL_PATH=$SERVER_TESTCLASSES/jmxurl
|
||||
|
||||
rm $URL_PATH
|
||||
|
||||
mkdir -p $SERVER_TESTCLASSES
|
||||
mkdir -p $CLIENT_TESTCLASSES
|
||||
|
||||
$TESTJAVA/bin/javac -d $CLIENT_TESTCLASSES $TESTSRC/Client/ConfigKey.java $TESTSRC/Client/TestNotification.java $TESTSRC/Client/Client.java
|
||||
$TESTJAVA/bin/javac -d $SERVER_TESTCLASSES $TESTSRC/Server/ConfigKey.java $TESTSRC/Server/TestNotification.java $TESTSRC/Server/SteMBean.java $TESTSRC/Server/Ste.java $TESTSRC/Server/Server.java
|
||||
|
||||
startServer()
|
||||
{
|
||||
($TESTJAVA/bin/java -classpath $SERVER_TESTCLASSES Server) 1>$URL_PATH &
|
||||
SERVER_PID=$!
|
||||
}
|
||||
|
||||
runClient()
|
||||
{
|
||||
while true
|
||||
do
|
||||
[ -f $URL_PATH ] && break
|
||||
sleep 2
|
||||
done
|
||||
read JMXURL < $URL_PATH
|
||||
|
||||
HAS_ERRORS=`($TESTJAVA/bin/java -classpath $CLIENT_TESTCLASSES Client $JMXURL) 2>&1 | grep -i "SEVERE: Failed to fetch notification, stopping thread. Error is: java.rmi.UnmarshalException"`
|
||||
}
|
||||
|
||||
startServer
|
||||
|
||||
runClient
|
||||
|
||||
sleep 1 # wait for notifications to arrive
|
||||
|
||||
kill "$SERVER_PID"
|
||||
|
||||
if [ -z "$HAS_ERRORS" ]
|
||||
then
|
||||
echo "Test PASSED"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Test FAILED"
|
||||
echo $HAS_ERRORS 1>&2
|
||||
exit 1
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
|
||||
@ -46,6 +46,11 @@ public class IsHidden {
|
||||
Files.getFileAttributeView(f.toPath(), DosFileAttributeView.class).setHidden(value);
|
||||
}
|
||||
|
||||
private static void checkHidden(File f) {
|
||||
if (!f.isHidden())
|
||||
throw new RuntimeException(f + " should be hidden");
|
||||
}
|
||||
|
||||
private static void testWin32() throws Exception {
|
||||
File f = new File(dir, "test");
|
||||
f.deleteOnExit();
|
||||
@ -58,6 +63,11 @@ public class IsHidden {
|
||||
}
|
||||
ck(".foo", false);
|
||||
ck("foo", false);
|
||||
|
||||
File pagefile = new File("C:\\pagefile.sys");
|
||||
File hiberfil = new File("C:\\hiberfil.sys");
|
||||
if (pagefile.exists()) checkHidden(pagefile);
|
||||
if (hiberfil.exists()) checkHidden(hiberfil);
|
||||
}
|
||||
|
||||
private static void testUnix() throws Exception {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6402006 7030573
|
||||
* @bug 6402006 7030573 8011136
|
||||
* @summary Test if available returns correct value when reading
|
||||
* a large file.
|
||||
*/
|
||||
@ -61,9 +61,12 @@ public class LargeFileAvailable {
|
||||
remaining -= skipBytes(fis, bigSkip, remaining);
|
||||
remaining -= skipBytes(fis, 10L, remaining);
|
||||
remaining -= skipBytes(fis, bigSkip, remaining);
|
||||
if (fis.available() != (int) remaining) {
|
||||
throw new RuntimeException("available() returns "
|
||||
+ fis.available() + " but expected " + remaining);
|
||||
int expected = (remaining >= Integer.MAX_VALUE)
|
||||
? Integer.MAX_VALUE
|
||||
: (remaining > 0 ? (int) remaining : 0);
|
||||
if (fis.available() != expected) {
|
||||
throw new RuntimeException("available() returns "
|
||||
+ fis.available() + " but expected " + expected);
|
||||
}
|
||||
} finally {
|
||||
file.delete();
|
||||
@ -77,19 +80,18 @@ public class LargeFileAvailable {
|
||||
long skip = is.skip(toSkip);
|
||||
if (skip != toSkip) {
|
||||
throw new RuntimeException("skip() returns " + skip
|
||||
+ " but expected " + toSkip);
|
||||
+ " but expected " + toSkip);
|
||||
}
|
||||
long remaining = avail - skip;
|
||||
int expected = remaining >= Integer.MAX_VALUE
|
||||
? Integer.MAX_VALUE
|
||||
: (int) remaining;
|
||||
int expected = (remaining >= Integer.MAX_VALUE)
|
||||
? Integer.MAX_VALUE
|
||||
: (remaining > 0 ? (int) remaining : 0);
|
||||
|
||||
System.out.println("Skipped " + skip + " bytes "
|
||||
+ " available() returns " + expected +
|
||||
" remaining=" + remaining);
|
||||
System.out.println("Skipped " + skip + " bytes, available() returns "
|
||||
+ expected + ", remaining " + remaining);
|
||||
if (is.available() != expected) {
|
||||
throw new RuntimeException("available() returns "
|
||||
+ is.available() + " but expected " + expected);
|
||||
+ is.available() + " but expected " + expected);
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8010837
|
||||
* @bug 8010837 8011136
|
||||
* @summary Test if available returns correct value when skipping beyond
|
||||
* the end of a file.
|
||||
* @author Dan Xu
|
||||
@ -42,6 +42,7 @@ public class NegativeAvailable {
|
||||
public static void main(String[] args) throws IOException {
|
||||
final int SIZE = 10;
|
||||
final int SKIP = 5;
|
||||
final int NEGATIVE_SKIP = -5;
|
||||
|
||||
// Create a temporary file with size of 10 bytes.
|
||||
Path tmp = Files.createTempFile(null, null);
|
||||
@ -56,12 +57,15 @@ public class NegativeAvailable {
|
||||
try (FileInputStream fis = new FileInputStream(tempFile)) {
|
||||
if (tempFile.length() != SIZE) {
|
||||
throw new RuntimeException("unexpected file size = "
|
||||
+ tempFile.length());
|
||||
+ tempFile.length());
|
||||
}
|
||||
long space = skipBytes(fis, SKIP, SIZE);
|
||||
space = skipBytes(fis, NEGATIVE_SKIP, space);
|
||||
space = skipBytes(fis, SKIP, space);
|
||||
space = skipBytes(fis, SKIP, space);
|
||||
space = skipBytes(fis, SKIP, space);
|
||||
space = skipBytes(fis, NEGATIVE_SKIP, space);
|
||||
space = skipBytes(fis, NEGATIVE_SKIP, space);
|
||||
}
|
||||
Files.deleteIfExists(tmp);
|
||||
}
|
||||
@ -74,17 +78,18 @@ public class NegativeAvailable {
|
||||
long skip = fis.skip(toSkip);
|
||||
if (skip != toSkip) {
|
||||
throw new RuntimeException("skip() returns " + skip
|
||||
+ " but expected " + toSkip);
|
||||
+ " but expected " + toSkip);
|
||||
}
|
||||
long remaining = space - toSkip;
|
||||
long newSpace = space - toSkip;
|
||||
long remaining = newSpace > 0 ? newSpace : 0;
|
||||
int avail = fis.available();
|
||||
if (avail != remaining) {
|
||||
throw new RuntimeException("available() returns " + avail
|
||||
+ " but expected " + remaining);
|
||||
+ " but expected " + remaining);
|
||||
}
|
||||
|
||||
System.out.println("Skipped " + skip + " bytes "
|
||||
+ " available() returns " + avail);
|
||||
return remaining;
|
||||
+ " available() returns " + avail);
|
||||
return newSpace;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
|
||||
@ -40,7 +40,7 @@ public class General {
|
||||
|
||||
|
||||
/* Generate a filename unique to this run */
|
||||
private static String gensym() {
|
||||
protected static String gensym() {
|
||||
return "x." + ++gensymCounter;
|
||||
}
|
||||
|
||||
@ -127,9 +127,9 @@ public class General {
|
||||
}
|
||||
for (int i = 0; i < dl.length; i++) {
|
||||
File f = new File(d, dl[i]);
|
||||
if (f.isDirectory() && f.canRead()) {
|
||||
if (f.isDirectory()) {
|
||||
String[] dl2 = f.list();
|
||||
if (dl2.length >= 250) {
|
||||
if (dl2 == null || dl2.length >= 250) {
|
||||
/* Heuristic to avoid scanning huge directories */
|
||||
continue;
|
||||
}
|
||||
@ -277,8 +277,8 @@ public class General {
|
||||
{
|
||||
check(ans, ask + slash);
|
||||
checkNames(depth, create,
|
||||
ans.endsWith(File.separator) ? ans : ans + File.separator,
|
||||
ask + slash);
|
||||
ans,
|
||||
ask);
|
||||
}
|
||||
|
||||
|
||||
@ -308,13 +308,16 @@ public class General {
|
||||
String ans, String ask)
|
||||
throws Exception
|
||||
{
|
||||
ans = ans.endsWith(File.separator) ? ans : ans + File.separator;
|
||||
ask = ask.endsWith(File.separator) ? ask : ask + File.separator;
|
||||
|
||||
int d = depth - 1;
|
||||
File f = new File(ans);
|
||||
String n;
|
||||
|
||||
/* Normal name */
|
||||
if (f.exists()) {
|
||||
if (f.isDirectory() && f.canRead()) {
|
||||
if (f.isDirectory() && f.list() != null) {
|
||||
if ((n = findSomeFile(ans, create)) != null)
|
||||
checkSlashes(d, create, ans + n, ask + n);
|
||||
if ((n = findSomeDir(ans, create)) != null)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
@bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520
|
||||
@bug 4032066 4039597 4046914 4054511 4065189 4109131 4875229 6983520 8009258
|
||||
@summary General exhaustive test of win32 pathname handling
|
||||
@author Mark Reinhold
|
||||
|
||||
@ -31,8 +31,6 @@
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class GeneralWin32 extends General {
|
||||
|
||||
@ -49,25 +47,29 @@ public class GeneralWin32 extends General {
|
||||
private static final String EXISTENT_UNC_SHARE = "pcdist";
|
||||
private static final String NONEXISTENT_UNC_HOST = "non-existent-unc-host";
|
||||
private static final String NONEXISTENT_UNC_SHARE = "bogus-share";
|
||||
|
||||
private static final int DEPTH = 2;
|
||||
private static String baseDir = null;
|
||||
private static String userDir = null;
|
||||
|
||||
/* Pathnames relative to working directory */
|
||||
|
||||
private static void checkCaseLookup(String ud) throws IOException {
|
||||
private static void checkCaseLookup() throws IOException {
|
||||
/* Use long names here to avoid 8.3 format, which Samba servers often
|
||||
force to lowercase */
|
||||
File d = new File("XyZzY0123", "FOO_bar_BAZ");
|
||||
File f = new File(d, "GLORPified");
|
||||
String relative = baseDir.substring(userDir.length() + 1);
|
||||
File d1 = new File(relative, "XyZzY0123");
|
||||
File d2 = new File(d1, "FOO_bar_BAZ");
|
||||
File f = new File(d2, "GLORPified");
|
||||
if (!f.exists()) {
|
||||
if (!d.exists()) {
|
||||
if (!d.mkdirs()) {
|
||||
throw new RuntimeException("Can't create directory " + d);
|
||||
if (!d2.exists()) {
|
||||
if (!d2.mkdirs()) {
|
||||
throw new RuntimeException("Can't create directory " + d2);
|
||||
}
|
||||
}
|
||||
OutputStream o = new FileOutputStream(f);
|
||||
o.close();
|
||||
}
|
||||
File f2 = new File(d.getParent(), "mumble"); /* For later ud tests */
|
||||
File f2 = new File(d2.getParent(), "mumble"); /* For later ud tests */
|
||||
if (!f2.exists()) {
|
||||
OutputStream o = new FileOutputStream(f2);
|
||||
o.close();
|
||||
@ -75,11 +77,11 @@ public class GeneralWin32 extends General {
|
||||
|
||||
/* Computing the canonical path of a Win32 file should expose the true
|
||||
case of filenames, rather than just using the input case */
|
||||
File y = new File(ud, f.getPath());
|
||||
File y = new File(userDir, f.getPath());
|
||||
String ans = y.getPath();
|
||||
check(ans, "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
|
||||
check(ans, "xyzzy0123\\foo_bar_baz\\glorpified");
|
||||
check(ans, "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
|
||||
check(ans, relative + "\\" + "XyZzY0123\\FOO_bar_BAZ\\GLORPified");
|
||||
check(ans, relative + "\\" + "xyzzy0123\\foo_bar_baz\\glorpified");
|
||||
check(ans, relative + "\\" + "XYZZY0123\\FOO_BAR_BAZ\\GLORPIFIED");
|
||||
}
|
||||
|
||||
private static void checkWild(File f) throws Exception {
|
||||
@ -91,18 +93,18 @@ public class GeneralWin32 extends General {
|
||||
throw new Exception("Wildcard path not rejected: " + f);
|
||||
}
|
||||
|
||||
private static void checkWildCards(String ud) throws Exception {
|
||||
File d = new File(ud).getCanonicalFile();
|
||||
private static void checkWildCards() throws Exception {
|
||||
File d = new File(baseDir).getCanonicalFile();
|
||||
checkWild(new File(d, "*.*"));
|
||||
checkWild(new File(d, "*.???"));
|
||||
checkWild(new File(new File(d, "*.*"), "foo"));
|
||||
}
|
||||
|
||||
private static void checkRelativePaths() throws Exception {
|
||||
String ud = System.getProperty("user.dir").replace('/', '\\');
|
||||
checkCaseLookup(ud);
|
||||
checkWildCards(ud);
|
||||
checkNames(3, true, ud + "\\", "");
|
||||
checkCaseLookup();
|
||||
checkWildCards();
|
||||
String relative = baseDir.substring(userDir.length() + 1);
|
||||
checkNames(3, true, baseDir.toString(), relative);
|
||||
}
|
||||
|
||||
|
||||
@ -134,7 +136,8 @@ public class GeneralWin32 extends General {
|
||||
String ans = exists ? df.getAbsolutePath() : d;
|
||||
if (!ans.endsWith("\\"))
|
||||
ans = ans + "\\";
|
||||
checkNames(depth, false, ans, d);
|
||||
String relative = baseDir.substring(userDir.length() + 1);
|
||||
checkNames(depth, false, ans + relative, d + relative);
|
||||
}
|
||||
|
||||
private static void checkDrivePaths() throws Exception {
|
||||
@ -149,7 +152,7 @@ public class GeneralWin32 extends General {
|
||||
String s = ("\\\\" + NONEXISTENT_UNC_HOST
|
||||
+ "\\" + NONEXISTENT_UNC_SHARE);
|
||||
ensureNon(s);
|
||||
checkSlashes(2, false, s, s);
|
||||
checkSlashes(DEPTH, false, s, s);
|
||||
|
||||
s = "\\\\" + EXISTENT_UNC_HOST + "\\" + EXISTENT_UNC_SHARE;
|
||||
if (!(new File(s)).exists()) {
|
||||
@ -158,7 +161,7 @@ public class GeneralWin32 extends General {
|
||||
return;
|
||||
}
|
||||
|
||||
checkSlashes(2, false, s, s);
|
||||
checkSlashes(DEPTH, false, s, s);
|
||||
}
|
||||
|
||||
|
||||
@ -168,9 +171,33 @@ public class GeneralWin32 extends General {
|
||||
return;
|
||||
}
|
||||
if (args.length > 0) debug = true;
|
||||
userDir = System.getProperty("user.dir");
|
||||
baseDir = initTestData(6);
|
||||
checkRelativePaths();
|
||||
checkDrivePaths();
|
||||
checkUncPaths();
|
||||
}
|
||||
|
||||
private static String initTestData(int maxDepth) throws IOException {
|
||||
File parent = new File(System.getProperty("user.dir"));
|
||||
String baseDir = null;
|
||||
maxDepth = maxDepth < DEPTH + 2 ? DEPTH + 2 : maxDepth;
|
||||
for (int i = 0; i < maxDepth; i ++) {
|
||||
File dir1 = new File(parent, gensym());
|
||||
dir1.mkdir();
|
||||
if (i != 0) {
|
||||
File dir2 = new File(parent, gensym());
|
||||
dir2.mkdir();
|
||||
File f1 = new File(parent, gensym());
|
||||
f1.createNewFile();
|
||||
File f2 = new File(parent, gensym());
|
||||
f2.createNewFile();
|
||||
}
|
||||
if (i == DEPTH + 1) {
|
||||
baseDir = dir1.getAbsolutePath();
|
||||
}
|
||||
parent = dir1;
|
||||
}
|
||||
return baseDir;
|
||||
}
|
||||
}
|
||||
|
||||
107
jdk/test/java/lang/String/StringContentEqualsBug.java
Normal file
107
jdk/test/java/lang/String/StringContentEqualsBug.java
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8014477
|
||||
* @summary test String.contentEquals(StringBuffer)
|
||||
*/
|
||||
public class StringContentEqualsBug {
|
||||
|
||||
static abstract class Task extends Thread {
|
||||
volatile StringBuffer sb;
|
||||
volatile Exception exception;
|
||||
|
||||
Task(StringBuffer sb) {
|
||||
this.sb = sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
StringBuffer sb;
|
||||
while ((sb = this.sb) != null) {
|
||||
doWith(sb);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
exception = e;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doWith(StringBuffer sb);
|
||||
}
|
||||
|
||||
static class Tester extends Task {
|
||||
Tester(StringBuffer sb) {
|
||||
super(sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWith(StringBuffer sb) {
|
||||
"AA".contentEquals(sb);
|
||||
}
|
||||
}
|
||||
|
||||
static class Disturber extends Task {
|
||||
Disturber(StringBuffer sb) {
|
||||
super(sb);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWith(StringBuffer sb) {
|
||||
sb.setLength(0);
|
||||
sb.trimToSize();
|
||||
sb.append("AA");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Task[] tasks = new Task[3];
|
||||
(tasks[0] = new Tester(sb)).start();
|
||||
for (int i = 1; i < tasks.length; i++) {
|
||||
(tasks[i] = new Disturber(sb)).start();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// wait at most 5 seconds for any of the threads to throw exception
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (Task task : tasks) {
|
||||
if (task.exception != null) {
|
||||
throw task.exception;
|
||||
}
|
||||
}
|
||||
Thread.sleep(250L);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
for (Task task : tasks) {
|
||||
task.sb = null;
|
||||
task.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8013395
|
||||
* @bug 8013395 8014814
|
||||
* @summary Test StringBuffer.toString caching
|
||||
*/
|
||||
|
||||
@ -199,6 +199,28 @@ public class ToStringCache {
|
||||
b = sb.toString();
|
||||
checkUnequal(a, b);
|
||||
|
||||
// Extra checks that append(null) works correctly
|
||||
|
||||
sb.append((String)null);
|
||||
b = sb.toString();
|
||||
checkUnequal(a, b);
|
||||
a = b;
|
||||
|
||||
sb.append((StringBuffer)null);
|
||||
b = sb.toString();
|
||||
checkUnequal(a, b);
|
||||
a = b;
|
||||
|
||||
sb.append((StringBuilder)null);
|
||||
b = sb.toString();
|
||||
checkUnequal(a, b);
|
||||
a = b;
|
||||
|
||||
sb.append((CharSequence)null);
|
||||
b = sb.toString();
|
||||
checkUnequal(a, b);
|
||||
a = b;
|
||||
|
||||
// non-mutating methods
|
||||
|
||||
// Reset to known value
|
||||
|
||||
@ -21,6 +21,11 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The -XX:MarkSweepAlwaysCompactCount=1 argument below makes sure serial gc
|
||||
* compacts the heap at every full gc so that the usage is correctly updated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4892507
|
||||
@ -28,7 +33,7 @@
|
||||
* @author Mandy Chung
|
||||
*
|
||||
* @build ResetPeakMemoryUsage MemoryUtil
|
||||
* @run main/othervm -XX:+UseSerialGC -Xmn8m ResetPeakMemoryUsage
|
||||
* @run main/othervm -XX:+UseSerialGC -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
|
||||
* @run main/othervm -XX:+UseConcMarkSweepGC -Xmn8m ResetPeakMemoryUsage
|
||||
* @run main/othervm -XX:+UseParallelGC -Xmn8m ResetPeakMemoryUsage
|
||||
* @run main/othervm -XX:+UseG1GC -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user