This commit is contained in:
Serguei Spitsyn 2016-05-06 20:36:12 +00:00
commit 55e2b30835
21 changed files with 1168 additions and 333 deletions

View File

@ -1527,12 +1527,9 @@ public final class DateTimeFormatterBuilder {
* ss 2 appendValue(ChronoField.SECOND_OF_MINUTE, 2) * ss 2 appendValue(ChronoField.SECOND_OF_MINUTE, 2)
* *
* S..S 1..n appendFraction(ChronoField.NANO_OF_SECOND, n, n, false) * S..S 1..n appendFraction(ChronoField.NANO_OF_SECOND, n, n, false)
* A 1 appendValue(ChronoField.MILLI_OF_DAY) * A..A 1..n appendValue(ChronoField.MILLI_OF_DAY, n, 19, SignStyle.NOT_NEGATIVE)
* A..A 2..n appendValue(ChronoField.MILLI_OF_DAY, n) * n..n 1..n appendValue(ChronoField.NANO_OF_SECOND, n, 19, SignStyle.NOT_NEGATIVE)
* n 1 appendValue(ChronoField.NANO_OF_SECOND) * N..N 1..n appendValue(ChronoField.NANO_OF_DAY, n, 19, SignStyle.NOT_NEGATIVE)
* n..n 2..n appendValue(ChronoField.NANO_OF_SECOND, n)
* N 1 appendValue(ChronoField.NANO_OF_DAY)
* N..N 2..n appendValue(ChronoField.NANO_OF_DAY, n)
* </pre> * </pre>
* <p> * <p>
* <b>Zone ID</b>: Pattern letters to output {@code ZoneId}. * <b>Zone ID</b>: Pattern letters to output {@code ZoneId}.
@ -1850,6 +1847,11 @@ public final class DateTimeFormatterBuilder {
case 'g': case 'g':
appendValue(field, count, 19, SignStyle.NORMAL); appendValue(field, count, 19, SignStyle.NORMAL);
break; break;
case 'A':
case 'n':
case 'N':
appendValue(field, count, 19, SignStyle.NOT_NEGATIVE);
break;
default: default:
if (count == 1) { if (count == 1) {
appendValue(field); appendValue(field);

View File

@ -0,0 +1,657 @@
/*
* Copyright (c) 2016, 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;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* Container class for immutable collections. Not part of the public API.
* Mainly for namespace management and shared infrastructure.
*
* Serial warnings are suppressed throughout because all implementation
* classes use a serial proxy and thus have no need to declare serialVersionUID.
*/
@SuppressWarnings("serial")
class ImmutableCollections {
/**
* A "salt" value used for randomizing iteration order. This is initialized once
* and stays constant for the lifetime of the JVM. It need not be truly random, but
* it needs to vary sufficiently from one run to the next so that iteration order
* will vary between JVM runs.
*/
static final int SALT;
static {
SALT = new Random().nextInt();
}
/** No instances. */
private ImmutableCollections() { }
/**
* The reciprocal of load factor. Given a number of elements
* to store, multiply by this factor to get the table size.
*/
static final double EXPAND_FACTOR = 2.0;
// ---------- List Implementations ----------
static final class List0<E> extends AbstractList<E> implements RandomAccess, Serializable {
List0() { }
@Override
public int size() {
return 0;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
return null; // but the compiler doesn't know this
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST);
}
}
static final class List1<E> extends AbstractList<E> implements RandomAccess, Serializable {
private final E e0;
List1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 1);
// assert index == 0
return e0;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0);
}
}
static final class List2<E> extends AbstractList<E> implements RandomAccess, Serializable {
private final E e0;
private final E e1;
List2(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
@Override
public int size() {
return 2;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 2);
if (index == 0) {
return e0;
} else { // index == 1
return e1;
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0, e1);
}
}
static final class ListN<E> extends AbstractList<E> implements RandomAccess, Serializable {
private final E[] elements;
@SafeVarargs
ListN(E... input) {
// copy and check manually to avoid TOCTOU
@SuppressWarnings("unchecked")
E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
this.elements = tmp;
}
@Override
public int size() {
return elements.length;
}
@Override
public E get(int index) {
Objects.checkIndex(index, elements.length);
return elements[index];
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, elements);
}
}
// ---------- Set Implementations ----------
static final class Set0<E> extends AbstractSet<E> implements Serializable {
Set0() { }
@Override
public int size() {
return 0;
}
@Override
public boolean contains(Object o) {
return super.contains(Objects.requireNonNull(o));
}
@Override
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET);
}
}
static final class Set1<E> extends AbstractSet<E> implements Serializable {
private final E e0;
Set1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public boolean contains(Object o) {
return super.contains(Objects.requireNonNull(o));
}
@Override
public Iterator<E> iterator() {
return Collections.singletonIterator(e0);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0);
}
}
static final class Set2<E> extends AbstractSet<E> implements Serializable {
private final E e0;
private final E e1;
Set2(E e0, E e1) {
Objects.requireNonNull(e0);
Objects.requireNonNull(e1);
if (e0.equals(e1)) {
throw new IllegalArgumentException("duplicate element: " + e0);
}
if (SALT >= 0) {
this.e0 = e0;
this.e1 = e1;
} else {
this.e0 = e1;
this.e1 = e0;
}
}
@Override
public int size() {
return 2;
}
@Override
public boolean contains(Object o) {
return super.contains(Objects.requireNonNull(o));
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int idx = 0;
@Override
public boolean hasNext() {
return idx < 2;
}
@Override
public E next() {
if (idx == 0) {
idx = 1;
return e0;
} else if (idx == 1) {
idx = 2;
return e1;
} else {
throw new NoSuchElementException();
}
}
};
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0, e1);
}
}
/**
* An array-based Set implementation. The element array must be strictly
* larger than the size (the number of contained elements) so that at
* least one null is always present.
* @param <E> the element type
*/
static final class SetN<E> extends AbstractSet<E> implements Serializable {
private final E[] elements;
private final int size;
@SafeVarargs
@SuppressWarnings("unchecked")
SetN(E... input) {
size = input.length; // implicit nullcheck of input
elements = (E[])new Object[(int)Math.ceil(EXPAND_FACTOR * input.length)];
for (int i = 0; i < input.length; i++) {
E e = Objects.requireNonNull(input[i]);
int idx = probe(e);
if (idx >= 0) {
throw new IllegalArgumentException("duplicate element: " + e);
} else {
elements[-(idx + 1)] = e;
}
}
}
@Override
public int size() {
return size;
}
@Override
public boolean contains(Object o) {
Objects.requireNonNull(o);
return probe(o) >= 0;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int idx = 0;
@Override
public boolean hasNext() {
while (idx < elements.length) {
if (elements[idx] != null)
return true;
idx++;
}
return false;
}
@Override
public E next() {
if (! hasNext()) {
throw new NoSuchElementException();
}
return elements[idx++];
}
};
}
// returns index at which element is present; or if absent,
// (-i - 1) where i is location where element should be inserted
private int probe(Object pe) {
int idx = Math.floorMod(pe.hashCode() ^ SALT, elements.length);
while (true) {
E ee = elements[idx];
if (ee == null) {
return -idx - 1;
} else if (pe.equals(ee)) {
return idx;
} else if (++idx == elements.length) {
idx = 0;
}
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
Object[] array = new Object[size];
int dest = 0;
for (Object o : elements) {
if (o != null) {
array[dest++] = o;
}
}
return new CollSer(CollSer.IMM_SET, array);
}
}
// ---------- Map Implementations ----------
static final class Map0<K,V> extends AbstractMap<K,V> implements Serializable {
Map0() { }
@Override
public Set<Map.Entry<K,V>> entrySet() {
return Set.of();
}
@Override
public boolean containsKey(Object o) {
return super.containsKey(Objects.requireNonNull(o));
}
@Override
public boolean containsValue(Object o) {
return super.containsValue(Objects.requireNonNull(o));
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP);
}
}
static final class Map1<K,V> extends AbstractMap<K,V> implements Serializable {
private final K k0;
private final V v0;
Map1(K k0, V v0) {
this.k0 = Objects.requireNonNull(k0);
this.v0 = Objects.requireNonNull(v0);
}
@Override
public Set<Map.Entry<K,V>> entrySet() {
return Set.of(new KeyValueHolder<>(k0, v0));
}
@Override
public boolean containsKey(Object o) {
return super.containsKey(Objects.requireNonNull(o));
}
@Override
public boolean containsValue(Object o) {
return super.containsValue(Objects.requireNonNull(o));
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP, k0, v0);
}
}
/**
* An array-based Map implementation. There is a single array "table" that
* contains keys and values interleaved: table[0] is kA, table[1] is vA,
* table[2] is kB, table[3] is vB, etc. The table size must be even. It must
* also be strictly larger than the size (the number of key-value pairs contained
* in the map) so that at least one null key is always present.
* @param <K> the key type
* @param <V> the value type
*/
static final class MapN<K,V> extends AbstractMap<K,V> implements Serializable {
private final Object[] table; // pairs of key, value
private final int size; // number of pairs
MapN(Object... input) {
Objects.requireNonNull(input);
if ((input.length & 1) != 0) {
throw new InternalError("length is odd");
}
size = input.length >> 1;
int len = (int)Math.ceil(EXPAND_FACTOR * input.length);
len = (len + 1) & ~1; // ensure table is even length
table = new Object[len];
for (int i = 0; i < input.length; i += 2) {
@SuppressWarnings("unchecked")
K k = Objects.requireNonNull((K)input[i]);
@SuppressWarnings("unchecked")
V v = Objects.requireNonNull((V)input[i+1]);
int idx = probe(k);
if (idx >= 0) {
throw new IllegalArgumentException("duplicate key: " + k);
} else {
int dest = -(idx + 1);
table[dest] = k;
table[dest+1] = v;
}
}
}
@Override
public boolean containsKey(Object o) {
return probe(Objects.requireNonNull(o)) >= 0;
}
@Override
public boolean containsValue(Object o) {
return super.containsValue(Objects.requireNonNull(o));
}
@Override
@SuppressWarnings("unchecked")
public V get(Object o) {
int i = probe(o);
if (i >= 0) {
return (V)table[i+1];
} else {
return null;
}
}
@Override
public int size() {
return size;
}
@Override
public Set<Map.Entry<K,V>> entrySet() {
return new AbstractSet<Map.Entry<K,V>>() {
@Override
public int size() {
return MapN.this.size;
}
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
int idx = 0;
@Override
public boolean hasNext() {
while (idx < table.length) {
if (table[idx] != null)
return true;
idx += 2;
}
return false;
}
@Override
public Map.Entry<K,V> next() {
if (hasNext()) {
@SuppressWarnings("unchecked")
Map.Entry<K,V> e =
new KeyValueHolder<>((K)table[idx], (V)table[idx+1]);
idx += 2;
return e;
} else {
throw new NoSuchElementException();
}
}
};
}
};
}
// returns index at which the probe key is present; or if absent,
// (-i - 1) where i is location where element should be inserted
private int probe(Object pk) {
int idx = Math.floorMod(pk.hashCode() ^ SALT, table.length >> 1) << 1;
while (true) {
@SuppressWarnings("unchecked")
K ek = (K)table[idx];
if (ek == null) {
return -idx - 1;
} else if (pk.equals(ek)) {
return idx;
} else if ((idx += 2) == table.length) {
idx = 0;
}
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
Object[] array = new Object[2 * size];
int len = table.length;
int dest = 0;
for (int i = 0; i < len; i += 2) {
if (table[i] != null) {
array[dest++] = table[i];
array[dest++] = table[i+1];
}
}
return new CollSer(CollSer.IMM_MAP, array);
}
}
}
// ---------- Serialization Proxy ----------
/**
* Serialization proxy class for immutable collections.
*/
final class CollSer implements Serializable {
private static final long serialVersionUID = 6309168927139932177L;
static final int IMM_LIST = 1;
static final int IMM_SET = 2;
static final int IMM_MAP = 3;
private final int flags;
private final Object[] array;
CollSer(int f, Object... a) {
flags = f;
array = a;
}
private Object readResolve() throws ObjectStreamException {
try {
if (array == null) {
throw new InvalidObjectException("null array");
}
// use low order 8 bits to indicate "kind"
// ignore high order bits
switch (flags & 0xff) {
case IMM_LIST:
return List.of(array);
case IMM_SET:
return Set.of(array);
case IMM_MAP:
if (array.length == 0) {
return new ImmutableCollections.Map0<>();
} else if (array.length == 2) {
return new ImmutableCollections.Map1<>(array[0], array[1]);
} else {
return new ImmutableCollections.MapN<>(array);
}
default:
throw new InvalidObjectException(String.format("invalid flags 0x%x", flags));
}
} catch (NullPointerException|IllegalArgumentException ex) {
InvalidObjectException ioe = new InvalidObjectException("invalid object");
ioe.initCause(ex);
throw ioe;
}
}
}

