mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-26 18:20:28 +00:00
Merge
This commit is contained in:
commit
27809f9ecf
@ -459,7 +459,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||
# We can only compile native code after java has been compiled (since we
|
||||
# depend on generated .h files)
|
||||
$(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller/Poller.o: \
|
||||
$(BUILD_DEMO_JAVA_POLLER_COMPILE_TARGETS)
|
||||
$(BUILD_DEMO_JAVA_Poller_COMPILE_TARGET)
|
||||
|
||||
# Copy to image
|
||||
$(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt: \
|
||||
|
||||
@ -29,32 +29,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
|
||||
################################################################################
|
||||
|
||||
LIBAPPLESCRIPTENGINE_SRC := $(JDK_TOPDIR)/src/jdk.deploy.osx/macosx/native/libapplescriptengine
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBAPPLESCRIPTENGINE, \
|
||||
LIBRARY := AppleScriptEngine, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(LIBAPPLESCRIPTENGINE_SRC), \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
-I$(LIBAPPLESCRIPTENGINE_SRC) \
|
||||
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.deploy.osx, \
|
||||
DISABLED_WARNINGS_clang := implicit-function-declaration format, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LIBS := -framework Cocoa \
|
||||
-framework Carbon \
|
||||
-framework JavaNativeFoundation \
|
||||
$(JDKLIB_LIBS), \
|
||||
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libAppleScriptEngine, \
|
||||
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
|
||||
|
||||
$(BUILD_LIBAPPLESCRIPTENGINE): $(call FindLib, java.base, java)
|
||||
|
||||
TARGETS += $(BUILD_LIBAPPLESCRIPTENGINE)
|
||||
|
||||
################################################################################
|
||||
|
||||
LIBOSX_DIRS := $(JDK_TOPDIR)/src/jdk.deploy.osx/macosx/native/libosx
|
||||
LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \
|
||||
-I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp \
|
||||
|
||||
@ -177,7 +177,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
return;
|
||||
}
|
||||
byte[] buf = StringUTF16.newBytesFor(value.length);
|
||||
StringLatin1.inflateSB(value, buf, 0, count);
|
||||
StringLatin1.inflate(value, 0, buf, 0, count);
|
||||
this.value = buf;
|
||||
this.coder = UTF16;
|
||||
}
|
||||
@ -414,9 +414,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
int n = srcEnd - srcBegin;
|
||||
checkRange(dstBegin, dstBegin + n, dst.length);
|
||||
if (isLatin1()) {
|
||||
StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
} else {
|
||||
StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -980,7 +980,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (isLatin1()) {
|
||||
return StringLatin1.newString(value, start, end - start);
|
||||
}
|
||||
return StringUTF16.newStringSB(value, start, end - start);
|
||||
return StringUTF16.newString(value, start, end - start);
|
||||
}
|
||||
|
||||
private void shift(int offset, int n) {
|
||||
@ -1576,7 +1576,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (this.coder == coder) {
|
||||
System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
|
||||
} else { // this.coder == LATIN && coder == UTF16
|
||||
StringLatin1.inflateSB(value, dst, dstBegin, count);
|
||||
StringLatin1.inflate(value, 0, dst, dstBegin, count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1641,10 +1641,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (getCoder() != str.coder()) {
|
||||
inflate();
|
||||
}
|
||||
byte[] val = this.value;
|
||||
byte coder = this.coder;
|
||||
checkOffset(index + str.length(), val.length >> coder);
|
||||
str.getBytes(val, index, coder);
|
||||
str.getBytes(value, index, coder);
|
||||
}
|
||||
|
||||
private final void appendChars(char[] s, int off, int end) {
|
||||
|
||||
@ -1720,7 +1720,6 @@ public final class String
|
||||
*/
|
||||
static int indexOf(byte[] src, byte srcCoder, int srcCount,
|
||||
String tgtStr, int fromIndex) {
|
||||
|
||||
byte[] tgt = tgtStr.value;
|
||||
byte tgtCoder = tgtStr.coder();
|
||||
int tgtCount = tgtStr.length();
|
||||
@ -3103,7 +3102,7 @@ public final class String
|
||||
* If {@code offset} is negative, {@code count} is negative,
|
||||
* or {@code offset} is greater than {@code length - count}
|
||||
*/
|
||||
private static void checkBoundsOffCount(int offset, int count, int length) {
|
||||
static void checkBoundsOffCount(int offset, int count, int length) {
|
||||
if (offset < 0 || count < 0 || offset > length - count) {
|
||||
throw new StringIndexOutOfBoundsException(
|
||||
"offset " + offset + ", count " + count + ", length " + length);
|
||||
|
||||
@ -413,7 +413,7 @@ public final class StringBuilder
|
||||
public String toString() {
|
||||
// Create a copy, don't share the array
|
||||
return isLatin1() ? StringLatin1.newString(value, 0, count)
|
||||
: StringUTF16.newStringSB(value, 0, count);
|
||||
: StringUTF16.newString(value, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -36,6 +36,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
import static java.lang.String.checkOffset;
|
||||
import static java.lang.String.checkBoundsOffCount;
|
||||
|
||||
final class StringLatin1 {
|
||||
|
||||
@ -523,6 +524,8 @@ final class StringLatin1 {
|
||||
// inflatedCopy byte[] -> byte[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
|
||||
// We need a range check here because 'putChar' has no checks
|
||||
checkBoundsOffCount(dstOff, len, dst.length);
|
||||
for (int i = 0; i < len; i++) {
|
||||
StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
|
||||
}
|
||||
@ -584,17 +587,4 @@ final class StringLatin1 {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
checkOffset(srcEnd, val.length);
|
||||
getChars(val, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
|
||||
public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) {
|
||||
checkOffset(count, val.length);
|
||||
checkOffset(dstOff + count, dst.length >> 1); // dst is utf16
|
||||
inflate(val, 0, dst, dstOff, count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import static java.lang.String.UTF16;
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.checkIndex;
|
||||
import static java.lang.String.checkOffset;
|
||||
import static java.lang.String.checkBoundsOffCount;
|
||||
|
||||
final class StringUTF16 {
|
||||
|
||||
@ -156,6 +157,8 @@ final class StringUTF16 {
|
||||
// compressedCopy byte[] -> byte[]
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
|
||||
// We need a range check here because 'getChar' has no checks
|
||||
checkBoundsOffCount(srcOff, len, src.length);
|
||||
for (int i = 0; i < len; i++) {
|
||||
int c = getChar(src, srcOff++);
|
||||
if (c >>> 8 != 0) {
|
||||
@ -200,6 +203,8 @@ final class StringUTF16 {
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
// We need a range check here because 'getChar' has no checks
|
||||
checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value.length);
|
||||
for (int i = srcBegin; i < srcEnd; i++) {
|
||||
dst[dstBegin++] = getChar(value, i);
|
||||
}
|
||||
@ -909,11 +914,6 @@ final class StringUTF16 {
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
|
||||
checkOffset(srcEnd, val.length >> 1);
|
||||
getChars(val, srcBegin, srcEnd, dst, dstBegin);
|
||||
}
|
||||
|
||||
public static void putCharSB(byte[] val, int index, int c) {
|
||||
checkIndex(index, val.length >> 1);
|
||||
putChar(val, index, c);
|
||||
@ -946,11 +946,6 @@ final class StringUTF16 {
|
||||
return codePointCount(val, beginIndex, endIndex);
|
||||
}
|
||||
|
||||
public static String newStringSB(byte[] val, int index, int len) {
|
||||
checkOffset(index + len, val.length >> 1);
|
||||
return newString(val, index, len);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
private static native boolean isBigEndian();
|
||||
|
||||
@ -324,27 +324,54 @@ class InvokerBytecodeGenerator {
|
||||
emitIconstInsn((int) con);
|
||||
return;
|
||||
}
|
||||
if (con instanceof Byte) {
|
||||
emitIconstInsn((byte)con);
|
||||
return;
|
||||
}
|
||||
if (con instanceof Short) {
|
||||
emitIconstInsn((short)con);
|
||||
return;
|
||||
}
|
||||
if (con instanceof Character) {
|
||||
emitIconstInsn((char)con);
|
||||
return;
|
||||
}
|
||||
if (con instanceof Long) {
|
||||
long x = (long) con;
|
||||
if (x == (short) x) {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2L);
|
||||
short sx = (short)x;
|
||||
if (x == sx) {
|
||||
if (sx >= 0 && sx <= 1) {
|
||||
mv.visitInsn(Opcodes.LCONST_0 + (int) sx);
|
||||
} else {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2L);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (con instanceof Float) {
|
||||
float x = (float) con;
|
||||
if (x == (short) x) {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2F);
|
||||
short sx = (short)x;
|
||||
if (x == sx) {
|
||||
if (sx >= 0 && sx <= 2) {
|
||||
mv.visitInsn(Opcodes.FCONST_0 + (int) sx);
|
||||
} else {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2F);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (con instanceof Double) {
|
||||
double x = (double) con;
|
||||
if (x == (short) x) {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2D);
|
||||
short sx = (short)x;
|
||||
if (x == sx) {
|
||||
if (sx >= 0 && sx <= 1) {
|
||||
mv.visitInsn(Opcodes.DCONST_0 + (int) sx);
|
||||
} else {
|
||||
emitIconstInsn((int) x);
|
||||
mv.visitInsn(Opcodes.I2D);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -356,26 +383,16 @@ class InvokerBytecodeGenerator {
|
||||
mv.visitLdcInsn(con);
|
||||
}
|
||||
|
||||
private void emitIconstInsn(int i) {
|
||||
int opcode;
|
||||
switch (i) {
|
||||
case 0: opcode = Opcodes.ICONST_0; break;
|
||||
case 1: opcode = Opcodes.ICONST_1; break;
|
||||
case 2: opcode = Opcodes.ICONST_2; break;
|
||||
case 3: opcode = Opcodes.ICONST_3; break;
|
||||
case 4: opcode = Opcodes.ICONST_4; break;
|
||||
case 5: opcode = Opcodes.ICONST_5; break;
|
||||
default:
|
||||
if (i == (byte) i) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, i & 0xFF);
|
||||
} else if (i == (short) i) {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, (char) i);
|
||||
} else {
|
||||
mv.visitLdcInsn(i);
|
||||
}
|
||||
return;
|
||||
private void emitIconstInsn(final int cst) {
|
||||
if (cst >= -1 && cst <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + cst);
|
||||
} else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, cst);
|
||||
} else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, cst);
|
||||
} else {
|
||||
mv.visitLdcInsn(cst);
|
||||
}
|
||||
mv.visitInsn(opcode);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -61,6 +61,7 @@
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import static java.time.LocalTime.MINUTES_PER_HOUR;
|
||||
import static java.time.LocalTime.NANOS_PER_SECOND;
|
||||
import static java.time.LocalTime.SECONDS_PER_DAY;
|
||||
import static java.time.LocalTime.SECONDS_PER_HOUR;
|
||||
@ -973,7 +974,7 @@ public final class Duration
|
||||
if (multiplicand == 1) {
|
||||
return this;
|
||||
}
|
||||
return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand)));
|
||||
return create(toBigDecimalSeconds().multiply(BigDecimal.valueOf(multiplicand)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -992,7 +993,7 @@ public final class Duration
|
||||
if (divisor == 1) {
|
||||
return this;
|
||||
}
|
||||
return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN));
|
||||
return create(toBigDecimalSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1001,7 +1002,7 @@ public final class Duration
|
||||
*
|
||||
* @return the total length of the duration in seconds, with a scale of 9, not null
|
||||
*/
|
||||
private BigDecimal toSeconds() {
|
||||
private BigDecimal toBigDecimalSeconds() {
|
||||
return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));
|
||||
}
|
||||
|
||||
@ -1167,6 +1168,19 @@ public final class Duration
|
||||
return seconds / SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of seconds in this duration.
|
||||
* <p>
|
||||
* This returns the total number of whole seconds in the duration.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the whole seconds part of the length of the duration, positive or negative
|
||||
*/
|
||||
public long toSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this duration to the total length in milliseconds.
|
||||
* <p>
|
||||
@ -1201,6 +1215,100 @@ public final class Duration
|
||||
return totalNanos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of days in the duration.
|
||||
* <p>
|
||||
* This returns the total number of days in the duration by dividing the
|
||||
* number of seconds by 86400.
|
||||
* This is based on the standard definition of a day as 24 hours.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of days in the duration, may be negative
|
||||
*/
|
||||
public long toDaysPart(){
|
||||
return seconds / SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of hours part in the duration.
|
||||
* <p>
|
||||
* This returns the number of remaining hours when dividing {@link #toHours}
|
||||
* by hours in a day.
|
||||
* This is based on the standard definition of a day as 24 hours.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of hours part in the duration, may be negative
|
||||
*/
|
||||
public int toHoursPart(){
|
||||
return (int) (toHours() % 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of minutes part in the duration.
|
||||
* <p>
|
||||
* This returns the number of remaining minutes when dividing {@link #toMinutes}
|
||||
* by minutes in an hour.
|
||||
* This is based on the standard definition of an hour as 60 minutes.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of minutes parts in the duration, may be negative
|
||||
* may be negative
|
||||
*/
|
||||
public int toMinutesPart(){
|
||||
return (int) (toMinutes() % MINUTES_PER_HOUR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of seconds part in the duration.
|
||||
* <p>
|
||||
* This returns the remaining seconds when dividing {@link #toSeconds}
|
||||
* by seconds in a minute.
|
||||
* This is based on the standard definition of a minute as 60 seconds.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of seconds parts in the duration, may be negative
|
||||
*/
|
||||
public int toSecondsPart(){
|
||||
return (int) (seconds % SECONDS_PER_MINUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the number of milliseconds part of the duration.
|
||||
* <p>
|
||||
* This returns the milliseconds part by dividing the number of nanoseconds by 1,000,000.
|
||||
* The length of the duration is stored using two fields - seconds and nanoseconds.
|
||||
* The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
|
||||
* the length in seconds.
|
||||
* The total duration is defined by calling {@link #getNano()} and {@link #getSeconds()}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of milliseconds part of the duration.
|
||||
*/
|
||||
public int toMillisPart(){
|
||||
return nanos / 1000_000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nanoseconds part within seconds of the duration.
|
||||
* <p>
|
||||
* The length of the duration is stored using two fields - seconds and nanoseconds.
|
||||
* The nanoseconds part is a value from 0 to 999,999,999 that is an adjustment to
|
||||
* the length in seconds.
|
||||
* The total duration is defined by calling {@link #getNano()} and {@link #getSeconds()}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the nanoseconds within the second part of the length of the duration, from 0 to 999,999,999
|
||||
*/
|
||||
public int toNanosPart(){
|
||||
return nanos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Compares this duration to the specified {@code Duration}.
|
||||
@ -1208,7 +1316,7 @@ public final class Duration
|
||||
* The comparison is based on the total length of the durations.
|
||||
* It is "consistent with equals", as defined by {@link Comparable}.
|
||||
*
|
||||
* @param otherDuration the other duration to compare to, not null
|
||||
* @param otherDuration the other duration to compare to, not null
|
||||
* @return the comparator value, negative if less, positive if greater
|
||||
*/
|
||||
@Override
|
||||
@ -1226,7 +1334,7 @@ public final class Duration
|
||||
* <p>
|
||||
* The comparison is based on the total length of the durations.
|
||||
*
|
||||
* @param otherDuration the other duration, null returns false
|
||||
* @param otherDuration the other duration, null returns false
|
||||
* @return true if the other duration is equal to this one
|
||||
*/
|
||||
@Override
|
||||
|
||||
126
jdk/src/java.base/share/classes/java/util/KeyValueHolder.java
Normal file
126
jdk/src/java.base/share/classes/java/util/KeyValueHolder.java
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.util;
|
||||
|
||||
/**
|
||||
* An immutable container for a key and a value, suitable for use
|
||||
* in creating and populating {@code Map} instances.
|
||||
*
|
||||
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
|
||||
* class; use of identity-sensitive operations (including reference equality
|
||||
* ({@code ==}), identity hash code, or synchronization) on instances of
|
||||
* {@code KeyValueHolder} may have unpredictable results and should be avoided.
|
||||
*
|
||||
* @apiNote
|
||||
* This class is not public. Instances can be created using the
|
||||
* {@link Map#entry Map.entry(k, v)} factory method, which is public.
|
||||
*
|
||||
* <p>This class differs from AbstractMap.SimpleImmutableEntry in the following ways:
|
||||
* it is not serializable, it is final, and its key and value must be non-null.
|
||||
*
|
||||
* @param <K> the key type
|
||||
* @param <V> the value type
|
||||
*
|
||||
* @see Map#ofEntries Map.ofEntries()
|
||||
* @since 9
|
||||
*/
|
||||
final class KeyValueHolder<K,V> implements Map.Entry<K,V> {
|
||||
final K key;
|
||||
final V value;
|
||||
|
||||
KeyValueHolder(K k, V v) {
|
||||
key = Objects.requireNonNull(k);
|
||||
value = Objects.requireNonNull(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key from this holder.
|
||||
*
|
||||
* @return the key
|
||||
*/
|
||||
@Override
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value from this holder.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
@Override
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @param value ignored
|
||||
* @return never returns normally
|
||||
*/
|
||||
@Override
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException("not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified object with this entry for equality.
|
||||
* Returns {@code true} if the given object is also a map entry and
|
||||
* the two entries' keys and values are equal. Note that key and
|
||||
* value are non-null, so equals() can be called safely on them.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Map.Entry))
|
||||
return false;
|
||||
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
||||
return key.equals(e.getKey()) && value.equals(e.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code value for this map entry. The hash code
|
||||
* is {@code key.hashCode() ^ value.hashCode()}. Note that key and
|
||||
* value are non-null, so hashCode() can be called safely on them.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String representation of this map entry. This
|
||||
* implementation returns the string representation of this
|
||||
* entry's key followed by the equals character ("{@code =}")
|
||||
* followed by the string representation of this entry's value.
|
||||
*
|
||||
* @return a String representation of this map entry
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return key + "=" + value;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -87,6 +87,28 @@ import java.util.function.UnaryOperator;
|
||||
* Such exceptions are marked as "optional" in the specification for this
|
||||
* interface.
|
||||
*
|
||||
* <h2><a name="immutable">Immutable List Static Factory Methods</a></h2>
|
||||
* <p>The {@link List#of(Object...) List.of()} static factory methods
|
||||
* provide a convenient way to create immutable lists. The {@code List}
|
||||
* instances created by these methods have the following characteristics:
|
||||
*
|
||||
* <ul>
|
||||
* <li>They are <em>structurally immutable</em>. Elements cannot be added, removed,
|
||||
* or replaced. Attempts to do so result in {@code UnsupportedOperationException}.
|
||||
* However, if the contained elements are themselves mutable,
|
||||
* this may cause the List's contents to appear to change.
|
||||
* <li>They disallow {@code null} elements. Attempts to create them with
|
||||
* {@code null} elements result in {@code NullPointerException}.
|
||||
* <li>They are serializable if all elements are serializable.
|
||||
* <li>The order of elements in the list is the same as the order of the
|
||||
* provided arguments, or of the elements in the provided array.
|
||||
* <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>.
|
||||
* Callers should make no assumptions about the identity of the returned instances.
|
||||
* Factories are free to create new instances or reuse existing ones. Therefore,
|
||||
* identity-sensitive operations on these instances (reference equality ({@code ==}),
|
||||
* identity hash code, and synchronization) are unreliable and should be avoided.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
@ -731,4 +753,312 @@ public interface List<E> extends Collection<E> {
|
||||
default Spliterator<E> spliterator() {
|
||||
return Spliterators.spliterator(this, Spliterator.ORDERED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing zero elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @return an empty {@code List}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing one element.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the single element
|
||||
* @return a {@code List} containing the specified element
|
||||
* @throws NullPointerException if the element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1) {
|
||||
return Collections.singletonList(Objects.requireNonNull(e1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing two elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing three elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing four elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing five elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing six elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing seven elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing eight elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing nine elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @param e9 the ninth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8),
|
||||
Objects.requireNonNull(e9)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing ten elements.
|
||||
*
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @param e9 the ninth element
|
||||
* @param e10 the tenth element
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
||||
return Collections.unmodifiableList(
|
||||
Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8),
|
||||
Objects.requireNonNull(e9),
|
||||
Objects.requireNonNull(e10)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing an arbitrary number of elements.
|
||||
* See <a href="#immutable">Immutable List Static Factory Methods</a> for details.
|
||||
*
|
||||
* @apiNote
|
||||
* This method also accepts a single array as an argument. The element type of
|
||||
* the resulting list will be the component type of the array, and the size of
|
||||
* the list will be equal to the length of the array. To create a list with
|
||||
* a single element that is an array, do the following:
|
||||
*
|
||||
* <pre>{@code
|
||||
* String[] array = ... ;
|
||||
* List<String[]> list = List.<String[]>of(array);
|
||||
* }</pre>
|
||||
*
|
||||
* This will cause the {@link List#of(Object) List.of(E)} method
|
||||
* to be invoked instead.
|
||||
*
|
||||
* @param <E> the {@code List}'s element type
|
||||
* @param elements the elements to be contained in the list
|
||||
* @return a {@code List} containing the specified elements
|
||||
* @throws NullPointerException if an element is {@code null} or if the array is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("varargs")
|
||||
static <E> List<E> of(E... elements) {
|
||||
elements = elements.clone(); // throws NPE if es is null
|
||||
for (E e : elements) {
|
||||
Objects.requireNonNull(e);
|
||||
}
|
||||
return Collections.unmodifiableList(Arrays.asList(elements));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1248,7 +1248,7 @@ public final class Locale implements Cloneable, Serializable {
|
||||
* object, consisting of language, country, variant, script,
|
||||
* and extensions as below:
|
||||
* <blockquote>
|
||||
* language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
|
||||
* language + "_" + country + "_" + (variant + "_#" | "#") + script + "_" + extensions
|
||||
* </blockquote>
|
||||
*
|
||||
* Language is always lower case, country is always upper case, script is always title
|
||||
@ -1278,7 +1278,7 @@ public final class Locale implements Cloneable, Serializable {
|
||||
* <li>{@code en_US_WIN}</li>
|
||||
* <li>{@code de__POSIX}</li>
|
||||
* <li>{@code zh_CN_#Hans}</li>
|
||||
* <li>{@code zh_TW_#Hant-x-java}</li>
|
||||
* <li>{@code zh_TW_#Hant_x-java}</li>
|
||||
* <li>{@code th_TH_TH_#u-nu-thai}</li></ul>
|
||||
*
|
||||
* @return A string representation of the Locale, for debugging.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -110,6 +110,31 @@ import java.io.Serializable;
|
||||
* Implementations may optionally handle the self-referential scenario, however
|
||||
* most current implementations do not do so.
|
||||
*
|
||||
* <h2><a name="immutable">Immutable Map Static Factory Methods</a></h2>
|
||||
* <p>The {@link Map#of() Map.of()} and
|
||||
* {@link Map#ofEntries(Map.Entry...) Map.ofEntries()}
|
||||
* static factory methods provide a convenient way to create immutable maps.
|
||||
* The {@code Map}
|
||||
* instances created by these methods have the following characteristics:
|
||||
*
|
||||
* <ul>
|
||||
* <li>They are <em>structurally immutable</em>. Keys and values cannot be added,
|
||||
* removed, or updated. Attempts to do so result in {@code UnsupportedOperationException}.
|
||||
* However, if the contained keys or values are themselves mutable, this may cause the
|
||||
* Map to behave inconsistently or its contents to appear to change.
|
||||
* <li>They disallow {@code null} keys and values. Attempts to create them with
|
||||
* {@code null} keys or values result in {@code NullPointerException}.
|
||||
* <li>They are serializable if all keys and values are serializable.
|
||||
* <li>They reject duplicate keys at creation time. Duplicate keys
|
||||
* passed to a static factory method result in {@code IllegalArgumentException}.
|
||||
* <li>The iteration order of mappings is unspecified and is subject to change.
|
||||
* <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>.
|
||||
* Callers should make no assumptions about the identity of the returned instances.
|
||||
* Factories are free to create new instances or reuse existing ones. Therefore,
|
||||
* identity-sensitive operations on these instances (reference equality ({@code ==}),
|
||||
* identity hash code, and synchronization) are unreliable and should be avoided.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
@ -126,7 +151,7 @@ import java.io.Serializable;
|
||||
* @see Set
|
||||
* @since 1.2
|
||||
*/
|
||||
public interface Map<K,V> {
|
||||
public interface Map<K, V> {
|
||||
// Query Operations
|
||||
|
||||
/**
|
||||
@ -373,7 +398,7 @@ public interface Map<K,V> {
|
||||
* @see Map#entrySet()
|
||||
* @since 1.2
|
||||
*/
|
||||
interface Entry<K,V> {
|
||||
interface Entry<K, V> {
|
||||
/**
|
||||
* Returns the key corresponding to this entry.
|
||||
*
|
||||
@ -468,7 +493,7 @@ public interface Map<K,V> {
|
||||
* @see Comparable
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
|
||||
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> comparingByKey() {
|
||||
return (Comparator<Map.Entry<K, V>> & Serializable)
|
||||
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
|
||||
}
|
||||
@ -485,7 +510,7 @@ public interface Map<K,V> {
|
||||
* @see Comparable
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
|
||||
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K, V>> comparingByValue() {
|
||||
return (Comparator<Map.Entry<K, V>> & Serializable)
|
||||
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
|
||||
}
|
||||
@ -1233,4 +1258,465 @@ public interface Map<K,V> {
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing zero mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @return an empty {@code Map}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing a single mapping.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the mapping's key
|
||||
* @param v1 the mapping's value
|
||||
* @return a {@code Map} containing the specified mapping
|
||||
* @throws NullPointerException if the key or the value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1) {
|
||||
return Collections.singletonMap(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing two mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if the keys are duplicates
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
|
||||
Map<K, V> map = new HashMap<>(3); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
if (map.size() != 2) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing three mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
|
||||
Map<K, V> map = new HashMap<>(5); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
if (map.size() != 3) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing four mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
|
||||
Map<K, V> map = new HashMap<>(6); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
if (map.size() != 4) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing five mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
|
||||
Map<K, V> map = new HashMap<>(7); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
if (map.size() != 5) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing six mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @param k6 the sixth mapping's key
|
||||
* @param v6 the sixth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6) {
|
||||
Map<K, V> map = new HashMap<>(9); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
|
||||
if (map.size() != 6) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing seven mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @param k6 the sixth mapping's key
|
||||
* @param v6 the sixth mapping's value
|
||||
* @param k7 the seventh mapping's key
|
||||
* @param v7 the seventh mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7) {
|
||||
Map<K, V> map = new HashMap<>(10); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
|
||||
map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
|
||||
if (map.size() != 7) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing eight mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @param k6 the sixth mapping's key
|
||||
* @param v6 the sixth mapping's value
|
||||
* @param k7 the seventh mapping's key
|
||||
* @param v7 the seventh mapping's value
|
||||
* @param k8 the eighth mapping's key
|
||||
* @param v8 the eighth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8) {
|
||||
Map<K, V> map = new HashMap<>(11); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
|
||||
map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
|
||||
map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
|
||||
if (map.size() != 8) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing nine mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @param k6 the sixth mapping's key
|
||||
* @param v6 the sixth mapping's value
|
||||
* @param k7 the seventh mapping's key
|
||||
* @param v7 the seventh mapping's value
|
||||
* @param k8 the eighth mapping's key
|
||||
* @param v8 the eighth mapping's value
|
||||
* @param k9 the ninth mapping's key
|
||||
* @param v9 the ninth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
|
||||
Map<K, V> map = new HashMap<>(13); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
|
||||
map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
|
||||
map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
|
||||
map.put(Objects.requireNonNull(k9), Objects.requireNonNull(v9));
|
||||
if (map.size() != 9) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing ten mappings.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param k1 the first mapping's key
|
||||
* @param v1 the first mapping's value
|
||||
* @param k2 the second mapping's key
|
||||
* @param v2 the second mapping's value
|
||||
* @param k3 the third mapping's key
|
||||
* @param v3 the third mapping's value
|
||||
* @param k4 the fourth mapping's key
|
||||
* @param v4 the fourth mapping's value
|
||||
* @param k5 the fifth mapping's key
|
||||
* @param v5 the fifth mapping's value
|
||||
* @param k6 the sixth mapping's key
|
||||
* @param v6 the sixth mapping's value
|
||||
* @param k7 the seventh mapping's key
|
||||
* @param v7 the seventh mapping's value
|
||||
* @param k8 the eighth mapping's key
|
||||
* @param v8 the eighth mapping's value
|
||||
* @param k9 the ninth mapping's key
|
||||
* @param v9 the ninth mapping's value
|
||||
* @param k10 the tenth mapping's key
|
||||
* @param v10 the tenth mapping's value
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any key or value is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
|
||||
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
|
||||
Map<K, V> map = new HashMap<>(14); // specify number of buckets to avoid resizing
|
||||
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1));
|
||||
map.put(Objects.requireNonNull(k2), Objects.requireNonNull(v2));
|
||||
map.put(Objects.requireNonNull(k3), Objects.requireNonNull(v3));
|
||||
map.put(Objects.requireNonNull(k4), Objects.requireNonNull(v4));
|
||||
map.put(Objects.requireNonNull(k5), Objects.requireNonNull(v5));
|
||||
map.put(Objects.requireNonNull(k6), Objects.requireNonNull(v6));
|
||||
map.put(Objects.requireNonNull(k7), Objects.requireNonNull(v7));
|
||||
map.put(Objects.requireNonNull(k8), Objects.requireNonNull(v8));
|
||||
map.put(Objects.requireNonNull(k9), Objects.requireNonNull(v9));
|
||||
map.put(Objects.requireNonNull(k10), Objects.requireNonNull(v10));
|
||||
if (map.size() != 10) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable map containing keys and values extracted from the given entries.
|
||||
* The entries themselves are not stored in the map.
|
||||
* See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
|
||||
*
|
||||
* @apiNote
|
||||
* It is convenient to create the map entries using the {@link Map#entry Map.entry()} method.
|
||||
* For example,
|
||||
*
|
||||
* <pre>{@code
|
||||
* import static java.util.Map.entry;
|
||||
*
|
||||
* Map<Integer,String> map = Map.ofEntries(
|
||||
* entry(1, "a"),
|
||||
* entry(2, "b"),
|
||||
* entry(3, "c"),
|
||||
* ...
|
||||
* entry(26, "z"));
|
||||
* }</pre>
|
||||
*
|
||||
* @param <K> the {@code Map}'s key type
|
||||
* @param <V> the {@code Map}'s value type
|
||||
* @param entries {@code Map.Entry}s containing the keys and values from which the map is populated
|
||||
* @return a {@code Map} containing the specified mappings
|
||||
* @throws IllegalArgumentException if there are any duplicate keys
|
||||
* @throws NullPointerException if any entry, key, or value is {@code null}, or if
|
||||
* the {@code entries} array is {@code null}
|
||||
*
|
||||
* @see Map#entry Map.entry()
|
||||
* @since 9
|
||||
*/
|
||||
@SafeVarargs
|
||||
@SuppressWarnings("varargs")
|
||||
static <K, V> Map<K, V> ofEntries(Entry<K, V>... entries) {
|
||||
Map<K, V> map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null
|
||||
for (Entry<K, V> e : entries) {
|
||||
// next line throws NPE if e is null
|
||||
map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue()));
|
||||
}
|
||||
if (map.size() != entries.length) {
|
||||
throw new IllegalArgumentException("duplicate keys");
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable {@link Entry} containing the given key and value.
|
||||
* These entries are suitable for populating {@code Map} instances using the
|
||||
* {@link Map#ofEntries Map.ofEntries()} method.
|
||||
* The {@code Entry} instances created by this method have the following characteristics:
|
||||
*
|
||||
* <ul>
|
||||
* <li>They disallow {@code null} keys and values. Attempts to create them using a {@code null}
|
||||
* key or value result in {@code NullPointerException}.
|
||||
* <li>They are immutable. Calls to {@link Entry#setValue Entry.setValue()}
|
||||
* on a returned {@code Entry} result in {@code UnsupportedOperationException}.
|
||||
* <li>They are not serializable.
|
||||
* <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>.
|
||||
* Callers should make no assumptions about the identity of the returned instances.
|
||||
* This method is free to create new instances or reuse existing ones. Therefore,
|
||||
* identity-sensitive operations on these instances (reference equality ({@code ==}),
|
||||
* identity hash code, and synchronization) are unreliable and should be avoided.
|
||||
* </ul>
|
||||
*
|
||||
* @apiNote
|
||||
* For a serializable {@code Entry}, see {@link AbstractMap.SimpleEntry} or
|
||||
* {@link AbstractMap.SimpleImmutableEntry}.
|
||||
*
|
||||
* @param <K> the key's type
|
||||
* @param <V> the value's type
|
||||
* @param k the key
|
||||
* @param v the value
|
||||
* @return an {@code Entry} containing the specified key and value
|
||||
* @throws NullPointerException if the key or value is {@code null}
|
||||
*
|
||||
* @see Map#ofEntries Map.ofEntries()
|
||||
* @since 9
|
||||
*/
|
||||
static <K, V> Entry<K, V> entry(K k, V v) {
|
||||
// KeyValueHolder checks for nulls
|
||||
return new KeyValueHolder<>(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -63,6 +63,29 @@ package java.util;
|
||||
* Such exceptions are marked as "optional" in the specification for this
|
||||
* interface.
|
||||
*
|
||||
* <h2><a name="immutable">Immutable Set Static Factory Methods</a></h2>
|
||||
* <p>The {@link Set#of(Object...) Set.of()} static factory methods
|
||||
* provide a convenient way to create immutable sets. The {@code Set}
|
||||
* instances created by these methods have the following characteristics:
|
||||
*
|
||||
* <ul>
|
||||
* <li>They are <em>structurally immutable</em>. Elements cannot be added or
|
||||
* removed. Attempts to do so result in {@code UnsupportedOperationException}.
|
||||
* However, if the contained elements are themselves mutable, this may cause the
|
||||
* Set to behave inconsistently or its contents to appear to change.
|
||||
* <li>They disallow {@code null} elements. Attempts to create them with
|
||||
* {@code null} elements result in {@code NullPointerException}.
|
||||
* <li>They are serializable if all elements are serializable.
|
||||
* <li>They reject duplicate elements at creation time. Duplicate elements
|
||||
* passed to a static factory method result in {@code IllegalArgumentException}.
|
||||
* <li>The iteration order of set elements is unspecified and is subject to change.
|
||||
* <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>.
|
||||
* Callers should make no assumptions about the identity of the returned instances.
|
||||
* Factories are free to create new instances or reuse existing ones. Therefore,
|
||||
* identity-sensitive operations on these instances (reference equality ({@code ==}),
|
||||
* identity hash code, and synchronization) are unreliable and should be avoided.
|
||||
* </ul>
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
|
||||
* Java Collections Framework</a>.
|
||||
@ -410,4 +433,341 @@ public interface Set<E> extends Collection<E> {
|
||||
default Spliterator<E> spliterator() {
|
||||
return Spliterators.spliterator(this, Spliterator.DISTINCT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing zero elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @return an empty {@code Set}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing one element.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the single element
|
||||
* @return a {@code Set} containing the specified element
|
||||
* @throws NullPointerException if the element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1) {
|
||||
return Collections.singleton(Objects.requireNonNull(e1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing two elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if the elements are duplicates
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2)));
|
||||
if (set.size() != 2) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing three elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3)));
|
||||
if (set.size() != 3) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing four elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4)));
|
||||
if (set.size() != 4) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing five elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5)));
|
||||
if (set.size() != 5) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing six elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6)));
|
||||
if (set.size() != 6) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing seven elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7)));
|
||||
if (set.size() != 7) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing eight elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8)));
|
||||
if (set.size() != 8) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing nine elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @param e9 the ninth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8),
|
||||
Objects.requireNonNull(e9)));
|
||||
if (set.size() != 9) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing ten elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param e1 the first element
|
||||
* @param e2 the second element
|
||||
* @param e3 the third element
|
||||
* @param e4 the fourth element
|
||||
* @param e5 the fifth element
|
||||
* @param e6 the sixth element
|
||||
* @param e7 the seventh element
|
||||
* @param e8 the eighth element
|
||||
* @param e9 the ninth element
|
||||
* @param e10 the tenth element
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
|
||||
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1),
|
||||
Objects.requireNonNull(e2),
|
||||
Objects.requireNonNull(e3),
|
||||
Objects.requireNonNull(e4),
|
||||
Objects.requireNonNull(e5),
|
||||
Objects.requireNonNull(e6),
|
||||
Objects.requireNonNull(e7),
|
||||
Objects.requireNonNull(e8),
|
||||
Objects.requireNonNull(e9),
|
||||
Objects.requireNonNull(e10)));
|
||||
if (set.size() != 10) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing an arbitrary number of elements.
|
||||
* See <a href="#immutable">Immutable Set Static Factory Methods</a> for details.
|
||||
*
|
||||
* @apiNote
|
||||
* This method also accepts a single array as an argument. The element type of
|
||||
* the resulting set will be the component type of the array, and the size of
|
||||
* the set will be equal to the length of the array. To create a set with
|
||||
* a single element that is an array, do the following:
|
||||
*
|
||||
* <pre>{@code
|
||||
* String[] array = ... ;
|
||||
* Set<String[]> list = Set.<String[]>of(array);
|
||||
* }</pre>
|
||||
*
|
||||
* This will cause the {@link Set#of(Object) Set.of(E)} method
|
||||
* to be invoked instead.
|
||||
*
|
||||
* @param <E> the {@code Set}'s element type
|
||||
* @param elements the elements to be contained in the set
|
||||
* @return a {@code Set} containing the specified elements
|
||||
* @throws IllegalArgumentException if there are any duplicate elements
|
||||
* @throws NullPointerException if an element is {@code null} or if the array is {@code null}
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@SafeVarargs
|
||||
static <E> Set<E> of(E... elements) {
|
||||
for (E e : elements) { // throws NPE if es is null
|
||||
Objects.requireNonNull(e);
|
||||
}
|
||||
@SuppressWarnings("varargs")
|
||||
Set<E> set = new HashSet<>(Arrays.asList(elements));
|
||||
if (set.size() != elements.length) {
|
||||
throw new IllegalArgumentException("duplicate elements");
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,8 +25,8 @@
|
||||
|
||||
package sun.nio.cs;
|
||||
|
||||
import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
|
||||
class StringUTF16 {
|
||||
|
||||
@ -35,5 +35,5 @@ class StringUTF16 {
|
||||
ARRAY_BYTE_BASE_OFFSET + ARRAY_BYTE_INDEX_SCALE * index * 2L);
|
||||
}
|
||||
|
||||
private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
|
||||
private static final jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
|
||||
}
|
||||
|
||||
@ -766,17 +766,27 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
// records, so this also increases robustness.
|
||||
//
|
||||
if (length > 0) {
|
||||
IOException ioe = null;
|
||||
byte description = 0; // 0: never used, make the compiler happy
|
||||
writeLock.lock();
|
||||
try {
|
||||
outputRecord.deliver(source, offset, length);
|
||||
} catch (SSLHandshakeException she) {
|
||||
// may be record sequence number overflow
|
||||
fatal(Alerts.alert_handshake_failure, she);
|
||||
description = Alerts.alert_handshake_failure;
|
||||
ioe = she;
|
||||
} catch (IOException e) {
|
||||
fatal(Alerts.alert_unexpected_message, e);
|
||||
description = Alerts.alert_unexpected_message;
|
||||
ioe = e;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
|
||||
// Be care of deadlock. Please don't place the call to fatal()
|
||||
// into the writeLock locked block.
|
||||
if (ioe != null) {
|
||||
fatal(description, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -35,8 +35,10 @@ import java.util.regex.Pattern;
|
||||
public class AlgorithmDecomposer {
|
||||
|
||||
private static final Pattern transPattern = Pattern.compile("/");
|
||||
|
||||
// '(?<!padd)in': match 'in' but not preceded with 'padd'.
|
||||
private static final Pattern pattern =
|
||||
Pattern.compile("with|and|in", Pattern.CASE_INSENSITIVE);
|
||||
Pattern.compile("with|and|(?<!padd)in", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Decompose the standard algorithm name into sub-elements.
|
||||
|
||||
@ -295,6 +295,7 @@ ping4(JNIEnv *env,
|
||||
char SendData[32] = {0};
|
||||
LPVOID ReplyBuffer = NULL;
|
||||
DWORD ReplySize = 0;
|
||||
jboolean ret = JNI_FALSE;
|
||||
|
||||
hIcmpFile = IcmpCreateFile();
|
||||
if (hIcmpFile == INVALID_HANDLE_VALUE) {
|
||||
@ -318,7 +319,11 @@ ping4(JNIEnv *env,
|
||||
NULL, // PIP_OPTION_INFORMATION RequestOptions,
|
||||
ReplyBuffer,// LPVOID ReplyBuffer,
|
||||
ReplySize, // DWORD ReplySize,
|
||||
timeout); // DWORD Timeout
|
||||
// Note: IcmpSendEcho and its derivatives
|
||||
// seem to have an undocumented minimum
|
||||
// timeout of 1000ms below which the
|
||||
// api behaves inconsistently.
|
||||
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
|
||||
} else {
|
||||
dwRetVal = IcmpSendEcho2Ex(hIcmpFile, // HANDLE IcmpHandle,
|
||||
NULL, // HANDLE Event
|
||||
@ -331,17 +336,19 @@ ping4(JNIEnv *env,
|
||||
NULL, // PIP_OPTION_INFORMATION RequestOptions,
|
||||
ReplyBuffer,// LPVOID ReplyBuffer,
|
||||
ReplySize, // DWORD ReplySize,
|
||||
timeout); // DWORD Timeout
|
||||
(timeout < 1000) ? 1000 : timeout); // DWORD Timeout
|
||||
}
|
||||
|
||||
if (dwRetVal != 0) {
|
||||
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
|
||||
if ((int)pEchoReply->RoundTripTime <= timeout)
|
||||
ret = JNI_TRUE;
|
||||
}
|
||||
|
||||
free(ReplyBuffer);
|
||||
IcmpCloseHandle(hIcmpFile);
|
||||
|
||||
if (dwRetVal != 0) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,389 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 apple.applescript;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.script.*;
|
||||
|
||||
/**
|
||||
* AppleScriptEngine implements JSR 223 for AppleScript on Mac OS X
|
||||
*/
|
||||
public class AppleScriptEngine implements ScriptEngine {
|
||||
private static native void initNative();
|
||||
|
||||
private static native long createContextFrom(final Object object);
|
||||
private static native Object createObjectFrom(final long context);
|
||||
private static native void disposeContext(final long context);
|
||||
|
||||
private static native long evalScript(final String script, long contextptr);
|
||||
private static native long evalScriptFromURL(final String filename, long contextptr);
|
||||
|
||||
static {
|
||||
System.loadLibrary("AppleScriptEngine");
|
||||
initNative();
|
||||
TRACE("<static-init>");
|
||||
}
|
||||
|
||||
static void checkSecurity() {
|
||||
final SecurityManager securityManager = System.getSecurityManager();
|
||||
if (securityManager != null) securityManager.checkExec("/usr/bin/osascript");
|
||||
}
|
||||
|
||||
static void TRACE(final String str) {
|
||||
// System.out.println(AppleScriptEngine.class.getName() + "." + str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the ScriptEngine's long name variable
|
||||
* @return the long name of the ScriptEngine
|
||||
*/
|
||||
protected static String getEngine() {
|
||||
TRACE("getEngine()");
|
||||
return AppleScriptEngineFactory.ENGINE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the ScriptEngine's version
|
||||
* @return the version of the ScriptEngine
|
||||
*/
|
||||
protected static String getEngineVersion() {
|
||||
TRACE("getEngineVersion()");
|
||||
return AppleScriptEngineFactory.ENGINE_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the ScriptEngine's short name
|
||||
* @return the short name of the ScriptEngine
|
||||
*/
|
||||
protected static String getName() {
|
||||
TRACE("getName()");
|
||||
return AppleScriptEngineFactory.ENGINE_SHORT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the ScriptEngine's supported language name
|
||||
* @return the language the ScriptEngine supports
|
||||
*/
|
||||
protected static String getLanguage() {
|
||||
TRACE("getLanguage()");
|
||||
return AppleScriptEngineFactory.LANGUAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The no argument constructor sets up the object with default members,
|
||||
* a factory for the engine and a fresh context.
|
||||
* @see com.apple.applescript.AppleScriptEngine#init()
|
||||
*/
|
||||
public AppleScriptEngine() {
|
||||
TRACE("<ctor>()");
|
||||
// set our parent factory to be a new factory
|
||||
factory = AppleScriptEngineFactory.getFactory();
|
||||
|
||||
// set up our noarg bindings
|
||||
setContext(new SimpleScriptContext());
|
||||
put(ARGV, "");
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* All AppleScriptEngines share the same ScriptEngineFactory
|
||||
*/
|
||||
private final ScriptEngineFactory factory;
|
||||
|
||||
/**
|
||||
* The local context for the AppleScriptEngine
|
||||
*/
|
||||
private ScriptContext context;
|
||||
|
||||
/**
|
||||
* The constructor taking a factory as an argument sets the parent factory for
|
||||
* this engine to be the passed factory, and sets up the engine with a fresh context
|
||||
* @param factory
|
||||
* @see com.apple.applescript.AppleScriptEngine#init()
|
||||
*/
|
||||
public AppleScriptEngine(final ScriptEngineFactory factory) {
|
||||
// inherit the factory passed to us
|
||||
this.factory = factory;
|
||||
|
||||
// set up our noarg bindings
|
||||
setContext(new SimpleScriptContext());
|
||||
put(ARGV, "");
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* The initializer populates the local context with some useful predefined variables:
|
||||
* <ul><li><code>javax_script_language_version</code> - the version of AppleScript that the AppleScriptEngine supports.</li>
|
||||
* <li><code>javax_script_language</code> - "AppleScript" -- the language supported by the AppleScriptEngine.</li>
|
||||
* <li><code>javax_script_engine</code> - "AppleScriptEngine" -- the name of the ScriptEngine.</li>
|
||||
* <li><code>javax_script_engine_version</code> - the version of the AppleScriptEngine</li>
|
||||
* <li><code>javax_script_argv</code> - "" -- AppleScript does not take arguments from the command line</li>
|
||||
* <li><code>javax_script_filename</code> - "" -- the currently executing filename</li>
|
||||
* <li><code>javax_script_name</code> - "AppleScriptEngine" -- the short name of the AppleScriptEngine</li>
|
||||
* <li><code>THREADING</code> - null -- the AppleScriptEngine does not support concurrency, you will have to implement thread-safeness yourself.</li></ul>
|
||||
*/
|
||||
private void init() {
|
||||
TRACE("init()");
|
||||
// set up our context
|
||||
/* TODO -- name of current executable? bad java documentation at:
|
||||
* http://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#FILENAME */
|
||||
put(ScriptEngine.FILENAME, "");
|
||||
put(ScriptEngine.ENGINE, getEngine());
|
||||
put(ScriptEngine.ENGINE_VERSION, getEngineVersion());
|
||||
put(ScriptEngine.NAME, getName());
|
||||
put(ScriptEngine.LANGUAGE, getLanguage());
|
||||
put(ScriptEngine.LANGUAGE_VERSION, getLanguageVersion());
|
||||
|
||||
// TODO -- for now, err on the side of caution and say that we are NOT thread-safe
|
||||
put("THREADING", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the AppleScriptEngine to get the local AppleScript version
|
||||
* @return the version of AppleScript running on the system
|
||||
*/
|
||||
protected String getLanguageVersion() {
|
||||
TRACE("AppleScriptEngine.getLanguageVersion()");
|
||||
try {
|
||||
final Object result = eval("get the version of AppleScript");
|
||||
if (result instanceof String) return (String)result;
|
||||
} catch (final ScriptException e) { e.printStackTrace(); }
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Returns the factory parent of this AppleScriptEngine
|
||||
*/
|
||||
public ScriptEngineFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Return the engine's context
|
||||
* @return this ScriptEngine's context
|
||||
*/
|
||||
public ScriptContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Set a new context for the engine
|
||||
* @param context the new context to install in the engine
|
||||
*/
|
||||
public void setContext(final ScriptContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Create and return a new set of simple bindings.
|
||||
* @return a new and empty set of bindings
|
||||
*/
|
||||
public Bindings createBindings() {
|
||||
return new SimpleBindings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Return the engines bindings for the context indicated by the argument.
|
||||
* @param scope contextual scope to return.
|
||||
* @return the bindings in the engine for the scope indicated by the parameter
|
||||
*/
|
||||
public Bindings getBindings(final int scope) {
|
||||
return context.getBindings(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Sets the bindings for the indicated scope
|
||||
* @param bindings a set of bindings to assign to the engine
|
||||
* @param scope the scope that the passed bindings should be assigned to
|
||||
*/
|
||||
public void setBindings(final Bindings bindings, final int scope) {
|
||||
context.setBindings(bindings, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Insert a key and value into the engine's bindings (scope: engine)
|
||||
* @param key the key of the pair
|
||||
* @param value the value of the pair
|
||||
*/
|
||||
public void put(final String key, final Object value) {
|
||||
getBindings(ScriptContext.ENGINE_SCOPE).put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Get a value from the engine's bindings using a key (scope: engine)
|
||||
* @param key the key of the pair
|
||||
* @return the value of the pair
|
||||
*/
|
||||
public Object get(final String key) {
|
||||
return getBindings(ScriptContext.ENGINE_SCOPE).get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Passes the Reader argument, as well as the engine's context to a lower evaluation function.<br />
|
||||
* Prefers FileReader or BufferedReader wrapping FileReader as argument.
|
||||
* @param reader a Reader to AppleScript source or compiled AppleScript
|
||||
* @return an Object corresponding to the return value of the script
|
||||
* @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
|
||||
*/
|
||||
public Object eval(final Reader reader) throws ScriptException {
|
||||
return eval(reader, getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Uses the passed bindings as the context for executing the passed script.
|
||||
* @param reader a stream to AppleScript source or compiled AppleScript
|
||||
* @param bindings a Bindings object representing the contexts to execute inside
|
||||
* @return the return value of the script
|
||||
* @see com.apple.applescript.AppleScriptEngine#eval(Reader, ScriptContext)
|
||||
*/
|
||||
public Object eval(final Reader reader, final Bindings bindings) throws ScriptException {
|
||||
final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
|
||||
final Object retval = eval(reader);
|
||||
getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* This function can execute either AppleScript source or compiled AppleScript and functions by writing the
|
||||
* contents of the Reader to a temporary file and then executing it with the engine's context.
|
||||
* @param reader
|
||||
* @param scriptContext
|
||||
* @return an Object corresponding to the return value of the script
|
||||
*/
|
||||
public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
|
||||
checkSecurity();
|
||||
|
||||
// write our passed reader to a temporary file
|
||||
File tmpfile;
|
||||
FileWriter tmpwrite;
|
||||
try {
|
||||
tmpfile = Files.createTempFile("AppleScriptEngine.", ".scpt").toFile();
|
||||
tmpwrite = new FileWriter(tmpfile);
|
||||
|
||||
// read in our input and write directly to tmpfile
|
||||
/* TODO -- this may or may not be avoidable for certain Readers,
|
||||
* if a filename can be grabbed, it would be faster to get that and
|
||||
* use the underlying file than writing a temp file.
|
||||
*/
|
||||
int data;
|
||||
while ((data = reader.read()) != -1) {
|
||||
tmpwrite.write(data);
|
||||
}
|
||||
tmpwrite.close();
|
||||
|
||||
// set up our context business
|
||||
final long contextptr = scriptContextToNSDictionary(context);
|
||||
try {
|
||||
final long retCtx = evalScriptFromURL("file://" + tmpfile.getCanonicalPath(), contextptr);
|
||||
Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
|
||||
disposeContext(retCtx);
|
||||
return retVal;
|
||||
} finally {
|
||||
disposeContext(contextptr);
|
||||
tmpfile.delete();
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new ScriptException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Evaluate an AppleScript script passed as a source string. Using the engine's built in context.
|
||||
* @param script the string to execute.
|
||||
* @return an Object representing the return value of the script
|
||||
* @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
|
||||
*/
|
||||
public Object eval(final String script) throws ScriptException {
|
||||
return eval(script, getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent<br />
|
||||
* Evaluate an AppleScript script passed as a source string with a custom ScriptContext.
|
||||
* @param script the AppleScript source to compile and execute.
|
||||
* @param scriptContext the context to execute the script under
|
||||
* @see com.apple.applescript.AppleScriptEngine#eval(String, ScriptContext)
|
||||
*/
|
||||
public Object eval(final String script, final Bindings bindings) throws ScriptException {
|
||||
final Bindings tmp = getContext().getBindings(ScriptContext.ENGINE_SCOPE);
|
||||
getContext().setBindings(bindings, ScriptContext.ENGINE_SCOPE);
|
||||
|
||||
final Object retval = eval(script);
|
||||
getContext().setBindings(tmp, ScriptContext.ENGINE_SCOPE);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation required by ScriptEngine parent
|
||||
* @param script
|
||||
* @param scriptContext
|
||||
*/
|
||||
public Object eval(final String script, final ScriptContext context) throws ScriptException {
|
||||
checkSecurity();
|
||||
final long ctxPtr = scriptContextToNSDictionary(context);
|
||||
try {
|
||||
final long retCtx = evalScript(script, ctxPtr);
|
||||
Object retVal = (retCtx == 0) ? null : createObjectFrom(retCtx);
|
||||
disposeContext(retCtx);
|
||||
return retVal;
|
||||
} finally {
|
||||
disposeContext(ctxPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a ScriptContext into an NSDictionary
|
||||
* @param context ScriptContext for the engine
|
||||
* @return a pointer to an NSDictionary
|
||||
*/
|
||||
private long scriptContextToNSDictionary(final ScriptContext context) throws ScriptException {
|
||||
final Map<String, Object> contextAsMap = new HashMap<String, Object>();
|
||||
for (final Entry<String, Object> e : context.getBindings(ScriptContext.ENGINE_SCOPE).entrySet()) {
|
||||
contextAsMap.put(e.getKey().replaceAll("\\.", "_"), e.getValue());
|
||||
}
|
||||
return createContextFrom(contextAsMap);
|
||||
}
|
||||
}
|
||||
@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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 apple.applescript;
|
||||
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import javax.script.*;
|
||||
|
||||
public class AppleScriptEngineFactory implements ScriptEngineFactory {
|
||||
private static volatile boolean initialized = false;
|
||||
|
||||
private static native void initNative();
|
||||
|
||||
static void TRACE(final String str) {
|
||||
// System.out.println(AppleScriptEngineFactory.class.getName() + "." + str);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of this ScriptEngine
|
||||
*/
|
||||
static final String ENGINE_NAME = "AppleScriptEngine";
|
||||
|
||||
/**
|
||||
* The version of this ScriptEngine
|
||||
*/
|
||||
static final String ENGINE_VERSION = "1.1";
|
||||
|
||||
/**
|
||||
* The name of this ScriptEngine (yes, again)
|
||||
*/
|
||||
static final String ENGINE_SHORT_NAME = ENGINE_NAME;
|
||||
|
||||
/**
|
||||
* The name of the language supported by this ScriptEngine
|
||||
*/
|
||||
static final String LANGUAGE = "AppleScript";
|
||||
|
||||
static ScriptEngineFactory getFactory() {
|
||||
TRACE("getFactory()");
|
||||
return new AppleScriptEngineFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new AppleScriptEngineFactory, replete with a member AppleScriptEngine
|
||||
*/
|
||||
public AppleScriptEngineFactory() {
|
||||
TRACE("<ctor>()");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full name of the ScriptEngine.
|
||||
*
|
||||
* @return full name of the ScriptEngine
|
||||
*/
|
||||
@Override
|
||||
public String getEngineName() {
|
||||
TRACE("getEngineName()");
|
||||
return ENGINE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the ScriptEngine.
|
||||
*
|
||||
* @return version of the ScriptEngine
|
||||
*/
|
||||
@Override
|
||||
public String getEngineVersion() {
|
||||
TRACE("getEngineVersion()");
|
||||
return ENGINE_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the scripting language supported by this ScriptEngine.
|
||||
*
|
||||
* @return name of the language supported by the ScriptEngine(Factory)
|
||||
*/
|
||||
@Override
|
||||
public String getLanguageName() {
|
||||
TRACE("getLanguageName()");
|
||||
return LANGUAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the scripting language supported by this ScriptEngine(Factory).
|
||||
*
|
||||
* @return language version supported by the ScriptEngine(Factory)
|
||||
*/
|
||||
@Override
|
||||
public String getLanguageVersion() {
|
||||
TRACE("getLanguageVersion()");
|
||||
return AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
final AppleScriptEngine engine = getScriptEngine();
|
||||
return engine.getLanguageVersion();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list of filename extensions, which generally identify
|
||||
* scripts written in the language supported by this ScriptEngine.
|
||||
*
|
||||
* @return ArrayList of file extensions AppleScript associates with
|
||||
*/
|
||||
@Override
|
||||
public List<String> getExtensions() {
|
||||
TRACE("getExtensions()");
|
||||
return Arrays.asList("scpt", "applescript", "app");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list of mimetypes, associated with scripts
|
||||
* that can be executed by the engine.
|
||||
*
|
||||
* @return ArrayList of mimetypes that AppleScript associates with
|
||||
*/
|
||||
@Override
|
||||
public List<String> getMimeTypes() {
|
||||
TRACE("getMimeTypes()");
|
||||
return Arrays.asList("application/x-applescript", "text/plain", "text/applescript");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable list of short names for the ScriptEngine,
|
||||
* which may be used to identify the ScriptEngine by the ScriptEngineManager.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
TRACE("getNames()");
|
||||
return Arrays.asList("AppleScriptEngine", "AppleScript", "OSA");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String which can be used to invoke a method of a Java
|
||||
* object using the syntax of the supported scripting language.
|
||||
*
|
||||
* @param obj
|
||||
* unused -- AppleScript does not support objects
|
||||
* @param m
|
||||
* function name
|
||||
* @param args
|
||||
* arguments to the function
|
||||
* @return the AppleScript string calling the method
|
||||
*/
|
||||
@Override
|
||||
public String getMethodCallSyntax(final String obj, final String fname, final String ... args) {
|
||||
// StringBuilder builder = new StringBuilder();
|
||||
// builder.append("my " + fname + "(");
|
||||
// // TODO -- do
|
||||
// builder.append(")\n");
|
||||
// return builder.toString();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String that can be used as a statement to display the specified String using the syntax of the supported scripting language.
|
||||
*
|
||||
* @param toDisplay
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getOutputStatement(final String toDisplay) {
|
||||
// TODO -- this might even be good enough? XD
|
||||
return getMethodCallSyntax(null, "print", toDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of an attribute whose meaning may be implementation-specific.
|
||||
*
|
||||
* @param key
|
||||
* the key to look up
|
||||
* @return the static preseeded value for the key in the ScriptEngine, if it exists, otherwise <code>null</code>
|
||||
*/
|
||||
@Override
|
||||
public Object getParameter(final String key) {
|
||||
final AppleScriptEngine engine = getScriptEngine();
|
||||
if (!engine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(key)) return null;
|
||||
return engine.getBindings(ScriptContext.ENGINE_SCOPE).get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns A valid scripting language executable program with given statements.
|
||||
*
|
||||
* @param statements
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getProgram(final String ... statements) {
|
||||
final StringBuilder program = new StringBuilder();
|
||||
for (final String statement : statements) {
|
||||
program.append(statement + "\n");
|
||||
}
|
||||
return program.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the ScriptEngine associated with this ScriptEngineFactory.
|
||||
*
|
||||
* @return new AppleScriptEngine with this factory as it's parent
|
||||
*/
|
||||
@Override
|
||||
public AppleScriptEngine getScriptEngine() {
|
||||
AppleScriptEngine.checkSecurity();
|
||||
ensureInitialized();
|
||||
|
||||
return new AppleScriptEngine(this);
|
||||
}
|
||||
|
||||
private static synchronized void ensureInitialized() {
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
|
||||
java.awt.Toolkit.getDefaultToolkit();
|
||||
System.loadLibrary("AppleScriptEngine");
|
||||
initNative();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
// A 'collection' (responds to -objectEnumerator) is translated to an AS list.
|
||||
// For any other object obj, this returns [[obj description] aeDescriptorValue], mainly
|
||||
// intended for debugging purposes.
|
||||
@interface NSObject (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *) aeDescriptorValue;
|
||||
@end
|
||||
|
||||
@interface NSAppleEventDescriptor (JavaAppleScriptEngineAdditions)
|
||||
- (id) objCObjectValue;
|
||||
@end
|
||||
@ -1,793 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Most of this is adapted from Ken Ferry's KFAppleScript Additions, contributed with permission
|
||||
// http://homepage.mac.com/kenferry/software.html
|
||||
//
|
||||
|
||||
#import "AS_NS_ConversionUtils.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
|
||||
@interface NSAppleEventDescriptor (JavaAppleScriptEngineAdditionsPrivate)
|
||||
|
||||
// just returns self. This means that you can pass custom descriptors
|
||||
// to -[NSAppleScript executeHandler:error:withParameters:].
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
|
||||
// working with primitive descriptor types
|
||||
+ (id)descriptorWithInt16:(SInt16)val;
|
||||
- (SInt16)int16Value;
|
||||
+ (id)descriptorWithUnsignedInt32:(UInt32)val;
|
||||
- (UInt32)unsignedInt32Value;
|
||||
+ (id)descriptorWithFloat32:(Float32)val;
|
||||
- (Float32)float32Value;
|
||||
+ (id)descriptorWithFloat64:(Float64)val;
|
||||
- (Float64)float64Value;
|
||||
+ (id)descriptorWithLongDateTime:(LongDateTime)val;
|
||||
- (LongDateTime)longDateTimeValue;
|
||||
|
||||
|
||||
// These are the methods for converting AS objects to objective-C objects.
|
||||
// -[NSAppleEventDescriptor objCObjectValue] is the general method for converting
|
||||
// AS objects to ObjC objects, and is called by -[NSAppleScript executeHandler:error:withParameters:].
|
||||
// It does no work itself. It finds a handler based on the type of the descriptor and lets that
|
||||
// handler object do the work. If there is no handler type registered for a the type of a descriptor,
|
||||
// the raw descriptor is returned.
|
||||
//
|
||||
// You can designate a handlers for descriptor types with
|
||||
// +[NSAppleEventDescriptor registerConversionHandler:selector:forDescriptorTypes:]. Please note
|
||||
// that this method does _not_ retain the handler object (for now anyway). The selector should
|
||||
// take a single argument, a descriptor to translate, and should return an object. An example such
|
||||
// selector is @selector(dictionaryWithAEDesc:), for which the handler object would be [NSDictionary class].
|
||||
//
|
||||
// A number of handlers are designated by default. The methods and objects can be easily inferred (or check
|
||||
// the implementation), but the automatically handled types are
|
||||
// typeUnicodeText,
|
||||
// typeText,
|
||||
// typeUTF8Text,
|
||||
// typeCString,
|
||||
// typeChar,
|
||||
// typeBoolean,
|
||||
// typeTrue,
|
||||
// typeFalse,
|
||||
// typeSInt16,
|
||||
// typeSInt32,
|
||||
// typeUInt32,
|
||||
// typeSInt64,
|
||||
// typeIEEE32BitFloatingPoint,
|
||||
// typeIEEE64BitFloatingPoint,
|
||||
// type128BitFloatingPoint,
|
||||
// typeAEList,
|
||||
// typeAERecord,
|
||||
// typeLongDateTime,
|
||||
// typeNull.
|
||||
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ...;
|
||||
+ (void) jaseSetUpHandlerDict;
|
||||
@end
|
||||
|
||||
// wrap the NSAppleEventDescriptor string methods
|
||||
@interface NSString (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
// wrap the NSAppleEventDescriptor longDateTime methods
|
||||
@interface NSDate (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
// these are fairly complicated methods, due to having to try to match up the various
|
||||
// AS number types (see NSAppleEventDescriptor for the primitive number methods)
|
||||
// with NSNumber variants. For complete behavior it's best to look at the implementation.
|
||||
// Some notes:
|
||||
// NSNumbers created with numberWithBool should be correctly translated to AS booleans and vice versa.
|
||||
// NSNumbers created with large integer types may have to be translated to AS doubles,
|
||||
// so be careful if checking equality (you may have to check equality within epsilon).
|
||||
// Since NSNumbers can't remember if they were created with an unsigned value,
|
||||
// [[NSNumber numberWithUnsignedChar:255] aeDescriptorValue] is going to get you an AS integer
|
||||
// with value -1. If you really need a descriptor with an unsigned value, you'll need to do it
|
||||
// manually using the primitive methods on NSAppleEventDescriptor. The resulting descriptor
|
||||
// can still be passed to AS with -[NSAppleScript executeHandler:error:withParameters:].
|
||||
@interface NSNumber (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
// Here we're following the behavior described in the CocoaScripting release note.
|
||||
//
|
||||
// NSPoint -> list of two numbers: {x, y}
|
||||
// NSRange -> list of two numbers: {begin offset, end offset}
|
||||
// NSRect -> list of four numbers: {left, bottom, right, top}
|
||||
// NSSize -> list of two numbers: {width, height}
|
||||
@interface NSValue (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
@end
|
||||
|
||||
// No need for ObjC -> AS conversion here, we fall through to NSObject as a collection.
|
||||
// For AS -> ObjC conversion, we build an array using the primitive list methods on
|
||||
// NSAppleEventDescriptor.
|
||||
@interface NSArray (JavaAppleScriptEngineAdditions)
|
||||
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
|
||||
// Please see the CocoaScripting release note for behavior. It's kind of complicated.
|
||||
//
|
||||
// methods wrap the primitive record methods on NSAppleEventDescriptor.
|
||||
@interface NSDictionary (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
// be aware that a null descriptor does not correspond to the 'null' keyword in
|
||||
// AppleScript - it's more like nothing at all. For example, the return
|
||||
// from an empty handler.
|
||||
@interface NSNull (JavaAppleScriptEngineAdditions)
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue;
|
||||
+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc;
|
||||
@end
|
||||
|
||||
|
||||
@interface NSNumber (JavaAppleScriptEngineAdditionsPrivate)
|
||||
+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes;
|
||||
+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes;
|
||||
+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes;
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSObject (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
// collections go to lists
|
||||
if (![self respondsToSelector:@selector(objectEnumerator)]) {
|
||||
// encode the description as a fallback - this is pretty useless, only helpful for debugging
|
||||
return [[self description] aeDescriptorValue];
|
||||
}
|
||||
|
||||
NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor listDescriptor];
|
||||
NSEnumerator *objectEnumerator = [(id)self objectEnumerator];
|
||||
|
||||
unsigned int i = 1; // apple event descriptors are 1-indexed
|
||||
id currentObject;
|
||||
while((currentObject = [objectEnumerator nextObject]) != nil) {
|
||||
[resultDesc insertDescriptor:[currentObject aeDescriptorValue] atIndex:i++];
|
||||
}
|
||||
|
||||
return resultDesc;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSArray (JavaAppleScriptEngineAdditions)
|
||||
|
||||
// don't need to override aeDescriptorValue, the NSObject will treat the array as a collection
|
||||
+ (NSArray *)arrayWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
NSAppleEventDescriptor *listDesc = [desc coerceToDescriptorType:typeAEList];
|
||||
NSMutableArray *resultArray = [NSMutableArray array];
|
||||
|
||||
// apple event descriptors are 1-indexed
|
||||
unsigned int listCount = [listDesc numberOfItems];
|
||||
unsigned int i;
|
||||
for (i = 1; i <= listCount; i++) {
|
||||
[resultArray addObject:[[listDesc descriptorAtIndex:i] objCObjectValue]];
|
||||
}
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSDictionary (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
NSAppleEventDescriptor *resultDesc = [NSAppleEventDescriptor recordDescriptor];
|
||||
NSMutableArray *userFields = [NSMutableArray array];
|
||||
NSArray *keys = [self allKeys];
|
||||
|
||||
unsigned int keyCount = [keys count];
|
||||
unsigned int i;
|
||||
for (i = 0; i < keyCount; i++) {
|
||||
id key = [keys objectAtIndex:i];
|
||||
|
||||
if ([key isKindOfClass:[NSNumber class]]) {
|
||||
[resultDesc setDescriptor:[[self objectForKey:key] aeDescriptorValue] forKeyword:[(NSNumber *)key intValue]];
|
||||
} else if ([key isKindOfClass:[NSString class]]) {
|
||||
[userFields addObject:key];
|
||||
[userFields addObject:[self objectForKey:key]];
|
||||
}
|
||||
}
|
||||
|
||||
if ([userFields count] > 0) {
|
||||
[resultDesc setDescriptor:[userFields aeDescriptorValue] forKeyword:keyASUserRecordFields];
|
||||
}
|
||||
|
||||
return resultDesc;
|
||||
}
|
||||
|
||||
+ (NSDictionary *)dictionaryWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
NSAppleEventDescriptor *recDescriptor = [desc coerceToDescriptorType:typeAERecord];
|
||||
NSMutableDictionary *resultDict = [NSMutableDictionary dictionary];
|
||||
|
||||
// NSAppleEventDescriptor uses 1 indexing
|
||||
unsigned int recordCount = [recDescriptor numberOfItems];
|
||||
unsigned int recordIndex;
|
||||
for (recordIndex = 1; recordIndex <= recordCount; recordIndex++) {
|
||||
AEKeyword keyword = [recDescriptor keywordForDescriptorAtIndex:recordIndex];
|
||||
|
||||
if(keyword == keyASUserRecordFields) {
|
||||
NSAppleEventDescriptor *listDescriptor = [recDescriptor descriptorAtIndex:recordIndex];
|
||||
|
||||
// NSAppleEventDescriptor uses 1 indexing
|
||||
unsigned int listCount = [listDescriptor numberOfItems];
|
||||
unsigned int listIndex;
|
||||
for (listIndex = 1; listIndex <= listCount; listIndex += 2) {
|
||||
id keyObj = [[listDescriptor descriptorAtIndex:listIndex] objCObjectValue];
|
||||
id valObj = [[listDescriptor descriptorAtIndex:listIndex+1] objCObjectValue];
|
||||
|
||||
[resultDict setObject:valObj forKey:keyObj];
|
||||
}
|
||||
} else {
|
||||
id keyObj = [NSNumber numberWithInt:keyword];
|
||||
id valObj = [[recDescriptor descriptorAtIndex:recordIndex] objCObjectValue];
|
||||
|
||||
[resultDict setObject:valObj forKey:keyObj];
|
||||
}
|
||||
}
|
||||
|
||||
return resultDict;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSString (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
return [NSAppleEventDescriptor descriptorWithString:self];
|
||||
}
|
||||
|
||||
+ (NSString *)stringWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
return [desc stringValue];
|
||||
}
|
||||
|
||||
+ (NSString *)versionWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
const AEDesc *aeDesc = [desc aeDesc];
|
||||
VersRec v;
|
||||
AEGetDescData(aeDesc, &v, sizeof(v));
|
||||
return [[[NSString alloc] initWithBytes:&v.shortVersion[1] length:StrLength(v.shortVersion) encoding:NSUTF8StringEncoding] autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSNull (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
return [NSAppleEventDescriptor nullDescriptor];
|
||||
}
|
||||
|
||||
+ (NSNull *)nullWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
return [NSNull null];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSDate (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
LongDateTime ldt;
|
||||
UCConvertCFAbsoluteTimeToLongDateTime(CFDateGetAbsoluteTime((CFDateRef)self), &ldt);
|
||||
return [NSAppleEventDescriptor descriptorWithLongDateTime:ldt];
|
||||
}
|
||||
|
||||
+ (NSDate *)dateWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
CFAbsoluteTime absTime;
|
||||
UCConvertLongDateTimeToCFAbsoluteTime([desc longDateTimeValue], &absTime);
|
||||
NSDate *resultDate = (NSDate *)CFDateCreate(NULL, absTime);
|
||||
return [resultDate autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
static inline int areEqualEncodings(const char *enc1, const char *enc2) {
|
||||
return (strcmp(enc1, enc2) == 0);
|
||||
}
|
||||
|
||||
@implementation NSNumber (JavaAppleScriptEngineAdditions)
|
||||
|
||||
-(id)jaseDescriptorValueWithFloatP:(void *)float_p byteCount:(int)bytes {
|
||||
float floatVal;
|
||||
if (bytes < sizeof(Float32)) {
|
||||
floatVal = [self floatValue];
|
||||
float_p = &floatVal;
|
||||
bytes = sizeof(floatVal);
|
||||
}
|
||||
|
||||
double doubleVal;
|
||||
if (bytes > sizeof(Float64)) {
|
||||
doubleVal = [self doubleValue];
|
||||
float_p = &doubleVal;
|
||||
bytes = sizeof(doubleVal);
|
||||
}
|
||||
|
||||
if (bytes == sizeof(Float32)) {
|
||||
return [NSAppleEventDescriptor descriptorWithFloat32:*(Float32 *)float_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(Float64)) {
|
||||
return [NSAppleEventDescriptor descriptorWithFloat64:*(Float64 *)float_p];
|
||||
}
|
||||
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Cannot create an NSAppleEventDescriptor for float with %d bytes of data.", bytes];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(id)jaseDescriptorValueWithSignedIntP:(void *)int_p byteCount:(int)bytes {
|
||||
int intVal;
|
||||
|
||||
if (bytes < sizeof(SInt16)) {
|
||||
intVal = [self intValue];
|
||||
int_p = &intVal;
|
||||
bytes = sizeof(intVal);
|
||||
}
|
||||
|
||||
if (bytes == sizeof(SInt16)) {
|
||||
return [NSAppleEventDescriptor descriptorWithInt16:*(SInt16 *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(SInt32)) {
|
||||
return [NSAppleEventDescriptor descriptorWithInt32:*(SInt32 *)int_p];
|
||||
}
|
||||
|
||||
double val = [self doubleValue];
|
||||
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
-(id)jaseDescriptorValueWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {
|
||||
unsigned int uIntVal;
|
||||
|
||||
if (bytes < sizeof(UInt32)) {
|
||||
uIntVal = [self unsignedIntValue];
|
||||
int_p = &uIntVal;
|
||||
bytes = sizeof(uIntVal);
|
||||
}
|
||||
|
||||
if (bytes == sizeof(UInt32)) {
|
||||
return [NSAppleEventDescriptor descriptorWithUnsignedInt32:*(UInt32 *)int_p];
|
||||
}
|
||||
|
||||
double val = (double)[self unsignedLongLongValue];
|
||||
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
// NSNumber is unfortunately complicated, because the applescript
|
||||
// type we should use depends on the c type that our NSNumber corresponds to
|
||||
|
||||
const char *type = [self objCType];
|
||||
|
||||
// convert
|
||||
if (areEqualEncodings(type, @encode(BOOL))) {
|
||||
return [NSAppleEventDescriptor descriptorWithBoolean:[self boolValue]];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(char))) {
|
||||
char val = [self charValue];
|
||||
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(short))) {
|
||||
short val = [self shortValue];
|
||||
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(int))) {
|
||||
int val = [self intValue];
|
||||
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(long))) {
|
||||
long val = [self longValue];
|
||||
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(long long))) {
|
||||
long long val = [self longLongValue];
|
||||
return [self jaseDescriptorValueWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(unsigned char))) {
|
||||
unsigned char val = [self unsignedCharValue];
|
||||
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(unsigned short))) {
|
||||
unsigned short val = [self unsignedShortValue];
|
||||
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(unsigned int))) {
|
||||
unsigned int val = [self unsignedIntValue];
|
||||
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(unsigned long))) {
|
||||
unsigned long val = [self unsignedLongValue];
|
||||
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(unsigned long long))) {
|
||||
unsigned long long val = [self unsignedLongLongValue];
|
||||
return [self jaseDescriptorValueWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(float))) {
|
||||
float val = [self floatValue];
|
||||
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(double))) {
|
||||
double val = [self doubleValue];
|
||||
return [self jaseDescriptorValueWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
[NSException raise:@"jaseUnsupportedAEDescriptorConversion"
|
||||
format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id)numberWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
DescType type = [desc descriptorType];
|
||||
|
||||
if ((type == typeTrue) || (type == typeFalse) || (type == typeBoolean)) {
|
||||
return [NSNumber numberWithBool:[desc booleanValue]];
|
||||
}
|
||||
|
||||
if (type == typeSInt16) {
|
||||
SInt16 val = [desc int16Value];
|
||||
return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (type == typeSInt32) {
|
||||
SInt32 val = [desc int32Value];
|
||||
return [NSNumber jaseNumberWithSignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (type == typeUInt32) {
|
||||
UInt32 val = [desc unsignedInt32Value];
|
||||
return [NSNumber jaseNumberWithUnsignedIntP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (type == typeIEEE32BitFloatingPoint) {
|
||||
Float32 val = [desc float32Value];
|
||||
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
if (type == typeIEEE64BitFloatingPoint) {
|
||||
Float64 val = [desc float64Value];
|
||||
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
// try to coerce to 64bit floating point
|
||||
desc = [desc coerceToDescriptorType:typeIEEE64BitFloatingPoint];
|
||||
if (desc != nil) {
|
||||
Float64 val = [desc float64Value];
|
||||
return [NSNumber jaseNumberWithFloatP:&val byteCount:sizeof(val)];
|
||||
}
|
||||
|
||||
[NSException raise:@"jaseUnsupportedAEDescriptorConversion"
|
||||
format:@"JavaAppleScriptEngineAdditions: conversion of an NSAppleEventDescriptor with objCType '%s' to an aeDescriptor is not supported.", type];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id) jaseNumberWithSignedIntP:(void *)int_p byteCount:(int)bytes {
|
||||
if (bytes == sizeof(char)) {
|
||||
return [NSNumber numberWithChar:*(char *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(short)) {
|
||||
return [NSNumber numberWithShort:*(short *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(int)) {
|
||||
return [NSNumber numberWithInt:*(int *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(long)) {
|
||||
return [NSNumber numberWithLong:*(long *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(long long)) {
|
||||
return [NSNumber numberWithLongLong:*(long long *)int_p];
|
||||
}
|
||||
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"NSNumber jaseNumberWithSignedIntP:byteCount: number with %i bytes not supported.", bytes];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id) jaseNumberWithUnsignedIntP:(void *)int_p byteCount:(int)bytes {
|
||||
if (bytes == sizeof(unsigned char)) {
|
||||
return [NSNumber numberWithUnsignedChar:*(unsigned char *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(unsigned short)) {
|
||||
return [NSNumber numberWithUnsignedShort:*(unsigned short *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(unsigned int)) {
|
||||
return [NSNumber numberWithUnsignedInt:*(unsigned int *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(unsigned long)) {
|
||||
return [NSNumber numberWithUnsignedLong:*(unsigned long *)int_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(unsigned long long)) {
|
||||
return [NSNumber numberWithUnsignedLongLong:*(unsigned long long *)int_p];
|
||||
}
|
||||
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"NSNumber numberWithUnsignedInt:byteCount: number with %i bytes not supported.", bytes];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (id) jaseNumberWithFloatP:(void *)float_p byteCount:(int)bytes {
|
||||
if (bytes == sizeof(float)) {
|
||||
return [NSNumber numberWithFloat:*(float *)float_p];
|
||||
}
|
||||
|
||||
if (bytes == sizeof(double)) {
|
||||
return [NSNumber numberWithFloat:*(double *)float_p];
|
||||
}
|
||||
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"NSNumber numberWithFloat:byteCount: floating point number with %i bytes not supported.", bytes];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSValue (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
const char *type = [self objCType];
|
||||
|
||||
if (areEqualEncodings(type, @encode(NSSize))) {
|
||||
NSSize size = [self sizeValue];
|
||||
return [[NSArray arrayWithObjects:
|
||||
[NSNumber numberWithFloat:size.width],
|
||||
[NSNumber numberWithFloat:size.height], nil] aeDescriptorValue];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(NSPoint))) {
|
||||
NSPoint point = [self pointValue];
|
||||
return [[NSArray arrayWithObjects:
|
||||
[NSNumber numberWithFloat:point.x],
|
||||
[NSNumber numberWithFloat:point.y], nil] aeDescriptorValue];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(NSRange))) {
|
||||
NSRange range = [self rangeValue];
|
||||
return [[NSArray arrayWithObjects:
|
||||
[NSNumber numberWithUnsignedInt:range.location],
|
||||
[NSNumber numberWithUnsignedInt:range.location + range.length], nil] aeDescriptorValue];
|
||||
}
|
||||
|
||||
if (areEqualEncodings(type, @encode(NSRect))) {
|
||||
NSRect rect = [self rectValue];
|
||||
return [[NSArray arrayWithObjects:
|
||||
[NSNumber numberWithFloat:rect.origin.x],
|
||||
[NSNumber numberWithFloat:rect.origin.y],
|
||||
[NSNumber numberWithFloat:rect.origin.x + rect.size.width],
|
||||
[NSNumber numberWithFloat:rect.origin.y + rect.size.height], nil] aeDescriptorValue];
|
||||
}
|
||||
|
||||
[NSException raise:@"jaseUnsupportedAEDescriptorConversion"
|
||||
format:@"JavaAppleScriptEngineAdditions: conversion of an NSNumber with objCType '%s' to an aeDescriptor is not supported.", type];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSImage (JavaAppleScriptEngineAdditions)
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
NSData *data = [self TIFFRepresentation];
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeTIFF data:data];
|
||||
}
|
||||
|
||||
+ (NSImage *)imageWithAEDesc:(NSAppleEventDescriptor *)desc {
|
||||
const AEDesc *d = [desc aeDesc];
|
||||
NSMutableData *data = [NSMutableData dataWithLength:AEGetDescDataSize(d)];
|
||||
AEGetDescData(d, [data mutableBytes], [data length]);
|
||||
return [[[NSImage alloc] initWithData:data] autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation NSAppleEventDescriptor (JavaAppleScriptEngineAdditions)
|
||||
|
||||
// we're going to leak this. It doesn't matter much for running apps, but
|
||||
// for developers it might be nice to try to dispose of it (so it would not clutter the
|
||||
// output when testing for leaks)
|
||||
static NSMutableDictionary *handlerDict = nil;
|
||||
|
||||
- (id)objCObjectValue {
|
||||
if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];
|
||||
|
||||
id returnObj;
|
||||
DescType type = [self descriptorType];
|
||||
NSInvocation *handlerInvocation = [handlerDict objectForKey:[NSValue valueWithBytes:&type objCType:@encode(DescType)]];
|
||||
if (handlerInvocation == nil) {
|
||||
if (type == typeType) {
|
||||
DescType subType;
|
||||
AEGetDescData([self aeDesc], &subType, sizeof(subType));
|
||||
if (subType == typeNull) return [NSNull null];
|
||||
}
|
||||
// return raw apple event descriptor if no handler is registered
|
||||
returnObj = self;
|
||||
} else {
|
||||
[handlerInvocation setArgument:&self atIndex:2];
|
||||
[handlerInvocation invoke];
|
||||
[handlerInvocation getReturnValue:&returnObj];
|
||||
}
|
||||
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
// FIXME - error checking, non nil handler
|
||||
+ (void)registerConversionHandler:(id)anObject selector:(SEL)aSelector forDescriptorTypes:(DescType)firstType, ... {
|
||||
if (handlerDict == nil) [NSAppleEventDescriptor jaseSetUpHandlerDict];
|
||||
|
||||
NSInvocation *handlerInvocation = [NSInvocation invocationWithMethodSignature:[anObject methodSignatureForSelector:aSelector]];
|
||||
[handlerInvocation setTarget:anObject];
|
||||
[handlerInvocation setSelector:aSelector];
|
||||
|
||||
DescType aType = firstType;
|
||||
va_list typesList;
|
||||
va_start(typesList, firstType);
|
||||
do {
|
||||
NSValue *type = [NSValue valueWithBytes:&aType objCType:@encode(DescType)];
|
||||
[handlerDict setObject:handlerInvocation forKey:type];
|
||||
} while((aType = va_arg(typesList, DescType)) != 0);
|
||||
va_end(typesList);
|
||||
}
|
||||
|
||||
|
||||
- (NSAppleEventDescriptor *)aeDescriptorValue {
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (id)descriptorWithInt16:(SInt16)val {
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt16 bytes:&val length:sizeof(val)];
|
||||
}
|
||||
|
||||
- (SInt16)int16Value {
|
||||
SInt16 retValue;
|
||||
[[[self coerceToDescriptorType:typeSInt16] data] getBytes:&retValue];
|
||||
return retValue;
|
||||
}
|
||||
|
||||
+ (id)descriptorWithUnsignedInt32:(UInt32)val {
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeUInt32 bytes:&val length:sizeof(val)];
|
||||
}
|
||||
|
||||
- (UInt32)unsignedInt32Value {
|
||||
UInt32 retValue;
|
||||
[[[self coerceToDescriptorType:typeUInt32] data] getBytes:&retValue];
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
+ (id)descriptorWithFloat32:(Float32)val {
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE32BitFloatingPoint bytes:&val length:sizeof(val)];
|
||||
}
|
||||
|
||||
- (Float32)float32Value {
|
||||
Float32 retValue;
|
||||
[[[self coerceToDescriptorType:typeIEEE32BitFloatingPoint] data] getBytes:&retValue];
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
+ (id)descriptorWithFloat64:(Float64)val {
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&val length:sizeof(val)];
|
||||
}
|
||||
|
||||
- (Float64)float64Value {
|
||||
Float64 retValue;
|
||||
[[[self coerceToDescriptorType:typeIEEE64BitFloatingPoint] data] getBytes:&retValue];
|
||||
return retValue;
|
||||
}
|
||||
|
||||
+ (id)descriptorWithLongDateTime:(LongDateTime)val {
|
||||
return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&val length:sizeof(val)];
|
||||
}
|
||||
|
||||
- (LongDateTime)longDateTimeValue {
|
||||
LongDateTime retValue;
|
||||
[[[self coerceToDescriptorType:typeLongDateTime] data] getBytes:&retValue];
|
||||
return retValue;
|
||||
}
|
||||
|
||||
+ (void)jaseSetUpHandlerDict {
|
||||
handlerDict = [[NSMutableDictionary alloc] init];
|
||||
|
||||
// register default handlers
|
||||
// types are culled from AEDataModel.h and AERegistry.h
|
||||
|
||||
// string -> NSStrings
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(stringWithAEDesc:) forDescriptorTypes:
|
||||
typeUnicodeText, typeText, typeUTF8Text, typeCString, typeChar, nil];
|
||||
|
||||
// number/bool -> NSNumber
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSNumber class] selector:@selector(numberWithAEDesc:) forDescriptorTypes:
|
||||
typeBoolean, typeTrue, typeFalse,
|
||||
typeSInt16, typeSInt32, typeUInt32, typeSInt64,
|
||||
typeIEEE32BitFloatingPoint, typeIEEE64BitFloatingPoint, type128BitFloatingPoint, nil];
|
||||
|
||||
// list -> NSArray
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSArray class] selector:@selector(arrayWithAEDesc:) forDescriptorTypes:typeAEList, nil];
|
||||
|
||||
// record -> NSDictionary
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSDictionary class] selector:@selector(dictionaryWithAEDesc:) forDescriptorTypes:typeAERecord, nil];
|
||||
|
||||
// date -> NSDate
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSDate class] selector:@selector(dateWithAEDesc:) forDescriptorTypes:typeLongDateTime, nil];
|
||||
|
||||
// images -> NSImage
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSImage class] selector:@selector(imageWithAEDesc:) forDescriptorTypes:
|
||||
typeTIFF, typeJPEG, typeGIF, typePict, typeIconFamily, typeIconAndMask, nil];
|
||||
|
||||
// vers -> NSString
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSString class] selector:@selector(versionWithAEDesc:) forDescriptorTypes:typeVersion, nil];
|
||||
|
||||
// null -> NSNull
|
||||
[NSAppleEventDescriptor registerConversionHandler:[NSNull class] selector:@selector(nullWithAEDesc:) forDescriptorTypes:typeNull, nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, 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.
|
||||
*/
|
||||
|
||||
#import "apple_applescript_AppleScriptEngine.h"
|
||||
#import "apple_applescript_AppleScriptEngineFactory.h"
|
||||
|
||||
// Must include this before JavaNativeFoundation.h to get jni.h from build
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
#import "NS_Java_ConversionUtils.h"
|
||||
#import "AppleScriptExecutionContext.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
/*
|
||||
* Declare library specific JNI_Onload entry if static build
|
||||
*/
|
||||
DEF_STATIC_JNI_OnLoad
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngineFactory
|
||||
* Method: initNative
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_apple_applescript_AppleScriptEngineFactory_initNative
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: initNative
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_apple_applescript_AppleScriptEngine_initNative
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: createContextFrom
|
||||
* Signature: (Ljava/lang/Object;)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_apple_applescript_AppleScriptEngine_createContextFrom
|
||||
(JNIEnv *env, jclass clazz, jobject javaContext)
|
||||
{
|
||||
NSObject *obj = nil;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
obj = [[JavaAppleScriptEngineCoercion coercer] coerceJavaObject:javaContext withEnv:env];
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"converted context: %@", obj);
|
||||
#endif
|
||||
|
||||
CFRetain(obj);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return ptr_to_jlong(obj);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: createObjectFrom
|
||||
* Signature: (J)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_apple_applescript_AppleScriptEngine_createObjectFrom
|
||||
(JNIEnv *env, jclass clazz, jlong nativeContext)
|
||||
{
|
||||
jobject obj = NULL;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
obj = [[JavaAppleScriptEngineCoercion coercer] coerceNSObject:(id)jlong_to_ptr(nativeContext) withEnv:env];
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: disposeContext
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_apple_applescript_AppleScriptEngine_disposeContext
|
||||
(JNIEnv *env, jclass clazz, jlong nativeContext)
|
||||
{
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
id obj = (id)jlong_to_ptr(nativeContext);
|
||||
if (obj != nil) CFRelease(obj);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: evalScript
|
||||
* Signature: (Ljava/lang/String;J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_apple_applescript_AppleScriptEngine_evalScript
|
||||
(JNIEnv *env, jclass clazz, jstring ascript, jlong contextptr)
|
||||
{
|
||||
id retval = nil;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
NSDictionary *ncontext = jlong_to_ptr(contextptr);
|
||||
NSString *source = JNFJavaToNSString(env, ascript);
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"evalScript(source:\"%@\" context: %@)", source, ncontext);
|
||||
#endif
|
||||
|
||||
AppleScriptExecutionContext *scriptInvocationCtx = [[[AppleScriptExecutionContext alloc] initWithSource:source context:ncontext] autorelease];
|
||||
retval = [scriptInvocationCtx invokeWithEnv:env];
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"returning: %@", retval);
|
||||
#endif
|
||||
|
||||
if (retval) CFRetain(retval);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return ptr_to_jlong(retval);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: apple_applescript_AppleScriptEngine
|
||||
* Method: evalScriptFromURL
|
||||
* Signature: (Ljava/lang/String;J)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_apple_applescript_AppleScriptEngine_evalScriptFromURL
|
||||
(JNIEnv *env, jclass clazz, jstring afilename, jlong contextptr)
|
||||
{
|
||||
id retval = nil;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
NSDictionary *ncontext = jlong_to_ptr(contextptr);
|
||||
NSString *filename = JNFJavaToNSString(env, afilename);
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"evalScript(filename:\"%@\" context: %@)", filename, ncontext);
|
||||
#endif
|
||||
|
||||
AppleScriptExecutionContext *scriptInvocationCtx = [[[AppleScriptExecutionContext alloc] initWithFile:filename context:ncontext] autorelease];
|
||||
retval = [scriptInvocationCtx invokeWithEnv:env];
|
||||
|
||||
#ifdef DEBUG
|
||||
NSLog(@"returning: %@", retval);
|
||||
#endif
|
||||
|
||||
if (retval) CFRetain(retval);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
return ptr_to_jlong(retval);
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
|
||||
@interface AppleScriptExecutionContext : NSObject {
|
||||
NSString *source;
|
||||
BOOL isFile;
|
||||
NSDictionary *context;
|
||||
NSDictionary *error;
|
||||
id returnValue;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) NSString *source;
|
||||
@property (nonatomic, retain) NSDictionary *context;
|
||||
@property (nonatomic, retain) NSDictionary *error;
|
||||
@property (nonatomic, retain) id returnValue;
|
||||
|
||||
- (id) initWithSource:(NSString *)source context:(NSDictionary *)context;
|
||||
- (id) initWithFile:(NSString *)filename context:(NSDictionary *)context;
|
||||
- (id) invokeWithEnv:(JNIEnv *)env;
|
||||
|
||||
@end
|
||||
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
#import "AppleScriptExecutionContext.h"
|
||||
|
||||
#import <Carbon/Carbon.h>
|
||||
|
||||
#import "AS_NS_ConversionUtils.h"
|
||||
|
||||
|
||||
@implementation AppleScriptExecutionContext
|
||||
|
||||
@synthesize source;
|
||||
@synthesize context;
|
||||
@synthesize error;
|
||||
@synthesize returnValue;
|
||||
|
||||
- (id) init:(NSString *)sourceIn context:(id)contextIn {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
self.source = sourceIn;
|
||||
self.context = contextIn;
|
||||
self.returnValue = nil;
|
||||
self.error = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithSource:(NSString *)sourceIn context:(NSDictionary *)contextIn {
|
||||
self = [self init:sourceIn context:contextIn];
|
||||
isFile = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithFile:(NSString *)filenameIn context:(NSDictionary *)contextIn {
|
||||
self = [self init:filenameIn context:contextIn];
|
||||
isFile = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
self.source = nil;
|
||||
self.context = nil;
|
||||
self.returnValue = nil;
|
||||
self.error = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSAppleScript *) scriptFromURL {
|
||||
NSURL *url = [NSURL URLWithString:source];
|
||||
NSDictionary *err = nil;
|
||||
NSAppleScript *script = [[[NSAppleScript alloc] initWithContentsOfURL:url error:(&err)] autorelease];
|
||||
if (err != nil) self.error = err;
|
||||
return script;
|
||||
}
|
||||
|
||||
- (NSAppleScript *) scriptFromSource {
|
||||
return [[[NSAppleScript alloc] initWithSource:source] autorelease];
|
||||
}
|
||||
|
||||
- (NSAppleEventDescriptor *) functionInvocationEvent {
|
||||
NSString *function = [[context objectForKey:@"javax_script_function"] description];
|
||||
if (function == nil) return nil;
|
||||
|
||||
// wrap the arg in an array if it is not already a list
|
||||
id args = [context objectForKey:@"javax_script_argv"];
|
||||
if (![args isKindOfClass:[NSArray class]]) {
|
||||
args = [NSArray arrayWithObjects:args, nil];
|
||||
}
|
||||
|
||||
// triangulate our target
|
||||
int pid = [[NSProcessInfo processInfo] processIdentifier];
|
||||
NSAppleEventDescriptor* targetAddress = [NSAppleEventDescriptor descriptorWithDescriptorType:typeKernelProcessID
|
||||
bytes:&pid
|
||||
length:sizeof(pid)];
|
||||
|
||||
// create the event to call a subroutine in the script
|
||||
NSAppleEventDescriptor* event = [[NSAppleEventDescriptor alloc] initWithEventClass:kASAppleScriptSuite
|
||||
eventID:kASSubroutineEvent
|
||||
targetDescriptor:targetAddress
|
||||
returnID:kAutoGenerateReturnID
|
||||
transactionID:kAnyTransactionID];
|
||||
|
||||
// set up the handler
|
||||
NSAppleEventDescriptor* subroutineDescriptor = [NSAppleEventDescriptor descriptorWithString:[function lowercaseString]];
|
||||
[event setParamDescriptor:subroutineDescriptor forKeyword:keyASSubroutineName];
|
||||
|
||||
// set up the arguments
|
||||
[event setParamDescriptor:[args aeDescriptorValue] forKeyword:keyDirectObject];
|
||||
|
||||
return [event autorelease];
|
||||
}
|
||||
|
||||
- (void) invoke {
|
||||
// create our script
|
||||
NSAppleScript *script = isFile ? [self scriptFromURL] : [self scriptFromSource];
|
||||
if (self.error != nil) return;
|
||||
|
||||
// find out if we have a subroutine to call
|
||||
NSAppleEventDescriptor *fxnInvkEvt = [self functionInvocationEvent];
|
||||
|
||||
// exec!
|
||||
NSAppleEventDescriptor *desc = nil;
|
||||
NSDictionary *err = nil;
|
||||
if (fxnInvkEvt == nil) {
|
||||
desc = [script executeAndReturnError:(&err)];
|
||||
} else {
|
||||
desc = [script executeAppleEvent:fxnInvkEvt error:(&err)];
|
||||
}
|
||||
|
||||
// if we encountered an exception, stash and bail
|
||||
if (err != nil) {
|
||||
self.error = err;
|
||||
return;
|
||||
}
|
||||
|
||||
// convert to NSObjects, and return in ivar
|
||||
self.returnValue = [desc objCObjectValue];
|
||||
}
|
||||
|
||||
- (id) invokeWithEnv:(JNIEnv *)env {
|
||||
BOOL useAnyThread = [@"any-thread" isEqual:[context valueForKey:@"javax_script_threading"]];
|
||||
|
||||
// check if we are already on the AppKit thread, if desired
|
||||
if(pthread_main_np() || useAnyThread) {
|
||||
[self invoke];
|
||||
} else {
|
||||
[JNFRunLoop performOnMainThread:@selector(invoke) on:self withObject:nil waitUntilDone:YES];
|
||||
}
|
||||
|
||||
// if we have an exception parked in our ivar, snarf the message (if there is one), and toss a ScriptException
|
||||
if (self.error != nil) {
|
||||
NSString *asErrString = [self.error objectForKey:NSAppleScriptErrorMessage];
|
||||
if (!asErrString) asErrString = @"AppleScriptEngine failed to execute script."; // usually when we fail to load a file
|
||||
[JNFException raise:env as:"javax/script/ScriptException" reason:[asErrString UTF8String]];
|
||||
}
|
||||
|
||||
return self.returnValue;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
#import <JavaNativeFoundation/JavaNativeFoundation.h>
|
||||
|
||||
|
||||
@interface JavaAppleScriptEngineCoercion : NSObject
|
||||
|
||||
+ (JNFTypeCoercer *) coercer;
|
||||
|
||||
@end
|
||||
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, 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.
|
||||
*/
|
||||
|
||||
#import "NS_Java_ConversionUtils.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface JavaAppleScriptBaseConverter : NSObject <JNFTypeCoercion>
|
||||
@end
|
||||
|
||||
@interface JavaAppleScriptImageConverter : NSObject <JNFTypeCoercion>
|
||||
@end
|
||||
|
||||
@interface JavaAppleScriptVersionConverter : NSObject <JNFTypeCoercion>
|
||||
@end
|
||||
|
||||
@interface JavaAppleScriptNullConverter : NSObject <JNFTypeCoercion>
|
||||
@end
|
||||
|
||||
|
||||
@implementation JavaAppleScriptEngineCoercion
|
||||
|
||||
static JNFTypeCoercer *appleScriptCoercer = nil;
|
||||
|
||||
+ (JNFTypeCoercer *) coercer {
|
||||
if (appleScriptCoercer) return appleScriptCoercer;
|
||||
|
||||
id asSpecificCoercions = [[JNFDefaultCoercions defaultCoercer] deriveCoercer];
|
||||
[asSpecificCoercions addCoercion:[[[JavaAppleScriptImageConverter alloc] init] autorelease] forNSClass:[NSImage class] javaClass:@"java/awt/Image"];
|
||||
[asSpecificCoercions addCoercion:[[[JavaAppleScriptVersionConverter alloc] init] autorelease] forNSClass:[NSAppleEventDescriptor class] javaClass:nil];
|
||||
[asSpecificCoercions addCoercion:[[[JavaAppleScriptNullConverter alloc] init] autorelease] forNSClass:[NSNull class] javaClass:nil];
|
||||
|
||||
return appleScriptCoercer = [asSpecificCoercions retain];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// [NSObject description] <-> java.lang.Object.toString()
|
||||
@implementation JavaAppleScriptBaseConverter
|
||||
|
||||
// by default, bizzare NSObjects will have -description called on them, and passed back to Java like that
|
||||
- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
return JNFNSToJavaString(env, [obj description]);
|
||||
}
|
||||
|
||||
// by default, bizzare Java objects will be toString()'d and passed to AppleScript like that
|
||||
- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
return JNFObjectToString(env, obj);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// NSImage <-> apple.awt.CImage
|
||||
@implementation JavaAppleScriptImageConverter
|
||||
|
||||
static JNF_CLASS_CACHE(jc_CImage, "apple/awt/CImage");
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_CImage_getCreator, jc_CImage, "getCreator", "()Lapple/awt/CImage$Creator;");
|
||||
static JNF_MEMBER_CACHE(jm_CImage_getNSImage, jc_CImage, "getNSImage", "()J");
|
||||
|
||||
static JNF_CLASS_CACHE(jc_CImage_Generator, "apple/awt/CImage$Creator");
|
||||
static JNF_MEMBER_CACHE(jm_CImage_Generator_createImageFromPtr, jc_CImage_Generator, "createImage", "(J)Ljava/awt/image/BufferedImage;");
|
||||
static JNF_MEMBER_CACHE(jm_CImage_Generator_createImageFromImg, jc_CImage_Generator, "createImage", "(Ljava/awt/Image;)Lapple/awt/CImage;");
|
||||
|
||||
- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
NSImage *img = (NSImage *)obj;
|
||||
CFRetain(img);
|
||||
jobject creator = JNFCallStaticObjectMethod(env, jm_CImage_getCreator);
|
||||
jobject jobj = JNFCallObjectMethod(env, creator, jm_CImage_Generator_createImageFromPtr, ptr_to_jlong(img));
|
||||
return jobj;
|
||||
}
|
||||
|
||||
- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
jobject cimage = obj;
|
||||
if (!JNFIsInstanceOf(env, obj, &jc_CImage)) {
|
||||
jobject creator = JNFCallStaticObjectMethod(env, jm_CImage_getCreator);
|
||||
cimage = JNFCallObjectMethod(env, creator, jm_CImage_Generator_createImageFromImg, obj);
|
||||
}
|
||||
|
||||
jlong nsImagePtr = JNFCallLongMethod(env, cimage, jm_CImage_getNSImage);
|
||||
|
||||
NSImage *img = (NSImage *)jlong_to_ptr(nsImagePtr);
|
||||
return [[img retain] autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// NSAppleEventDescriptor('vers') -> java.lang.String
|
||||
@implementation JavaAppleScriptVersionConverter
|
||||
|
||||
- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
NSAppleEventDescriptor *desc = (NSAppleEventDescriptor *)obj;
|
||||
|
||||
const AEDesc *aeDesc = [desc aeDesc];
|
||||
if (aeDesc->descriptorType == typeNull) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return JNFNSToJavaString(env, [obj description]);
|
||||
}
|
||||
|
||||
- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
return nil; // there is no Java object that represents a "version"
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// NSNull <-> null
|
||||
@implementation JavaAppleScriptNullConverter
|
||||
|
||||
- (jobject) coerceNSObject:(id)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- (id) coerceJavaObject:(jobject)obj withEnv:(JNIEnv *)env usingCoercer:(JNFTypeCoercion *)coercer {
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -407,3 +407,10 @@ sun/tools/jinfo/JInfoRunningProcessFlagTest.java generic-all
|
||||
sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_other
|
||||
|
||||
############################################################################
|
||||
|
||||
# 8141370
|
||||
com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java linux-i586,macosx-all
|
||||
|
||||
@ -32,6 +32,7 @@ tier1 = \
|
||||
:jdk_util \
|
||||
-java/util/WeakHashMap/GCDuringIteration.java \
|
||||
-java/util/concurrent/Phaser/Basic.java \
|
||||
-java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java
|
||||
sun/nio/cs/ISO8859x.java \
|
||||
java/nio/Buffer \
|
||||
com/sun/crypto/provider/Cipher \
|
||||
@ -42,6 +43,7 @@ tier2 = \
|
||||
java/util/zip/TestLocalTime.java \
|
||||
java/util/concurrent/Phaser/Basic.java \
|
||||
java/util/WeakHashMap/GCDuringIteration.java \
|
||||
java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \
|
||||
:jdk_io \
|
||||
:jdk_nio \
|
||||
-sun/nio/cs/ISO8859x.java \
|
||||
|
||||
210
jdk/test/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java
Normal file
210
jdk/test/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, 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
|
||||
* @run main/othervm DeadSSLLdapTimeoutTest
|
||||
* @bug 8141370
|
||||
* @key intermittent
|
||||
*/
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.io.*;
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import java.util.List;
|
||||
import java.util.Hashtable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
|
||||
|
||||
class DeadServerTimeoutSSLTest implements Callable {
|
||||
|
||||
Hashtable env;
|
||||
DeadSSLServer server;
|
||||
boolean passed = false;
|
||||
private int HANGING_TEST_TIMEOUT = 20_000;
|
||||
|
||||
public DeadServerTimeoutSSLTest(Hashtable env) throws IOException {
|
||||
this.server = new DeadSSLServer();
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
public void performOp(InitialContext ctx) throws NamingException {}
|
||||
|
||||
public void handleNamingException(NamingException e, long start, long end) {
|
||||
if (e.getCause() instanceof SocketTimeoutException) {
|
||||
// SSL connect will timeout via readReply using
|
||||
// SocketTimeoutException
|
||||
e.printStackTrace();
|
||||
pass();
|
||||
} else if (e.getCause() instanceof SSLHandshakeException
|
||||
&& e.getCause().getCause() instanceof EOFException) {
|
||||
// test seems to be failing intermittently on some
|
||||
// platforms.
|
||||
pass();
|
||||
} else {
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void pass() {
|
||||
this.passed = true;
|
||||
}
|
||||
|
||||
public void fail() {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
|
||||
public void fail(Exception e) {
|
||||
throw new RuntimeException("Test failed", e);
|
||||
}
|
||||
|
||||
boolean shutItDown(InitialContext ctx) {
|
||||
try {
|
||||
if (ctx != null) ctx.close();
|
||||
return true;
|
||||
} catch (NamingException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean call() {
|
||||
InitialContext ctx = null;
|
||||
ScheduledFuture killer = null;
|
||||
long start = System.nanoTime();
|
||||
|
||||
try {
|
||||
while(!server.accepting())
|
||||
Thread.sleep(200); // allow the server to start up
|
||||
Thread.sleep(200); // to be sure
|
||||
|
||||
env.put(Context.PROVIDER_URL, "ldap://localhost:" +
|
||||
server.getLocalPort());
|
||||
|
||||
try {
|
||||
ctx = new InitialDirContext(env);
|
||||
performOp(ctx);
|
||||
fail();
|
||||
} catch (NamingException e) {
|
||||
long end = System.nanoTime();
|
||||
System.out.println(this.getClass().toString() + " - elapsed: "
|
||||
+ NANOSECONDS.toMillis(end - start));
|
||||
handleNamingException(e, start, end);
|
||||
} finally {
|
||||
if (killer != null && !killer.isDone())
|
||||
killer.cancel(true);
|
||||
shutItDown(ctx);
|
||||
server.close();
|
||||
}
|
||||
return passed;
|
||||
} catch (IOException|InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeadSSLServer extends Thread {
|
||||
ServerSocket serverSock;
|
||||
boolean accepting = false;
|
||||
|
||||
public DeadSSLServer() throws IOException {
|
||||
this.serverSock = new ServerSocket(0);
|
||||
start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
try {
|
||||
accepting = true;
|
||||
Socket socket = serverSock.accept();
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getLocalPort() {
|
||||
return serverSock.getLocalPort();
|
||||
}
|
||||
|
||||
public boolean accepting() {
|
||||
return accepting;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
serverSock.close();
|
||||
}
|
||||
}
|
||||
|
||||
public class DeadSSLLdapTimeoutTest {
|
||||
|
||||
static Hashtable createEnv() {
|
||||
Hashtable env = new Hashtable(11);
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY,
|
||||
"com.sun.jndi.ldap.LdapCtxFactory");
|
||||
return env;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
InitialContext ctx = null;
|
||||
|
||||
//
|
||||
// Running this test serially as it seems to tickle a problem
|
||||
// on older kernels
|
||||
//
|
||||
// run the DeadServerTest with connect / read timeouts set
|
||||
// and ssl enabled
|
||||
// this should exit with a SocketTimeoutException as the root cause
|
||||
// it should also use the connect timeout instead of the read timeout
|
||||
System.out.println("Running connect timeout test with 10ms connect timeout, 3000ms read timeout & SSL");
|
||||
Hashtable sslenv = createEnv();
|
||||
sslenv.put("com.sun.jndi.ldap.connect.timeout", "10");
|
||||
sslenv.put("com.sun.jndi.ldap.read.timeout", "3000");
|
||||
sslenv.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
boolean testFailed =
|
||||
(new DeadServerTimeoutSSLTest(sslenv).call()) ? false : true;
|
||||
|
||||
if (testFailed) {
|
||||
throw new AssertionError("some tests failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -225,29 +225,6 @@ class DeadServerTimeoutTest extends DeadServerTest {
|
||||
}
|
||||
}
|
||||
|
||||
class DeadServerTimeoutSSLTest extends DeadServerTest {
|
||||
|
||||
public DeadServerTimeoutSSLTest(Hashtable env) throws IOException {
|
||||
super(env);
|
||||
}
|
||||
|
||||
public void handleNamingException(NamingException e, long start, long end) {
|
||||
if (e.getCause() instanceof SocketTimeoutException) {
|
||||
// SSL connect will timeout via readReply using
|
||||
// SocketTimeoutException
|
||||
e.printStackTrace();
|
||||
pass();
|
||||
} else if (e.getCause() instanceof SSLHandshakeException
|
||||
&& e.getCause().getCause() instanceof EOFException) {
|
||||
// test seems to be failing intermittently on some
|
||||
// platforms.
|
||||
pass();
|
||||
} else {
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ReadServerNoTimeoutTest extends ReadServerTest {
|
||||
|
||||
@ -454,21 +431,6 @@ public class LdapTimeoutTest {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Running this test serially as it seems to tickle a problem
|
||||
// on older kernels
|
||||
//
|
||||
// run the DeadServerTest with connect / read timeouts set
|
||||
// and ssl enabled
|
||||
// this should exit with a SocketTimeoutException as the root cause
|
||||
// it should also use the connect timeout instead of the read timeout
|
||||
System.out.println("Running connect timeout test with 10ms connect timeout, 3000ms read timeout & SSL");
|
||||
Hashtable sslenv = createEnv();
|
||||
sslenv.put("com.sun.jndi.ldap.connect.timeout", "10");
|
||||
sslenv.put("com.sun.jndi.ldap.read.timeout", "3000");
|
||||
sslenv.put(Context.SECURITY_PROTOCOL, "ssl");
|
||||
testFailed = (new DeadServerTimeoutSSLTest(sslenv).call()) ? false : true;
|
||||
|
||||
if (testFailed) {
|
||||
throw new AssertionError("some tests failed");
|
||||
}
|
||||
|
||||
@ -2474,6 +2474,147 @@ public class TCKDuration extends AbstractTCKTest {
|
||||
test.toMillis();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toSeconds()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toSeconds_provider")
|
||||
Object[][] provider_toSeconds() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 31556926L},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), -31556927L},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, 123_456_789), -31556926L},
|
||||
{Duration.ofSeconds(0), 0L},
|
||||
{Duration.ofSeconds(0, 123_456_789), 0L},
|
||||
{Duration.ofSeconds(0, -123_456_789), -1L},
|
||||
{Duration.ofSeconds(Long.MAX_VALUE), 9223372036854775807L},
|
||||
{Duration.ofSeconds(Long.MIN_VALUE), -9223372036854775808L},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toSeconds_provider")
|
||||
public void test_toSeconds(Duration dur, long seconds) {
|
||||
assertEquals(dur.toSeconds(), seconds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toDaysPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toDaysPart_provider")
|
||||
Object[][] provider_toDaysPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 365L},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), -365L},
|
||||
{Duration.ofSeconds(5 * 3600 + 48 * 60 + 46, 123_456_789), 0L},
|
||||
{Duration.ofDays(365), 365L},
|
||||
{Duration.ofHours(2), 0L},
|
||||
{Duration.ofHours(-2), 0L},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toDaysPart_provider")
|
||||
public void test_toDaysPart(Duration dur, long days) {
|
||||
assertEquals(dur.toDaysPart(), days);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toHoursPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toHoursPart_provider")
|
||||
Object[][] provider_toHoursPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 5},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), -5},
|
||||
{Duration.ofSeconds(48 * 60 + 46, 123_456_789), 0},
|
||||
{Duration.ofHours(2), 2},
|
||||
{Duration.ofHours(-2), -2},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toHoursPart_provider")
|
||||
public void test_toHoursPart(Duration dur, int hours) {
|
||||
assertEquals(dur.toHoursPart(), hours);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toMinutesPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toMinutesPart_provider")
|
||||
Object[][] provider_toMinutesPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 48},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), -48},
|
||||
{Duration.ofSeconds(46, 123_456_789),0},
|
||||
{Duration.ofMinutes(48), 48},
|
||||
{Duration.ofHours(2), 0},
|
||||
{Duration.ofHours(-2),0},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toMinutesPart_provider")
|
||||
public void test_toMinutesPart(Duration dur, int minutes) {
|
||||
assertEquals(dur.toMinutesPart(), minutes);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toSecondsPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toSecondsPart_provider")
|
||||
Object[][] provider_toSecondsPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 46},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), -47},
|
||||
{Duration.ofSeconds(0, 123_456_789), 0},
|
||||
{Duration.ofSeconds(46), 46},
|
||||
{Duration.ofHours(2), 0},
|
||||
{Duration.ofHours(-2), 0},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toSecondsPart_provider")
|
||||
public void test_toSecondsPart(Duration dur, int seconds) {
|
||||
assertEquals(dur.toSecondsPart(), seconds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toMillisPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toMillisPart_provider")
|
||||
Object[][] provider_toMillisPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 123},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), 876},
|
||||
{Duration.ofSeconds(5 * 3600 + 48 * 60 + 46, 0), 0},
|
||||
{Duration.ofMillis(123), 123},
|
||||
{Duration.ofHours(2), 0},
|
||||
{Duration.ofHours(-2), 0},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toMillisPart_provider")
|
||||
public void test_toMillisPart(Duration dur, int millis) {
|
||||
assertEquals(dur.toMillisPart(), millis);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// toNanosPart()
|
||||
//-----------------------------------------------------------------------
|
||||
@DataProvider(name="toNanosPart_provider")
|
||||
Object[][] provider_toNanosPart() {
|
||||
return new Object[][] {
|
||||
{Duration.ofSeconds(365 * 86400 + 5 * 3600 + 48 * 60 + 46, 123_456_789), 123_456_789},
|
||||
{Duration.ofSeconds(-365 * 86400 - 5 * 3600 - 48 * 60 - 46, -123_456_789), 876_543_211},
|
||||
{Duration.ofSeconds(5 * 3600 + 48 * 60 + 46, 0), 0},
|
||||
{Duration.ofNanos(123_456_789), 123_456_789},
|
||||
{Duration.ofHours(2), 0},
|
||||
{Duration.ofHours(-2), 0},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider="toNanosPart_provider")
|
||||
public void test_toNanosPart(Duration dur, int nanos) {
|
||||
assertEquals(dur.toNanosPart(), nanos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// compareTo()
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -58,6 +58,21 @@ import static java.util.Collections.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class MOAT {
|
||||
// Collections under test must not be initialized to contain this value,
|
||||
// and maps under test must not contain this value as a key.
|
||||
// It's used as a sentinel for absent-element testing.
|
||||
static final int ABSENT_VALUE = 778347983;
|
||||
|
||||
static final Integer[] integerArray;
|
||||
static {
|
||||
Integer[] ia = new Integer[20];
|
||||
// fill with 1..20 inclusive
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
ia[i] = i + 1;
|
||||
}
|
||||
integerArray = ia;
|
||||
}
|
||||
|
||||
public static void realMain(String[] args) {
|
||||
|
||||
testCollection(new NewAbstractCollection<Integer>());
|
||||
@ -178,6 +193,70 @@ public class MOAT {
|
||||
equal(singletonMap.size(), 1);
|
||||
testMap(singletonMap);
|
||||
testImmutableMap(singletonMap);
|
||||
|
||||
// Immutable List
|
||||
testEmptyList(List.of());
|
||||
for (List<Integer> list : Arrays.asList(
|
||||
List.<Integer>of(),
|
||||
List.of(1),
|
||||
List.of(1, 2),
|
||||
List.of(1, 2, 3),
|
||||
List.of(1, 2, 3, 4),
|
||||
List.of(1, 2, 3, 4, 5),
|
||||
List.of(1, 2, 3, 4, 5, 6),
|
||||
List.of(1, 2, 3, 4, 5, 6, 7),
|
||||
List.of(1, 2, 3, 4, 5, 6, 7, 8),
|
||||
List.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
|
||||
List.of(integerArray))) {
|
||||
testCollection(list);
|
||||
testImmutableList(list);
|
||||
}
|
||||
|
||||
// Immutable Set
|
||||
testEmptySet(Set.of());
|
||||
for (Set<Integer> set : Arrays.asList(
|
||||
Set.<Integer>of(),
|
||||
Set.of(1),
|
||||
Set.of(1, 2),
|
||||
Set.of(1, 2, 3),
|
||||
Set.of(1, 2, 3, 4),
|
||||
Set.of(1, 2, 3, 4, 5),
|
||||
Set.of(1, 2, 3, 4, 5, 6),
|
||||
Set.of(1, 2, 3, 4, 5, 6, 7),
|
||||
Set.of(1, 2, 3, 4, 5, 6, 7, 8),
|
||||
Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
|
||||
Set.of(integerArray))) {
|
||||
testCollection(set);
|
||||
testImmutableSet(set);
|
||||
}
|
||||
|
||||
// Immutable Map
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20];
|
||||
for (int i = 0; i < ea.length; i++) {
|
||||
ea[i] = Map.entry(i+1, i+101);
|
||||
}
|
||||
|
||||
testEmptyMap(Map.of());
|
||||
for (Map<Integer,Integer> map : Arrays.asList(
|
||||
Map.<Integer,Integer>of(),
|
||||
Map.of(1, 101),
|
||||
Map.of(1, 101, 2, 202),
|
||||
Map.of(1, 101, 2, 202, 3, 303),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909),
|
||||
Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010),
|
||||
Map.ofEntries(ea))) {
|
||||
testMap(map);
|
||||
testImmutableMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkContainsSelf(Collection<Integer> c) {
|
||||
@ -190,6 +269,17 @@ public class MOAT {
|
||||
check(c.containsAll(new ArrayList<Integer>()));
|
||||
}
|
||||
|
||||
private static void checkUnique(Set<Integer> s) {
|
||||
for (Integer i : s) {
|
||||
int count = 0;
|
||||
for (Integer j : s) {
|
||||
if (Objects.equals(i,j))
|
||||
++count;
|
||||
}
|
||||
check(count == 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void testEmptyCollection(Collection<T> c) {
|
||||
check(c.isEmpty());
|
||||
equal(c.size(), 0);
|
||||
@ -330,19 +420,19 @@ public class MOAT {
|
||||
}
|
||||
|
||||
private static boolean supportsAdd(Collection<Integer> c) {
|
||||
try { check(c.add(778347983)); }
|
||||
try { check(c.add(ABSENT_VALUE)); }
|
||||
catch (UnsupportedOperationException t) { return false; }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
try {
|
||||
check(c.contains(778347983));
|
||||
check(c.remove(778347983));
|
||||
check(c.contains(ABSENT_VALUE));
|
||||
check(c.remove(ABSENT_VALUE));
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean supportsRemove(Collection<Integer> c) {
|
||||
try { check(! c.remove(19134032)); }
|
||||
try { check(! c.remove(ABSENT_VALUE)); }
|
||||
catch (UnsupportedOperationException t) { return false; }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
return true;
|
||||
@ -359,6 +449,7 @@ public class MOAT {
|
||||
checkContainsSelf(c);
|
||||
checkContainsEmpty(c);
|
||||
check(c.size() != 0 ^ c.isEmpty());
|
||||
check(! c.contains(ABSENT_VALUE));
|
||||
|
||||
{
|
||||
int size = 0;
|
||||
@ -366,6 +457,10 @@ public class MOAT {
|
||||
check(c.size() == size);
|
||||
}
|
||||
|
||||
if (c instanceof Set) {
|
||||
checkUnique((Set<Integer>)c);
|
||||
}
|
||||
|
||||
check(c.toArray().length == c.size());
|
||||
check(c.toArray().getClass() == Object[].class
|
||||
||
|
||||
@ -861,6 +956,20 @@ public class MOAT {
|
||||
checkFunctionalInvariants(m.keySet());
|
||||
checkFunctionalInvariants(m.values());
|
||||
check(m.size() != 0 ^ m.isEmpty());
|
||||
check(! m.containsKey(ABSENT_VALUE));
|
||||
|
||||
if (m instanceof Serializable) {
|
||||
//System.out.printf("Serializing %s%n", m.getClass().getName());
|
||||
try {
|
||||
Object clone = serialClone(m);
|
||||
equal(m instanceof Serializable,
|
||||
clone instanceof Serializable);
|
||||
equal(m, clone);
|
||||
} catch (Error xxx) {
|
||||
if (! (xxx.getCause() instanceof NotSerializableException))
|
||||
throw xxx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMap(Map<Integer,Integer> m) {
|
||||
@ -910,13 +1019,13 @@ public class MOAT {
|
||||
// We're asking for .equals(...) semantics
|
||||
if (m instanceof IdentityHashMap) return false;
|
||||
|
||||
try { check(m.put(778347983,12735) == null); }
|
||||
try { check(m.put(ABSENT_VALUE,12735) == null); }
|
||||
catch (UnsupportedOperationException t) { return false; }
|
||||
catch (Throwable t) { unexpected(t); }
|
||||
|
||||
try {
|
||||
check(m.containsKey(778347983));
|
||||
check(m.remove(778347983) != null);
|
||||
check(m.containsKey(ABSENT_VALUE));
|
||||
check(m.remove(ABSENT_VALUE) != null);
|
||||
} catch (Throwable t) { unexpected(t); }
|
||||
return true;
|
||||
}
|
||||
|
||||
275
jdk/test/java/util/Collection/SetFactories.java
Normal file
275
jdk/test/java/util/Collection/SetFactories.java
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048330
|
||||
* @summary Test convenience static factory methods on Set.
|
||||
* @run testng SetFactories
|
||||
*/
|
||||
|
||||
|
||||
public class SetFactories {
|
||||
|
||||
static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
|
||||
static final String[] stringArray;
|
||||
static {
|
||||
String[] sa = new String[NUM_STRINGS];
|
||||
for (int i = 0; i < NUM_STRINGS; i++) {
|
||||
sa[i] = String.valueOf((char)('a' + i));
|
||||
}
|
||||
stringArray = sa;
|
||||
}
|
||||
|
||||
static Object[] a(Set<String> act, Set<String> exp) {
|
||||
return new Object[] { act, exp };
|
||||
}
|
||||
|
||||
static Set<String> hashSetOf(String... args) {
|
||||
return new HashSet<>(Arrays.asList(args));
|
||||
}
|
||||
|
||||
@DataProvider(name="empty")
|
||||
public Iterator<Object[]> empty() {
|
||||
return Collections.singletonList(
|
||||
// actual, expected
|
||||
a(Set.of(), Collections.emptySet())
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonempty")
|
||||
public Iterator<Object[]> nonempty() {
|
||||
return Arrays.asList(
|
||||
// actual, expected
|
||||
a( Set.of("a"),
|
||||
hashSetOf("a")),
|
||||
a( Set.of("a", "b"),
|
||||
hashSetOf("a", "b")),
|
||||
a( Set.of("a", "b", "c"),
|
||||
hashSetOf("a", "b", "c")),
|
||||
a( Set.of("a", "b", "c", "d"),
|
||||
hashSetOf("a", "b", "c", "d")),
|
||||
a( Set.of("a", "b", "c", "d", "e"),
|
||||
hashSetOf("a", "b", "c", "d", "e")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")),
|
||||
a( Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
|
||||
hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
|
||||
a( Set.of(stringArray),
|
||||
hashSetOf(stringArray))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="all")
|
||||
public Iterator<Object[]> all() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAdd(Set<String> act, Set<String> exp) {
|
||||
act.add("x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotRemove(Set<String> act, Set<String> exp) {
|
||||
act.remove(act.iterator().next());
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void contentsMatch(Set<String> act, Set<String> exp) {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed2() {
|
||||
Set<String> set = Set.of("a", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed3() {
|
||||
Set<String> set = Set.of("a", "b", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed4() {
|
||||
Set<String> set = Set.of("a", "b", "c", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed5() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed6() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed7() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed8() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed9() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowed10() {
|
||||
Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupsDisallowedN() {
|
||||
String[] array = stringArray.clone();
|
||||
array[0] = array[1];
|
||||
Set<String> set = Set.of(array);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed1() {
|
||||
Set.of((String)null); // force one-arg overload
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2a() {
|
||||
Set.of("a", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2b() {
|
||||
Set.of(null, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed3() {
|
||||
Set.of("a", "b", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed4() {
|
||||
Set.of("a", "b", "c", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed5() {
|
||||
Set.of("a", "b", "c", "d", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed6() {
|
||||
Set.of("a", "b", "c", "d", "e", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed7() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed8() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed9() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", "h", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed10() {
|
||||
Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowedN() {
|
||||
String[] array = stringArray.clone();
|
||||
array[0] = null;
|
||||
Set.of(array);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullArrayDisallowed() {
|
||||
Set.of((Object[])null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void serialEquality(Set<String> act, Set<String> exp) {
|
||||
// assume that act.equals(exp) tested elsewhere
|
||||
Set<String> copy = serialClone(act);
|
||||
assertEquals(act, copy);
|
||||
assertEquals(copy, exp);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(obj);
|
||||
oos.close();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
return (T) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
234
jdk/test/java/util/List/ListFactories.java
Normal file
234
jdk/test/java/util/List/ListFactories.java
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048330
|
||||
* @summary Test convenience static factory methods on List.
|
||||
* @run testng ListFactories
|
||||
*/
|
||||
|
||||
public class ListFactories {
|
||||
|
||||
static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
|
||||
static final String[] stringArray;
|
||||
static {
|
||||
String[] sa = new String[NUM_STRINGS];
|
||||
for (int i = 0; i < NUM_STRINGS; i++) {
|
||||
sa[i] = String.valueOf((char)('a' + i));
|
||||
}
|
||||
stringArray = sa;
|
||||
}
|
||||
|
||||
// returns array of [actual, expected]
|
||||
static Object[] a(List<String> act, List<String> exp) {
|
||||
return new Object[] { act, exp };
|
||||
}
|
||||
|
||||
@DataProvider(name="empty")
|
||||
public Iterator<Object[]> empty() {
|
||||
return Collections.singletonList(
|
||||
a(List.of(), Collections.emptyList())
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonempty")
|
||||
public Iterator<Object[]> nonempty() {
|
||||
return asList(
|
||||
a(List.of("a"),
|
||||
asList("a")),
|
||||
a(List.of("a", "b"),
|
||||
asList("a", "b")),
|
||||
a(List.of("a", "b", "c"),
|
||||
asList("a", "b", "c")),
|
||||
a(List.of("a", "b", "c", "d"),
|
||||
asList("a", "b", "c", "d")),
|
||||
a(List.of("a", "b", "c", "d", "e"),
|
||||
asList("a", "b", "c", "d", "e")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f"),
|
||||
asList("a", "b", "c", "d", "e", "f")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i")),
|
||||
a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
|
||||
asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
|
||||
a(List.of(stringArray),
|
||||
asList(stringArray))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="all")
|
||||
public Iterator<Object[]> all() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAddLast(List<String> act, List<String> exp) {
|
||||
act.add("x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotAddFirst(List<String> act, List<String> exp) {
|
||||
act.add(0, "x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotRemove(List<String> act, List<String> exp) {
|
||||
act.remove(0);
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotSet(List<String> act, List<String> exp) {
|
||||
act.set(0, "x");
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void contentsMatch(List<String> act, List<String> exp) {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed1() {
|
||||
List.of((Object)null); // force one-arg overload
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2a() {
|
||||
List.of("a", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed2b() {
|
||||
List.of(null, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed3() {
|
||||
List.of("a", "b", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed4() {
|
||||
List.of("a", "b", "c", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed5() {
|
||||
List.of("a", "b", "c", "d", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed6() {
|
||||
List.of("a", "b", "c", "d", "e", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed7() {
|
||||
List.of("a", "b", "c", "d", "e", "f", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed8() {
|
||||
List.of("a", "b", "c", "d", "e", "f", "g", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed9() {
|
||||
List.of("a", "b", "c", "d", "e", "f", "g", "h", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowed10() {
|
||||
List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullDisallowedN() {
|
||||
String[] array = stringArray.clone();
|
||||
array[0] = null;
|
||||
List.of(array);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullArrayDisallowed() {
|
||||
List.of((Object[])null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureArrayCannotModifyList() {
|
||||
String[] array = stringArray.clone();
|
||||
List<String> list = List.of(array);
|
||||
array[0] = "xyzzy";
|
||||
assertEquals(list, Arrays.asList(stringArray));
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void serialEquality(List<String> act, List<String> exp) {
|
||||
// assume that act.equals(exp) tested elsewhere
|
||||
List<String> copy = serialClone(act);
|
||||
assertEquals(act, copy);
|
||||
assertEquals(copy, exp);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(obj);
|
||||
oos.close();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
return (T) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
380
jdk/test/java/util/Map/MapFactories.java
Normal file
380
jdk/test/java/util/Map/MapFactories.java
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048330
|
||||
* @summary Test convenience static factory methods on Map.
|
||||
* @run testng MapFactories
|
||||
*/
|
||||
|
||||
public class MapFactories {
|
||||
|
||||
static final int MAX_ENTRIES = 20; // should be larger than the largest fixed-arg overload
|
||||
static String valueFor(int i) {
|
||||
// the String literal below should be of length MAX_ENTRIES
|
||||
return "abcdefghijklmnopqrst".substring(i, i+1);
|
||||
}
|
||||
|
||||
// for "expected" values
|
||||
Map<Integer,String> genMap(int n) {
|
||||
Map<Integer,String> result = new HashMap<>();
|
||||
for (int i = 0; i < n; i++) {
|
||||
result.put(i, valueFor(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// for varargs Map.Entry methods
|
||||
@SuppressWarnings("unchecked")
|
||||
Map.Entry<Integer,String>[] genEntries(int n) {
|
||||
return IntStream.range(0, n)
|
||||
.mapToObj(i -> Map.entry(i, valueFor(i)))
|
||||
.toArray(Map.Entry[]::new);
|
||||
}
|
||||
|
||||
// returns array of [actual, expected]
|
||||
static Object[] a(Map<Integer,String> act, Map<Integer,String> exp) {
|
||||
return new Object[] { act, exp };
|
||||
}
|
||||
|
||||
@DataProvider(name="empty")
|
||||
public Iterator<Object[]> empty() {
|
||||
return Collections.singletonList(
|
||||
a(Map.of(), genMap(0))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="nonempty")
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<Object[]> nonempty() {
|
||||
return Arrays.asList(
|
||||
a(Map.of(0, "a"), genMap(1)),
|
||||
a(Map.of(0, "a", 1, "b"), genMap(2)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c"), genMap(3)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d"), genMap(4)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e"), genMap(5)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f"), genMap(6)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g"), genMap(7)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h"), genMap(8)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i"), genMap(9)),
|
||||
a(Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "h", 8, "i", 9, "j"), genMap(10)),
|
||||
a(Map.ofEntries(genEntries(MAX_ENTRIES)), genMap(MAX_ENTRIES))
|
||||
).iterator();
|
||||
}
|
||||
|
||||
@DataProvider(name="all")
|
||||
public Iterator<Object[]> all() {
|
||||
List<Object[]> all = new ArrayList<>();
|
||||
empty().forEachRemaining(all::add);
|
||||
nonempty().forEachRemaining(all::add);
|
||||
return all.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotPutNew(Map<Integer,String> act, Map<Integer,String> exp) {
|
||||
act.put(-1, "xyzzy");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotPutOld(Map<Integer,String> act, Map<Integer,String> exp) {
|
||||
act.put(0, "a");
|
||||
}
|
||||
|
||||
@Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
|
||||
public void cannotRemove(Map<Integer,String> act, Map<Integer,String> exp) {
|
||||
act.remove(act.keySet().iterator().next());
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void contentsMatch(Map<Integer,String> act, Map<Integer,String> exp) {
|
||||
assertEquals(act, exp);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed2() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 0, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed3() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 0, "c");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed4() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 0, "d");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed5() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 0, "e");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed6() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
0, "f");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed7() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 0, "g");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed8() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 0, "h");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed9() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", 0, "i");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowed10() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", 8, "i", 0, "j");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=IllegalArgumentException.class)
|
||||
public void dupKeysDisallowedN() {
|
||||
Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
|
||||
entries[MAX_ENTRIES-1] = Map.entry(0, "xxx");
|
||||
Map<Integer, String> map = Map.ofEntries(entries);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed1() {
|
||||
Map<Integer, String> map = Map.of(null, "a");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed1() {
|
||||
Map<Integer, String> map = Map.of(0, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed2() {
|
||||
Map<Integer, String> map = Map.of(0, "a", null, "b");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed2() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed3() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", null, "c");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed3() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed4() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", null, "d");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed4() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed5() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", null, "e");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed5() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed6() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
null, "f");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed6() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed7() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", null, "g");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed7() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed8() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", null, "h");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed8() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed9() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", null, "i");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed9() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", 8, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowed10() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", 8, "i", null, "j");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowed10() {
|
||||
Map<Integer, String> map = Map.of(0, "a", 1, "b", 2, "c", 3, "d", 4, "e",
|
||||
5, "f", 6, "g", 7, "h", 8, "i", 9, null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullKeyDisallowedN() {
|
||||
Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
|
||||
entries[0] = new AbstractMap.SimpleImmutableEntry(null, "a");
|
||||
Map<Integer, String> map = Map.ofEntries(entries);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullValueDisallowedN() {
|
||||
Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
|
||||
entries[0] = new AbstractMap.SimpleImmutableEntry(0, null);
|
||||
Map<Integer, String> map = Map.ofEntries(entries);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullEntryDisallowedN() {
|
||||
Map.Entry<Integer,String>[] entries = genEntries(MAX_ENTRIES);
|
||||
entries[5] = null;
|
||||
Map<Integer, String> map = Map.ofEntries(entries);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void nullArrayDisallowed() {
|
||||
Map.ofEntries(null);
|
||||
}
|
||||
|
||||
@Test(dataProvider="all")
|
||||
public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) {
|
||||
// assume that act.equals(exp) tested elsewhere
|
||||
Map<Integer, String> copy = serialClone(act);
|
||||
assertEquals(act, copy);
|
||||
assertEquals(copy, exp);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T serialClone(T obj) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(obj);
|
||||
oos.close();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
return (T) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Map.entry() tests
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void entryWithNullKeyDisallowed() {
|
||||
Map.Entry<Integer,String> e = Map.entry(null, "x");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions=NullPointerException.class)
|
||||
public void entryWithNullValueDisallowed() {
|
||||
Map.Entry<Integer,String> e = Map.entry(0, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entryBasicTests() {
|
||||
Map.Entry<String,String> kvh1 = Map.entry("xyzzy", "plugh");
|
||||
Map.Entry<String,String> kvh2 = Map.entry("foobar", "blurfl");
|
||||
Map.Entry<String,String> sie = new AbstractMap.SimpleImmutableEntry("xyzzy", "plugh");
|
||||
|
||||
assertTrue(kvh1.equals(sie));
|
||||
assertTrue(sie.equals(kvh1));
|
||||
assertFalse(kvh2.equals(sie));
|
||||
assertFalse(sie.equals(kvh2));
|
||||
assertEquals(sie.hashCode(), kvh1.hashCode());
|
||||
assertEquals(sie.toString(), kvh1.toString());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2015, 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
|
||||
@ -25,7 +25,10 @@
|
||||
* @test
|
||||
* @bug 6450200
|
||||
* @summary Test proper handling of pool state changes
|
||||
* @library /lib/testlibrary/
|
||||
* @build jdk.testlibrary.RandomFactory
|
||||
* @run main/othervm ConfigChanges
|
||||
* @key randomness intermittent
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
@ -42,11 +45,12 @@ import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import jdk.testlibrary.RandomFactory;
|
||||
|
||||
public class ConfigChanges {
|
||||
static final ThreadGroup tg = new ThreadGroup("pool");
|
||||
|
||||
static final Random rnd = new Random();
|
||||
static final Random rnd = RandomFactory.getRandom();
|
||||
|
||||
static void report(ThreadPoolExecutor tpe) {
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -21,15 +21,20 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
//
|
||||
// SunJSSE does not support dynamic system properties, no way to re-use
|
||||
// system properties in samevm/agentvm mode.
|
||||
//
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6216082
|
||||
* @summary Redirect problem with HttpsURLConnection using a proxy
|
||||
* SunJSSE does not support dynamic system properties, no way to re-use
|
||||
* system properties in samevm/agentvm mode.
|
||||
* @modules java.base/sun.net.www
|
||||
* @library ..
|
||||
* @build HttpCallback TestHttpsServer ClosedChannelList HttpTransaction TunnelProxy
|
||||
* @build HttpCallback TestHttpsServer ClosedChannelList
|
||||
* HttpTransaction TunnelProxy
|
||||
* @key intermittent
|
||||
* @run main/othervm B6216082
|
||||
*/
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 8136410
|
||||
* @summary AlgorithmDecomposer is not parsing padding correctly
|
||||
* @modules java.base/sun.security.util
|
||||
*/
|
||||
|
||||
import sun.security.util.AlgorithmDecomposer;
|
||||
import java.util.Set;
|
||||
|
||||
public class DecomposeAlgorithms {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AlgorithmDecomposer decomposer = new AlgorithmDecomposer();
|
||||
|
||||
check(decomposer, "AES/CBC/NoPadding", new String[] {
|
||||
"AES", "CBC", "NoPadding"});
|
||||
check(decomposer, "DES/CBC/PKCS5Padding", new String[] {
|
||||
"DES", "CBC", "PKCS5Padding"});
|
||||
check(decomposer, "RSA/ECB/OAEPWithSHA-1AndMGF1Padding", new String[] {
|
||||
"RSA", "ECB", "OAEP", "SHA1", "SHA-1", "MGF1Padding"});
|
||||
check(decomposer, "OAEPWithSHA-512AndMGF1Padding", new String[] {
|
||||
"OAEP", "SHA512", "SHA-512", "MGF1Padding"});
|
||||
check(decomposer, "OAEPWithSHA-512AndMGF1Padding", new String[] {
|
||||
"OAEP", "SHA512", "SHA-512", "MGF1Padding"});
|
||||
check(decomposer, "PBEWithSHA1AndRC2_40", new String[] {
|
||||
"PBE", "SHA1", "SHA-1", "RC2_40"});
|
||||
check(decomposer, "PBEWithHmacSHA224AndAES_128", new String[] {
|
||||
"PBE", "HmacSHA224", "AES_128"});
|
||||
}
|
||||
|
||||
private static void check(AlgorithmDecomposer parser,
|
||||
String fullAlgName, String[] components) throws Exception {
|
||||
|
||||
Set<String> parsed = parser.decompose(fullAlgName);
|
||||
if (parsed.size() != components.length) {
|
||||
throw new Exception("Not expected components number: " + parsed);
|
||||
}
|
||||
|
||||
for (String component : components) {
|
||||
if (!parsed.contains(component)) {
|
||||
throw new Exception("Not a expected component: " + component);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("OK: " + fullAlgName);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user