View File

@ -765,7 +765,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of() { static <E> List<E> of() {
return Collections.emptyList(); return new ImmutableCollections.List0<>();
} }
/** /**
@ -781,7 +781,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1) { static <E> List<E> of(E e1) {
return Collections.singletonList(Objects.requireNonNull(e1)); return new ImmutableCollections.List1<>(e1);
} }
/** /**
@ -798,9 +798,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2) { static <E> List<E> of(E e1, E e2) {
return Collections.unmodifiableList( return new ImmutableCollections.List2<>(e1, e2);
Arrays.asList(Objects.requireNonNull(e1),
Objects.requireNonNull(e2)));
} }
/** /**
@ -818,10 +816,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3) { static <E> List<E> of(E e1, E e2, E e3) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3);
Arrays.asList(Objects.requireNonNull(e1),
Objects.requireNonNull(e2),
Objects.requireNonNull(e3)));
} }
/** /**
@ -840,11 +835,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3, E e4) { static <E> List<E> of(E e1, E e2, E e3, E e4) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3, e4);
Arrays.asList(Objects.requireNonNull(e1),
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4)));
} }
/** /**
@ -864,12 +855,7 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) { static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5);
Arrays.asList(Objects.requireNonNull(e1),
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4),
Objects.requireNonNull(e5)));
} }
/** /**
@ -890,13 +876,8 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
Arrays.asList(Objects.requireNonNull(e1), e6);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4),
Objects.requireNonNull(e5),
Objects.requireNonNull(e6)));
} }
/** /**
@ -918,14 +899,8 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
Arrays.asList(Objects.requireNonNull(e1), e6, e7);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4),
Objects.requireNonNull(e5),
Objects.requireNonNull(e6),
Objects.requireNonNull(e7)));
} }
/** /**
@ -948,15 +923,8 @@ public interface List<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
return Collections.unmodifiableList( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
Arrays.asList(Objects.requireNonNull(e1), e6, e7, e8);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4),
Objects.requireNonNull(e5),
Objects.requireNonNull(e6),
Objects.requireNonNull(e7),
Objects.requireNonNull(e8)));
} }
/** /**
@ -980,16 +948,8 @@ public interface List<E> extends Collection<E> {
* @since 9 * @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) { 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( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
Arrays.asList(Objects.requireNonNull(e1), e6, e7, e8, e9);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4),
Objects.requireNonNull(e5),
Objects.requireNonNull(e6),
Objects.requireNonNull(e7),
Objects.requireNonNull(e8),
Objects.requireNonNull(e9)));
} }
/** /**
@ -1014,17 +974,8 @@ public interface List<E> extends Collection<E> {
* @since 9 * @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) { 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( return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
Arrays.asList(Objects.requireNonNull(e1), e6, e7, e8, e9, e10);
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)));
} }
/** /**
@ -1055,10 +1006,16 @@ public interface List<E> extends Collection<E> {
@SafeVarargs @SafeVarargs
@SuppressWarnings("varargs") @SuppressWarnings("varargs")
static <E> List<E> of(E... elements) { static <E> List<E> of(E... elements) {
elements = elements.clone(); // throws NPE if es is null Objects.requireNonNull(elements);
for (E e : elements) { switch (elements.length) {
Objects.requireNonNull(e); case 0:
return new ImmutableCollections.List0<>();
case 1:
return new ImmutableCollections.List1<>(elements[0]);
case 2:
return new ImmutableCollections.List2<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
} }
return Collections.unmodifiableList(Arrays.asList(elements));
} }
} }

View File

@ -1282,7 +1282,7 @@ public interface Map<K, V> {
* @since 9 * @since 9
*/ */
static <K, V> Map<K, V> of() { static <K, V> Map<K, V> of() {
return Collections.emptyMap(); return new ImmutableCollections.Map0<>();
} }
/** /**
@ -1299,7 +1299,7 @@ public interface Map<K, V> {
* @since 9 * @since 9
*/ */
static <K, V> Map<K, V> of(K k1, V v1) { static <K, V> Map<K, V> of(K k1, V v1) {
return Collections.singletonMap(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); return new ImmutableCollections.Map1<>(k1, v1);
} }
/** /**
@ -1319,13 +1319,7 @@ public interface Map<K, V> {
* @since 9 * @since 9
*/ */
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) { 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2);
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);
} }
/** /**
@ -1347,14 +1341,7 @@ public interface Map<K, V> {
* @since 9 * @since 9
*/ */
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) { 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3);
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);
} }
/** /**
@ -1378,15 +1365,7 @@ public interface Map<K, V> {
* @since 9 * @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) { 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4);
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);
} }
/** /**
@ -1412,16 +1391,7 @@ public interface Map<K, V> {
* @since 9 * @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) { 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
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);
} }
/** /**
@ -1450,17 +1420,8 @@ public interface Map<K, V> {
*/ */
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, 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 k6, V v6) {
Map<K, V> map = new HashMap<>(9); // specify number of buckets to avoid resizing return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); k6, v6);
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);
} }
/** /**
@ -1491,18 +1452,8 @@ public interface Map<K, V> {
*/ */
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, 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 k6, V v6, K k7, V v7) {
Map<K, V> map = new HashMap<>(10); // specify number of buckets to avoid resizing return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); k6, v6, k7, v7);
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);
} }
/** /**
@ -1535,19 +1486,8 @@ public interface Map<K, V> {
*/ */
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, 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 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); k6, v6, k7, v7, k8, v8);
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);
} }
/** /**
@ -1582,20 +1522,8 @@ public interface Map<K, V> {
*/ */
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, 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 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); k6, v6, k7, v7, k8, v8, k9, v9);
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);
} }
/** /**
@ -1632,21 +1560,8 @@ public interface Map<K, V> {
*/ */
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, 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) { 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 return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5,
map.put(Objects.requireNonNull(k1), Objects.requireNonNull(v1)); k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
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);
} }
/** /**
@ -1683,15 +1598,21 @@ public interface Map<K, V> {
@SafeVarargs @SafeVarargs
@SuppressWarnings("varargs") @SuppressWarnings("varargs")
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) { static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
Map<K, V> map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null Objects.requireNonNull(entries);
for (Entry<? extends K, ? extends V> e : entries) { if (entries.length == 0) {
// next line throws NPE if e is null return new ImmutableCollections.Map0<>();
map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue())); } else if (entries.length == 1) {
return new ImmutableCollections.Map1<>(entries[0].getKey(),
entries[0].getValue());
} else {
Object[] kva = new Object[entries.length << 1];
int a = 0;
for (Entry<? extends K, ? extends V> entry : entries) {
kva[a++] = entry.getKey();
kva[a++] = entry.getValue();
} }
if (map.size() != entries.length) { return new ImmutableCollections.MapN<>(kva);
throw new IllegalArgumentException("duplicate keys");
} }
return Collections.unmodifiableMap(map);
} }
/** /**

View File

@ -444,7 +444,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of() { static <E> Set<E> of() {
return Collections.emptySet(); return new ImmutableCollections.Set0<>();
} }
/** /**
@ -459,7 +459,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1) { static <E> Set<E> of(E e1) {
return Collections.singleton(Objects.requireNonNull(e1)); return new ImmutableCollections.Set1<>(e1);
} }
/** /**
@ -476,12 +476,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2) { static <E> Set<E> of(E e1, E e2) {
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1), return new ImmutableCollections.Set2<>(e1, e2);
Objects.requireNonNull(e2)));
if (set.size() != 2) {
throw new IllegalArgumentException("duplicate elements");
}
return Collections.unmodifiableSet(set);
} }
/** /**
@ -499,13 +494,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3) { static <E> Set<E> of(E e1, E e2, E e3) {
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1), return new ImmutableCollections.SetN<>(e1, e2, e3);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3)));
if (set.size() != 3) {
throw new IllegalArgumentException("duplicate elements");
}
return Collections.unmodifiableSet(set);
} }
/** /**
@ -524,14 +513,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3, E e4) { static <E> Set<E> of(E e1, E e2, E e3, E e4) {
Set<E> set = new HashSet<>(Arrays.asList(Objects.requireNonNull(e1), return new ImmutableCollections.SetN<>(e1, e2, e3, e4);
Objects.requireNonNull(e2),
Objects.requireNonNull(e3),
Objects.requireNonNull(e4)));
if (set.size() != 4) {
throw new IllegalArgumentException("duplicate elements");
}
return Collections.unmodifiableSet(set);
} }
/** /**
@ -551,15 +533,7 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5);
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);
} }
/** /**
@ -580,16 +554,8 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
Objects.requireNonNull(e2), e6);
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);
} }
/** /**
@ -611,17 +577,8 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
Objects.requireNonNull(e2), e6, e7);
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);
} }
/** /**
@ -644,18 +601,8 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
static <E> Set<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
Objects.requireNonNull(e2), e6, e7, e8);
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);
} }
/** /**
@ -679,19 +626,8 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @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) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
Objects.requireNonNull(e2), e6, e7, e8, e9);
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);
} }
/** /**
@ -716,20 +652,8 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @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) { 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), return new ImmutableCollections.SetN<>(e1, e2, e3, e4, e5,
Objects.requireNonNull(e2), e6, e7, e8, e9, e10);
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);
} }
/** /**
@ -759,15 +683,18 @@ public interface Set<E> extends Collection<E> {
* @since 9 * @since 9
*/ */
@SafeVarargs @SafeVarargs
static <E> Set<E> of(E... elements) {
for (E e : elements) { // throws NPE if es is null
Objects.requireNonNull(e);
}
@SuppressWarnings("varargs") @SuppressWarnings("varargs")
Set<E> set = new HashSet<>(Arrays.asList(elements)); static <E> Set<E> of(E... elements) {
if (set.size() != elements.length) { Objects.requireNonNull(elements);
throw new IllegalArgumentException("duplicate elements"); switch (elements.length) {
case 0:
return new ImmutableCollections.Set0<>();
case 1:
return new ImmutableCollections.Set1<>(elements[0]);
case 2:
return new ImmutableCollections.Set2<>(elements[0], elements[1]);
default:
return new ImmutableCollections.SetN<>(elements);
} }
return Collections.unmodifiableSet(set);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -191,4 +191,11 @@ typedef jubyte FourByteAbgrDataType;
COMP_PREFIX ## A, COMP_PREFIX ## R, \ COMP_PREFIX ## A, COMP_PREFIX ## R, \
COMP_PREFIX ## G, COMP_PREFIX ## B) COMP_PREFIX ## G, COMP_PREFIX ## B)
/*
* SrcOver ## TYPE ## BlendFactor
* Returns appropriate blend value for use in blending calculations.
*/
#define SrcOverFourByteAbgrBlendFactor(dF, dA) \
(dA)
#endif /* FourByteAbgr_h_Included */ #endif /* FourByteAbgr_h_Included */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -217,4 +217,11 @@ typedef jubyte FourByteAbgrPreDataType;
(pRas)[4*(x)+3] = (jubyte) COMP_PREFIX ## R; \ (pRas)[4*(x)+3] = (jubyte) COMP_PREFIX ## R; \
} while (0) } while (0)
/*
* SrcOver ## TYPE ## BlendFactor
* Returns appropriate blend value for use in blending calculations.
*/
#define SrcOverFourByteAbgrPreBlendFactor(dF, dA) \
(dF)
#endif /* FourByteAbgrPre_h_Included */ #endif /* FourByteAbgrPre_h_Included */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -208,4 +208,11 @@ typedef jint IntArgbDataType;
COMP_PREFIX ## A = (COMP_PREFIX ## A << 8) + COMP_PREFIX ## A; \ COMP_PREFIX ## A = (COMP_PREFIX ## A << 8) + COMP_PREFIX ## A; \
} while (0) } while (0)
/*
* SrcOver ## TYPE ## BlendFactor
* Returns appropriate blend value for use in blending calculations.
*/
#define SrcOverIntArgbBlendFactor(dF, dA) \
(dA)
#endif /* IntArgb_h_Included */ #endif /* IntArgb_h_Included */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -206,4 +206,11 @@ typedef jint IntArgbBmDataType;
COMP_PREFIX ## A = (COMP_PREFIX ## A << 8) + COMP_PREFIX ## A; \ COMP_PREFIX ## A = (COMP_PREFIX ## A << 8) + COMP_PREFIX ## A; \
} while (0) } while (0)
/*
* SrcOver ## TYPE ## BlendFactor
* Returns appropriate blend value for use in blending calculations.
*/
#define SrcOverIntArgbBmBlendFactor(dF, dA) \
(dA)
#endif /* IntArgbBm_h_Included */ #endif /* IntArgbBm_h_Included */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -216,4 +216,11 @@ typedef jint IntArgbPreDataType;
COMP_PREFIX ## G, \ COMP_PREFIX ## G, \
COMP_PREFIX ## B) COMP_PREFIX ## B)
/*
* SrcOver ## TYPE ## BlendFactor
* Returns appropriate blend value for use in blending calculations.
*/
#define SrcOverIntArgbPreBlendFactor(dF, dA) \
(dF)
#endif /* IntArgbPre_h_Included */ #endif /* IntArgbPre_h_Included */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1668,31 +1668,83 @@ void NAME_SOLID_DRAWGLYPHLIST(DST)(SurfaceDataRasInfo *pRasInfo, \
} \ } \
} while (0); } while (0);
/*
* Antialiased glyph drawing results in artifacts around the character edges
* when text is drawn ontop of translucent background color. The standard
* blending equation for two colors:
* destColor = srcColor * glyphAlpha + destColor * (1 - glyphAlpha)
* works only when srcColor and destColor are opaque. For translucent srcColor
* and destColor, the respective alpha components in each color will influence
* the visibility of the color and the visibility of the color below it. Hence
* the equation for blending is given as:
* resA = srcAlpha + dstAlpha * (1 - srcAlpha)
* resCol = (srcColor * srcAlpha + destColor * destAlpha * (1- srcAlpha))/resA
* In addition, srcAlpha is multiplied with the glyphAlpha- that indicates the
* grayscale mask value of the glyph being drawn. The combined result provides
* smooth antialiased text on the buffer without any artifacts. Since the
* logic is executed for every pixel in a glyph, the implementation is further
* optimized to reduce computation and improve execution time.
*/
#define GlyphListAABlend4ByteArgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \ #define GlyphListAABlend4ByteArgb(DST, GLYPH_PIXELS, PIXEL_INDEX, DST_PTR, \
FG_PIXEL, PREFIX, SRC_PREFIX) \ FG_PIXEL, PREFIX, SRC_PREFIX) \
do { \ do { \
DeclareAlphaVarFor4ByteArgb(dstA) \ DeclareAlphaVarFor4ByteArgb(resA) \
DeclareCompVarsFor4ByteArgb(dst) \ DeclareCompVarsFor4ByteArgb(res) \
jint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \ jint mixValSrc = GLYPH_PIXELS[PIXEL_INDEX]; \
if (mixValSrc) { \ if (mixValSrc) { \
if (mixValSrc < 255) { \ if (mixValSrc != 0xff) { \
jint mixValDst = 255 - mixValSrc; \ PromoteByteAlphaFor4ByteArgb(mixValSrc); \
resA = MultiplyAlphaFor4ByteArgb(mixValSrc, SRC_PREFIX ## A); \
} else { \
resA = SRC_PREFIX ## A; \
} \
if (resA != MaxValFor4ByteArgb) { \
DeclareAndInvertAlphaVarFor4ByteArgb(dstF, resA) \
DeclareAndClearAlphaVarFor4ByteArgb(dstA) \
DeclareCompVarsFor4ByteArgb(dst) \
DeclareCompVarsFor4ByteArgb(tmp) \
MultiplyAndStore4ByteArgbComps(res, resA, SRC_PREFIX); \
if (!(DST ## IsPremultiplied)) { \
Load ## DST ## To4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \ Load ## DST ## To4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \
dstA, dstR, dstG, dstB); \ dstA, dstR, dstG, dstB); \
dstA = MUL8(dstA, mixValDst) + \ Store4ByteArgbCompsUsingOp(tmp, =, dst); \
MUL8(SRC_PREFIX ## A, mixValSrc); \ } else { \
MultMultAddAndStore4ByteArgbComps(dst, mixValDst, dst, \ Declare ## DST ## AlphaLoadData(DstPix) \
mixValSrc, SRC_PREFIX); \ jint pixelOffset = PIXEL_INDEX * (DST ## PixelStride); \
if (!(DST ## IsOpaque) && \ DST ## DataType *pixelAddress = PtrAddBytes(DST_PTR, \
!(DST ## IsPremultiplied) && dstA && dstA < 255) { \ pixelOffset); \
DivideAndStore4ByteArgbComps(dst, dst, dstA); \ LoadAlphaFrom ## DST ## For4ByteArgb(pixelAddress, \
DstPix, \
dst); \
Postload4ByteArgbFrom ## DST(pixelAddress, \
DstPix, \
tmp); \
} \
if (dstA) { \
DeclareAlphaVarFor4ByteArgb(blendF) \
dstA = MultiplyAlphaFor4ByteArgb(dstF, dstA); \
resA += dstA; \
blendF = SrcOver ## DST ## BlendFactor(dstF, dstA); \
if (blendF != MaxValFor4ByteArgb) { \
MultiplyAndStore4ByteArgbComps(tmp, \
blendF, \
tmp); \
} \
Store4ByteArgbCompsUsingOp(res, +=, tmp); \
} \ } \
Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
PIXEL_INDEX, dst); \
} else { \ } else { \
Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \ Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \
FG_PIXEL, PREFIX); \ FG_PIXEL, PREFIX); \
break; \
} \ } \
if (!(DST ## IsOpaque) && \
!(DST ## IsPremultiplied) && resA && \
resA < MaxValFor4ByteArgb) \
{ \
DivideAndStore4ByteArgbComps(res, res, resA); \
} \
Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \
PIXEL_INDEX, res); \
} \ } \
} while (0); } while (0);

View File

@ -144,13 +144,9 @@ public class AsyncSSLDelegate implements Closeable, AsyncConnection {
sslParameters = Utils.copySSLParameters(sslp); sslParameters = Utils.copySSLParameters(sslp);
if (alpn != null) { if (alpn != null) {
sslParameters.setApplicationProtocols(alpn); sslParameters.setApplicationProtocols(alpn);
Log.logSSL("Setting application protocols: " + Arrays.toString(alpn));
} else {
Log.logSSL("No application protocols proposed");
} }
logParams(sslParameters);
engine.setSSLParameters(sslParameters); engine.setSSLParameters(sslParameters);
engine.setEnabledCipherSuites(sslp.getCipherSuites());
engine.setEnabledProtocols(sslp.getProtocols());
this.lowerOutput = lowerOutput; this.lowerOutput = lowerOutput;
this.client = client; this.client = client;
this.channelInputQ = new Queue<>(); this.channelInputQ = new Queue<>();
@ -560,24 +556,26 @@ public class AsyncSSLDelegate implements Closeable, AsyncConnection {
return sslParameters; return sslParameters;
} }
static void printParams(SSLParameters p) { static void logParams(SSLParameters p) {
System.out.println("SSLParameters:"); if (!Log.ssl())
return;
Log.logSSL("SSLParameters:");
if (p == null) { if (p == null) {
System.out.println("Null params"); Log.logSSL("Null params");
return; return;
} }
for (String cipher : p.getCipherSuites()) { for (String cipher : p.getCipherSuites()) {
System.out.printf("cipher: %s\n", cipher); Log.logSSL("cipher: {0}\n", cipher);
} }
for (String approto : p.getApplicationProtocols()) { for (String approto : p.getApplicationProtocols()) {
System.out.printf("application protocol: %s\n", approto); Log.logSSL("application protocol: {0}\n", approto);
} }
for (String protocol : p.getProtocols()) { for (String protocol : p.getProtocols()) {
System.out.printf("protocol: %s\n", protocol); Log.logSSL("protocol: {0}\n", protocol);
} }
if (p.getServerNames() != null) if (p.getServerNames() != null)
for (SNIServerName sname : p.getServerNames()) { for (SNIServerName sname : p.getServerNames()) {
System.out.printf("server name: %s\n", sname.toString()); Log.logSSL("server name: {0}\n", sname.toString());
} }
} }

View File

@ -110,6 +110,9 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
this.proxySelector = builder.proxy; this.proxySelector = builder.proxy;
authenticator = builder.authenticator; authenticator = builder.authenticator;
version = builder.version; version = builder.version;
if (builder.sslParams == null)
sslParams = getDefaultParams(sslContext);
else
sslParams = builder.sslParams; sslParams = builder.sslParams;
connections = new ConnectionPool(); connections = new ConnectionPool();
connections.start(); connections.start();
@ -129,6 +132,12 @@ class HttpClientImpl extends HttpClient implements BufferHandler {
selmgr.start(); selmgr.start();
} }
private static SSLParameters getDefaultParams(SSLContext ctx) {
SSLParameters params = ctx.getSupportedSSLParameters();
params.setProtocols(new String[]{"TLSv1.2"});
return params;
}
/** /**
* Wait for activity on given exchange (assuming blocking = false). * Wait for activity on given exchange (assuming blocking = false).
* It's a no-op if blocking = true. In particular, the following occurs * It's a no-op if blocking = true. In particular, the following occurs

View File

@ -66,8 +66,6 @@ class SSLDelegate {
Log.logSSL("No application protocols proposed"); Log.logSSL("No application protocols proposed");
} }
engine.setSSLParameters(sslParameters); engine.setSSLParameters(sslParameters);
engine.setEnabledCipherSuites(sslp.getCipherSuites());
engine.setEnabledProtocols(sslp.getProtocols());
wrapper = new EngineWrapper(chan, engine); wrapper = new EngineWrapper(chan, engine);
this.chan = chan; this.chan = chan;
this.client = client; this.client = client;

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2016, 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 8015070
* @summary Tests for artifacts around the edges of anti-aliased text
* drawn over translucent background color.
*/
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class AntialiasedTextArtifact {
/* Image dimensions */
private static final int TEST_IMAGE_WIDTH = 2800;
private static final int TEST_IMAGE_HEIGHT = 100;
private static final String TEST_STRING =
"The quick brown fox jumps over the lazy dog. 0123456789.";
/*
* The artifacts appear when text is drawn ontop of translucent
* background. In other words, a background with alpha channel.
* Hence we test the algorithm for image types that contain either
* straight alpha channel or pre-multiplied alpha channel. In
* addition we test the images with other common pixel formats.
*/
private static final int[] TYPES = {BufferedImage.TYPE_INT_ARGB,
BufferedImage.TYPE_INT_ARGB_PRE,
BufferedImage.TYPE_4BYTE_ABGR,
BufferedImage.TYPE_4BYTE_ABGR_PRE,
BufferedImage.TYPE_INT_RGB,
BufferedImage.TYPE_INT_BGR,
BufferedImage.TYPE_3BYTE_BGR};
public static void main(String[] args) throws IOException {
/* Iterate over different image types */
for (int type : TYPES) {
BufferedImage testImg = getBufferedImage(type);
/* Draw anti-aliased string and check for artifacts */
drawAntialiasedString(testImg);
checkArtifact(testImg);
}
}
private static BufferedImage getBufferedImage(int imageType) {
/* Create a Graphics2D object from the given image type */
BufferedImage image = new BufferedImage(TEST_IMAGE_WIDTH,
TEST_IMAGE_HEIGHT,
imageType);
return image;
}
private static void drawAntialiasedString(BufferedImage image) {
/* Create Graphics2D object */
Graphics2D graphics = (Graphics2D) image.getGraphics();
/* Fill the image with translucent color */
graphics.setColor(new Color(127, 127, 127, 127));
graphics.fillRect(0, 0, TEST_IMAGE_WIDTH, TEST_IMAGE_HEIGHT);
/* Drawstring with Antialiasing hint */
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
Font font = new Font("Verdana" , Font.PLAIN, 60);
graphics.setFont(font);
graphics.setColor(new Color(255, 0, 0));
graphics.drawString(TEST_STRING, 10, 75);
graphics.dispose();
}
private static void checkArtifact(BufferedImage image) throws IOException {
int componentMask = 0xff;
int colorThreshold = 200;
int rowIndex = 0;
int colIndex = 0;
/* Loop through every pixel to check for possible artifact */
for (rowIndex = 0; rowIndex < image.getHeight(); rowIndex++) {
for (colIndex = 0; colIndex < image.getWidth(); colIndex++) {
/*
* API: getRGB(x,y) returns color in INT_ARGB color space.
* Extract individual color components with a simple mask.
*/
int colorValue = image.getRGB(colIndex, rowIndex);
int colorComponent1 = colorValue & componentMask;
int colorComponent2 = (colorValue>>8) & componentMask;
int colorComponent3 = (colorValue>>16) & componentMask;
/*
* Artifacts are predominantly a subjective decision based on
* the quality of the rendered image content. However, in the
* current use-case, the artifacts around the edges of the anti
* aliased text appear like spots of white pixels without any
* relation to the color of foreground text or the background
* translucent shape.
*
* To identify the artifact pixels, each color component from
* the testImage is compared with a constant threshold. The
* component threshold has been set based on observation from
* different experiments on mulitple Java versions.
*/
if (colorComponent1 >= colorThreshold
&& colorComponent2 >= colorThreshold
&& colorComponent3 >= colorThreshold) {
/* Artifact has been noticed. Report error. */
throw new RuntimeException("Test Failed.");
}
}
}
}
}

View File

@ -98,6 +98,7 @@ public class BasicTest {
simpleTest(true); simpleTest(true);
streamTest(false); streamTest(false);
streamTest(true); streamTest(true);
paramsTest();
Thread.sleep(1000 * 4); Thread.sleep(1000 * 4);
} finally { } finally {
httpServer.stop(); httpServer.stop();
@ -180,6 +181,30 @@ public class BasicTest {
System.err.println("DONE"); System.err.println("DONE");
} }
static void paramsTest() throws Exception {
Http2TestServer server = new Http2TestServer(true, 0, (t -> {
SSLSession s = t.getSSLSession();
String prot = s.getProtocol();
if (prot.equals("TLSv1.2")) {
t.sendResponseHeaders(200, -1);
} else {
System.err.printf("Protocols =%s\n", prot);
t.sendResponseHeaders(500, -1);
}
}), exec, sslContext);
server.start();
int port = server.getAddress().getPort();
URI u = new URI("https://127.0.0.1:"+port+"/foo");
HttpClient client = getClient();
HttpRequest req = client.request(u)
.GET();
HttpResponse resp = req.response();
int stat = resp.statusCode();
if (stat != 200) {
throw new RuntimeException("paramsTest failed "
+ Integer.toString(stat));
}
}
static void simpleTest(boolean secure) throws Exception { static void simpleTest(boolean secure) throws Exception {
URI uri = getURI(secure); URI uri = getURI(secure);

View File

@ -5,6 +5,7 @@ import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import javax.net.ssl.SSLSession;
public class Http2TestExchange { public class Http2TestExchange {
@ -14,6 +15,7 @@ public class Http2TestExchange {
final String method; final String method;
final InputStream is; final InputStream is;
final BodyOutputStream os; final BodyOutputStream os;
final SSLSession sslSession;
final int streamid; final int streamid;
final boolean pushAllowed; final boolean pushAllowed;
final Http2TestServerConnection conn; final Http2TestServerConnection conn;
@ -24,6 +26,7 @@ public class Http2TestExchange {
Http2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders, Http2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
HttpHeadersImpl rspheaders, URI uri, InputStream is, HttpHeadersImpl rspheaders, URI uri, InputStream is,
SSLSession sslSession,
BodyOutputStream os, Http2TestServerConnection conn, boolean pushAllowed) { BodyOutputStream os, Http2TestServerConnection conn, boolean pushAllowed) {
this.reqheaders = reqheaders; this.reqheaders = reqheaders;
this.rspheaders = rspheaders; this.rspheaders = rspheaders;
@ -32,6 +35,7 @@ public class Http2TestExchange {
this.is = is; this.is = is;
this.streamid = streamid; this.streamid = streamid;
this.os = os; this.os = os;
this.sslSession = sslSession;
this.pushAllowed = pushAllowed; this.pushAllowed = pushAllowed;
this.conn = conn; this.conn = conn;
this.server = conn.server; this.server = conn.server;
@ -53,6 +57,10 @@ public class Http2TestExchange {
return method; return method;
} }
public SSLSession getSSLSession() {
return sslSession;
}
public void close() { public void close() {
try { try {
is.close(); is.close();

View File

@ -31,6 +31,8 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.net.URI; import java.net.URI;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE; import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -355,7 +357,8 @@ public class Http2TestServerConnection {
URI uri = new URI(us); URI uri = new URI(us);
boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1; boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
Http2TestExchange exchange = new Http2TestExchange(streamid, method, Http2TestExchange exchange = new Http2TestExchange(streamid, method,
headers, rspheaders, uri, bis, bos, this, pushAllowed); headers, rspheaders, uri, bis, getSSLSession(),
bos, this, pushAllowed);
// give to user // give to user
handler.handle(exchange); handler.handle(exchange);
@ -368,6 +371,12 @@ public class Http2TestServerConnection {
} }
} }
private SSLSession getSSLSession() {
if (! (socket instanceof SSLSocket))
return null;
SSLSocket ssl = (SSLSocket)socket;
return ssl.getSession();
}
// Runs in own thread // Runs in own thread
@SuppressWarnings({"rawtypes","unchecked"}) @SuppressWarnings({"rawtypes","unchecked"})

View File

@ -72,6 +72,7 @@ import static org.testng.Assert.assertEquals;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth; import java.time.YearMonth;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -794,6 +795,54 @@ public class TCKDateTimeFormatterBuilder {
assertEquals(LocalDate.of(y, m, d).format(df), expected); assertEquals(LocalDate.of(y, m, d).format(df), expected);
} }
//-----------------------------------------------------------------------
@DataProvider(name="secondsPattern")
Object[][] data_secondsPattern() {
return new Object[][] {
{"A", "1", LocalTime.ofNanoOfDay(1_000_000)},
{"A", "100000", LocalTime.ofSecondOfDay(100)},
{"AA", "01", LocalTime.ofNanoOfDay(1_000_000)},
{"AA", "100000", LocalTime.ofSecondOfDay(100)},
{"AAAAAA", "100000", LocalTime.ofSecondOfDay(100)},
{"HHmmssn", "0000001", LocalTime.ofNanoOfDay(1)},
{"HHmmssn", "000000111", LocalTime.ofNanoOfDay(111)},
{"HHmmssnn", "00000001", LocalTime.ofNanoOfDay(1)},
{"HHmmssnn", "0000001111", LocalTime.ofNanoOfDay(1111)},
{"HHmmssnnnnnn", "000000111111", LocalTime.ofNanoOfDay(111_111)},
{"N", "1", LocalTime.ofNanoOfDay(1)},
{"N", "100000", LocalTime.ofNanoOfDay(100_000)},
{"NN", "01", LocalTime.ofNanoOfDay(1)},
{"NN", "100000", LocalTime.ofNanoOfDay(100_000)},
{"NNNNNN", "100000", LocalTime.ofNanoOfDay(100_000)},
};
}
@Test(dataProvider="secondsPattern")
public void test_secondsPattern(String pattern, String input, LocalTime expected) throws Exception {
DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
assertEquals(LocalTime.parse(input, df), expected);
}
@DataProvider(name="secondsValues")
Object[][] data_secondsValues() {
return new Object[][] {
{"A", 1, "1000"},
{"n", 1, "0"},
{"N", 1, "1000000000"},
};
}
@Test(dataProvider="secondsValues")
public void test_secondsValues(String pattern, int seconds , String expected) throws Exception {
DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
assertEquals(LocalTime.ofSecondOfDay(seconds).format(df), expected);
}
@Test(expectedExceptions = DateTimeParseException.class)
public void test_secondsPatternInvalidAdacentValueParsingPattern() {
// patterns A*, N*, n* will not take part in adjacent value parsing
DateTimeFormatter.ofPattern("yyyyAA").parse("201610");
}
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@Test @Test

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -746,17 +746,17 @@ public class TestDateTimeFormatterBuilder {
{"SSS", "Fraction(NanoOfSecond,3,3)"}, {"SSS", "Fraction(NanoOfSecond,3,3)"},
{"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"}, {"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"},
{"A", "Value(MilliOfDay)"}, {"A", "Value(MilliOfDay,1,19,NOT_NEGATIVE)"},
{"AA", "Value(MilliOfDay,2)"}, {"AA", "Value(MilliOfDay,2,19,NOT_NEGATIVE)"},
{"AAA", "Value(MilliOfDay,3)"}, {"AAA", "Value(MilliOfDay,3,19,NOT_NEGATIVE)"},
{"n", "Value(NanoOfSecond)"}, {"n", "Value(NanoOfSecond,1,19,NOT_NEGATIVE)"},
{"nn", "Value(NanoOfSecond,2)"}, {"nn", "Value(NanoOfSecond,2,19,NOT_NEGATIVE)"},
{"nnn", "Value(NanoOfSecond,3)"}, {"nnn", "Value(NanoOfSecond,3,19,NOT_NEGATIVE)"},
{"N", "Value(NanoOfDay)"}, {"N", "Value(NanoOfDay,1,19,NOT_NEGATIVE)"},
{"NN", "Value(NanoOfDay,2)"}, {"NN", "Value(NanoOfDay,2,19,NOT_NEGATIVE)"},
{"NNN", "Value(NanoOfDay,3)"}, {"NNN", "Value(NanoOfDay,3,19,NOT_NEGATIVE)"},
{"z", "ZoneText(SHORT)"}, {"z", "ZoneText(SHORT)"},
{"zz", "ZoneText(SHORT)"}, {"zz", "ZoneText(SHORT)"},

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, 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 8139233
* @summary ensure entry set's iterator doesn't have side effects on the entry set
* @run testng EntrySetIterator
*/
import java.util.*;
import org.testng.annotations.Test;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertEquals;
public class EntrySetIterator {
@Test
public void main() {
Map<String, String> map = Map.of("a", "1", "b", "2", "c", "3");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
assertTrue(iterator.hasNext());
// copying implicitly iterates an iterator
Set<Map.Entry<String, String>> copy1 = new HashSet<>(entrySet);
Set<Map.Entry<String, String>> copy2 = new HashSet<>(entrySet);
assertEquals(copy2, copy1);
assertTrue(iterator.hasNext());
}
}