mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 12:34:32 +02:00
Merge
This commit is contained in:
commit
df35adf83b
38 changed files with 2350 additions and 565 deletions
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code Integer} class wraps a value of the primitive type
|
* The {@code Integer} class wraps a value of the primitive type
|
||||||
* {@code int} in an object. An object of type {@code Integer}
|
* {@code int} in an object. An object of type {@code Integer}
|
||||||
|
@ -442,6 +444,12 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
public static int parseInt(String s, int radix)
|
public static int parseInt(String s, int radix)
|
||||||
throws NumberFormatException
|
throws NumberFormatException
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* WARNING: This method may be invoked early during VM initialization
|
||||||
|
* before IntegerCache is initialized. Care must be taken to not use
|
||||||
|
* the valueOf method.
|
||||||
|
*/
|
||||||
|
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
throw new NumberFormatException("null");
|
throw new NumberFormatException("null");
|
||||||
}
|
}
|
||||||
|
@ -545,7 +553,7 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
* does not contain a parsable {@code int}.
|
* does not contain a parsable {@code int}.
|
||||||
*/
|
*/
|
||||||
public static Integer valueOf(String s, int radix) throws NumberFormatException {
|
public static Integer valueOf(String s, int radix) throws NumberFormatException {
|
||||||
return new Integer(parseInt(s,radix));
|
return Integer.valueOf(parseInt(s,radix));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -570,20 +578,56 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
* @exception NumberFormatException if the string cannot be parsed
|
* @exception NumberFormatException if the string cannot be parsed
|
||||||
* as an integer.
|
* as an integer.
|
||||||
*/
|
*/
|
||||||
public static Integer valueOf(String s) throws NumberFormatException
|
public static Integer valueOf(String s) throws NumberFormatException {
|
||||||
{
|
return Integer.valueOf(parseInt(s, 10));
|
||||||
return new Integer(parseInt(s, 10));
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache to support the object identity semantics of autoboxing for values between
|
||||||
|
* -128 and 127 (inclusive) as required by JLS.
|
||||||
|
*
|
||||||
|
* The cache is initialized on first usage. During VM initialization the
|
||||||
|
* getAndRemoveCacheProperties method may be used to get and remove any system
|
||||||
|
* properites that configure the cache size. At this time, the size of the
|
||||||
|
* cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
|
||||||
|
private static String integerCacheHighPropValue;
|
||||||
|
|
||||||
|
static void getAndRemoveCacheProperties() {
|
||||||
|
if (!sun.misc.VM.isBooted()) {
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
integerCacheHighPropValue =
|
||||||
|
(String)props.remove("java.lang.Integer.IntegerCache.high");
|
||||||
|
if (integerCacheHighPropValue != null)
|
||||||
|
System.setProperties(props); // remove from system props
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class IntegerCache {
|
private static class IntegerCache {
|
||||||
private IntegerCache(){}
|
static final int low = -128;
|
||||||
|
static final int high;
|
||||||
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
|
static final Integer cache[];
|
||||||
|
|
||||||
static {
|
static {
|
||||||
for(int i = 0; i < cache.length; i++)
|
// high value may be configured by property
|
||||||
cache[i] = new Integer(i - 128);
|
int h = 127;
|
||||||
|
if (integerCacheHighPropValue != null) {
|
||||||
|
int i = parseInt(integerCacheHighPropValue);
|
||||||
|
i = Math.max(i, 127);
|
||||||
|
// Maximum array size is Integer.MAX_VALUE
|
||||||
|
h = Math.min(i, Integer.MAX_VALUE - (-low));
|
||||||
|
}
|
||||||
|
high = h;
|
||||||
|
|
||||||
|
cache = new Integer[(high - low) + 1];
|
||||||
|
int j = low;
|
||||||
|
for(int k = 0; k < cache.length; k++)
|
||||||
|
cache[k] = new Integer(j++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IntegerCache() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -599,10 +643,9 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
* @since 1.5
|
* @since 1.5
|
||||||
*/
|
*/
|
||||||
public static Integer valueOf(int i) {
|
public static Integer valueOf(int i) {
|
||||||
final int offset = 128;
|
assert IntegerCache.high >= 127;
|
||||||
if (i >= -128 && i <= 127) { // must cache
|
if (i >= IntegerCache.low && i <= IntegerCache.high)
|
||||||
return IntegerCache.cache[i + offset];
|
return IntegerCache.cache[i + (-IntegerCache.low)];
|
||||||
}
|
|
||||||
return new Integer(i);
|
return new Integer(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,7 +849,7 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
*/
|
*/
|
||||||
public static Integer getInteger(String nm, int val) {
|
public static Integer getInteger(String nm, int val) {
|
||||||
Integer result = getInteger(nm, null);
|
Integer result = getInteger(nm, null);
|
||||||
return (result == null) ? new Integer(val) : result;
|
return (result == null) ? Integer.valueOf(val) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -938,7 +981,7 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = Integer.valueOf(nm.substring(index), radix);
|
result = Integer.valueOf(nm.substring(index), radix);
|
||||||
result = negative ? new Integer(-result.intValue()) : result;
|
result = negative ? Integer.valueOf(-result.intValue()) : result;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// If number is Integer.MIN_VALUE, we'll end up here. The next line
|
// If number is Integer.MIN_VALUE, we'll end up here. The next line
|
||||||
// handles this case, and causes any genuine format error to be
|
// handles this case, and causes any genuine format error to be
|
||||||
|
|
|
@ -510,7 +510,7 @@ public final class Long extends Number implements Comparable<Long> {
|
||||||
* contain a parsable {@code long}.
|
* contain a parsable {@code long}.
|
||||||
*/
|
*/
|
||||||
public static Long valueOf(String s, int radix) throws NumberFormatException {
|
public static Long valueOf(String s, int radix) throws NumberFormatException {
|
||||||
return new Long(parseLong(s, radix));
|
return Long.valueOf(parseLong(s, radix));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,7 +537,7 @@ public final class Long extends Number implements Comparable<Long> {
|
||||||
*/
|
*/
|
||||||
public static Long valueOf(String s) throws NumberFormatException
|
public static Long valueOf(String s) throws NumberFormatException
|
||||||
{
|
{
|
||||||
return new Long(parseLong(s, 10));
|
return Long.valueOf(parseLong(s, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LongCache {
|
private static class LongCache {
|
||||||
|
@ -650,7 +650,7 @@ public final class Long extends Number implements Comparable<Long> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = Long.valueOf(nm.substring(index), radix);
|
result = Long.valueOf(nm.substring(index), radix);
|
||||||
result = negative ? new Long(-result.longValue()) : result;
|
result = negative ? Long.valueOf(-result.longValue()) : result;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// If number is Long.MIN_VALUE, we'll end up here. The next line
|
// If number is Long.MIN_VALUE, we'll end up here. The next line
|
||||||
// handles this case, and causes any genuine format error to be
|
// handles this case, and causes any genuine format error to be
|
||||||
|
@ -869,7 +869,7 @@ public final class Long extends Number implements Comparable<Long> {
|
||||||
*/
|
*/
|
||||||
public static Long getLong(String nm, long val) {
|
public static Long getLong(String nm, long val) {
|
||||||
Long result = Long.getLong(nm, null);
|
Long result = Long.getLong(nm, null);
|
||||||
return (result == null) ? new Long(val) : result;
|
return (result == null) ? Long.valueOf(val) : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1105,6 +1105,13 @@ public final class System {
|
||||||
props = new Properties();
|
props = new Properties();
|
||||||
initProperties(props);
|
initProperties(props);
|
||||||
sun.misc.Version.init();
|
sun.misc.Version.init();
|
||||||
|
|
||||||
|
// Gets and removes system properties that configure the Integer
|
||||||
|
// cache used to support the object identity semantics of autoboxing.
|
||||||
|
// At this time, the size of the cache may be controlled by the
|
||||||
|
// -XX:AutoBoxCacheMax=<size> option.
|
||||||
|
Integer.getAndRemoveCacheProperties();
|
||||||
|
|
||||||
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
|
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
|
||||||
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
|
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
|
||||||
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
|
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
|
||||||
|
|
|
@ -261,7 +261,10 @@ public abstract class DatagramChannel
|
||||||
*
|
*
|
||||||
* <p> This method may be invoked at any time. It will not have any effect
|
* <p> This method may be invoked at any time. It will not have any effect
|
||||||
* on read or write operations that are already in progress at the moment
|
* on read or write operations that are already in progress at the moment
|
||||||
* that it is invoked. </p>
|
* that it is invoked. If this channel's socket is not bound then this method
|
||||||
|
* will first cause the socket to be bound to an address that is assigned
|
||||||
|
* automatically, as if invoking the {@link #bind bind} method with a
|
||||||
|
* parameter of {@code null}. </p>
|
||||||
*
|
*
|
||||||
* @param remote
|
* @param remote
|
||||||
* The remote address to which this channel is to be connected
|
* The remote address to which this channel is to be connected
|
||||||
|
@ -356,7 +359,10 @@ public abstract class DatagramChannel
|
||||||
* <p> This method may be invoked at any time. If another thread has
|
* <p> This method may be invoked at any time. If another thread has
|
||||||
* already initiated a read operation upon this channel, however, then an
|
* already initiated a read operation upon this channel, however, then an
|
||||||
* invocation of this method will block until the first operation is
|
* invocation of this method will block until the first operation is
|
||||||
* complete. </p>
|
* complete. If this channel's socket is not bound then this method will
|
||||||
|
* first cause the socket to be bound to an address that is assigned
|
||||||
|
* automatically, as if invoking the {@link #bind bind} method with a
|
||||||
|
* parameter of {@code null}. </p>
|
||||||
*
|
*
|
||||||
* @param dst
|
* @param dst
|
||||||
* The buffer into which the datagram is to be transferred
|
* The buffer into which the datagram is to be transferred
|
||||||
|
@ -413,7 +419,10 @@ public abstract class DatagramChannel
|
||||||
* <p> This method may be invoked at any time. If another thread has
|
* <p> This method may be invoked at any time. If another thread has
|
||||||
* already initiated a write operation upon this channel, however, then an
|
* already initiated a write operation upon this channel, however, then an
|
||||||
* invocation of this method will block until the first operation is
|
* invocation of this method will block until the first operation is
|
||||||
* complete. </p>
|
* complete. If this channel's socket is not bound then this method will
|
||||||
|
* first cause the socket to be bound to an address that is assigned
|
||||||
|
* automatically, as if by invoking the {@link #bind bind) method with a
|
||||||
|
* parameter of {@code null}. </p>
|
||||||
*
|
*
|
||||||
* @param src
|
* @param src
|
||||||
* The buffer containing the datagram to be sent
|
* The buffer containing the datagram to be sent
|
||||||
|
|
|
@ -1068,14 +1068,14 @@ public class TreeMap<K,V>
|
||||||
}
|
}
|
||||||
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
|
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
|
||||||
E toElement, boolean toInclusive) {
|
E toElement, boolean toInclusive) {
|
||||||
return new TreeSet<E>(m.subMap(fromElement, fromInclusive,
|
return new KeySet<E>(m.subMap(fromElement, fromInclusive,
|
||||||
toElement, toInclusive));
|
toElement, toInclusive));
|
||||||
}
|
}
|
||||||
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
||||||
return new TreeSet<E>(m.headMap(toElement, inclusive));
|
return new KeySet<E>(m.headMap(toElement, inclusive));
|
||||||
}
|
}
|
||||||
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
||||||
return new TreeSet<E>(m.tailMap(fromElement, inclusive));
|
return new KeySet<E>(m.tailMap(fromElement, inclusive));
|
||||||
}
|
}
|
||||||
public SortedSet<E> subSet(E fromElement, E toElement) {
|
public SortedSet<E> subSet(E fromElement, E toElement) {
|
||||||
return subSet(fromElement, true, toElement, false);
|
return subSet(fromElement, true, toElement, false);
|
||||||
|
@ -1087,7 +1087,7 @@ public class TreeMap<K,V>
|
||||||
return tailSet(fromElement, true);
|
return tailSet(fromElement, true);
|
||||||
}
|
}
|
||||||
public NavigableSet<E> descendingSet() {
|
public NavigableSet<E> descendingSet() {
|
||||||
return new TreeSet(m.descendingMap());
|
return new KeySet(m.descendingMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2394,15 +2394,14 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||||
boolean fromInclusive,
|
boolean fromInclusive,
|
||||||
E toElement,
|
E toElement,
|
||||||
boolean toInclusive) {
|
boolean toInclusive) {
|
||||||
return new ConcurrentSkipListSet<E>
|
return new KeySet<E>(m.subMap(fromElement, fromInclusive,
|
||||||
(m.subMap(fromElement, fromInclusive,
|
toElement, toInclusive));
|
||||||
toElement, toInclusive));
|
|
||||||
}
|
}
|
||||||
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
|
||||||
return new ConcurrentSkipListSet<E>(m.headMap(toElement, inclusive));
|
return new KeySet<E>(m.headMap(toElement, inclusive));
|
||||||
}
|
}
|
||||||
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
|
||||||
return new ConcurrentSkipListSet<E>(m.tailMap(fromElement, inclusive));
|
return new KeySet<E>(m.tailMap(fromElement, inclusive));
|
||||||
}
|
}
|
||||||
public NavigableSet<E> subSet(E fromElement, E toElement) {
|
public NavigableSet<E> subSet(E fromElement, E toElement) {
|
||||||
return subSet(fromElement, true, toElement, false);
|
return subSet(fromElement, true, toElement, false);
|
||||||
|
@ -2414,7 +2413,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||||
return tailSet(fromElement, true);
|
return tailSet(fromElement, true);
|
||||||
}
|
}
|
||||||
public NavigableSet<E> descendingSet() {
|
public NavigableSet<E> descendingSet() {
|
||||||
return new ConcurrentSkipListSet(m.descendingMap());
|
return new KeySet(m.descendingMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,11 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
static final int SIGNAL = -1;
|
static final int SIGNAL = -1;
|
||||||
/** waitStatus value to indicate thread is waiting on condition */
|
/** waitStatus value to indicate thread is waiting on condition */
|
||||||
static final int CONDITION = -2;
|
static final int CONDITION = -2;
|
||||||
|
/**
|
||||||
|
* waitStatus value to indicate the next acquireShared should
|
||||||
|
* unconditionally propagate
|
||||||
|
*/
|
||||||
|
static final int PROPAGATE = -3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status field, taking on only the values:
|
* Status field, taking on only the values:
|
||||||
|
@ -180,10 +185,16 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
* Nodes never leave this state. In particular,
|
* Nodes never leave this state. In particular,
|
||||||
* a thread with cancelled node never again blocks.
|
* a thread with cancelled node never again blocks.
|
||||||
* CONDITION: This node is currently on a condition queue.
|
* CONDITION: This node is currently on a condition queue.
|
||||||
* It will not be used as a sync queue node until
|
* It will not be used as a sync queue node
|
||||||
* transferred. (Use of this value here
|
* until transferred, at which time the status
|
||||||
* has nothing to do with the other uses
|
* will be set to 0. (Use of this value here has
|
||||||
* of the field, but simplifies mechanics.)
|
* nothing to do with the other uses of the
|
||||||
|
* field, but simplifies mechanics.)
|
||||||
|
* PROPAGATE: A releaseShared should be propagated to other
|
||||||
|
* nodes. This is set (for head node only) in
|
||||||
|
* doReleaseShared to ensure propagation
|
||||||
|
* continues, even if other operations have
|
||||||
|
* since intervened.
|
||||||
* 0: None of the above
|
* 0: None of the above
|
||||||
*
|
*
|
||||||
* The values are arranged numerically to simplify use.
|
* The values are arranged numerically to simplify use.
|
||||||
|
@ -403,10 +414,13 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
*/
|
*/
|
||||||
private void unparkSuccessor(Node node) {
|
private void unparkSuccessor(Node node) {
|
||||||
/*
|
/*
|
||||||
* Try to clear status in anticipation of signalling. It is
|
* If status is negative (i.e., possibly needing signal) try
|
||||||
* OK if this fails or if status is changed by waiting thread.
|
* to clear in anticipation of signalling. It is OK if this
|
||||||
|
* fails or if status is changed by waiting thread.
|
||||||
*/
|
*/
|
||||||
compareAndSetWaitStatus(node, Node.SIGNAL, 0);
|
int ws = node.waitStatus;
|
||||||
|
if (ws < 0)
|
||||||
|
compareAndSetWaitStatus(node, ws, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Thread to unpark is held in successor, which is normally
|
* Thread to unpark is held in successor, which is normally
|
||||||
|
@ -425,24 +439,71 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
LockSupport.unpark(s.thread);
|
LockSupport.unpark(s.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release action for shared mode -- signal successor and ensure
|
||||||
|
* propagation. (Note: For exclusive mode, release just amounts
|
||||||
|
* to calling unparkSuccessor of head if it needs signal.)
|
||||||
|
*/
|
||||||
|
private void doReleaseShared() {
|
||||||
|
/*
|
||||||
|
* Ensure that a release propagates, even if there are other
|
||||||
|
* in-progress acquires/releases. This proceeds in the usual
|
||||||
|
* way of trying to unparkSuccessor of head if it needs
|
||||||
|
* signal. But if it does not, status is set to PROPAGATE to
|
||||||
|
* ensure that upon release, propagation continues.
|
||||||
|
* Additionally, we must loop in case a new node is added
|
||||||
|
* while we are doing this. Also, unlike other uses of
|
||||||
|
* unparkSuccessor, we need to know if CAS to reset status
|
||||||
|
* fails, if so rechecking.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
Node h = head;
|
||||||
|
if (h != null && h != tail) {
|
||||||
|
int ws = h.waitStatus;
|
||||||
|
if (ws == Node.SIGNAL) {
|
||||||
|
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
|
||||||
|
continue; // loop to recheck cases
|
||||||
|
unparkSuccessor(h);
|
||||||
|
}
|
||||||
|
else if (ws == 0 &&
|
||||||
|
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
|
||||||
|
continue; // loop on failed CAS
|
||||||
|
}
|
||||||
|
if (h == head) // loop if head changed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets head of queue, and checks if successor may be waiting
|
* Sets head of queue, and checks if successor may be waiting
|
||||||
* in shared mode, if so propagating if propagate > 0.
|
* in shared mode, if so propagating if either propagate > 0 or
|
||||||
|
* PROPAGATE status was set.
|
||||||
*
|
*
|
||||||
* @param pred the node holding waitStatus for node
|
|
||||||
* @param node the node
|
* @param node the node
|
||||||
* @param propagate the return value from a tryAcquireShared
|
* @param propagate the return value from a tryAcquireShared
|
||||||
*/
|
*/
|
||||||
private void setHeadAndPropagate(Node node, long propagate) {
|
private void setHeadAndPropagate(Node node, long propagate) {
|
||||||
|
Node h = head; // Record old head for check below
|
||||||
setHead(node);
|
setHead(node);
|
||||||
if (propagate > 0 && node.waitStatus != 0) {
|
/*
|
||||||
/*
|
* Try to signal next queued node if:
|
||||||
* Don't bother fully figuring out successor. If it
|
* Propagation was indicated by caller,
|
||||||
* looks null, call unparkSuccessor anyway to be safe.
|
* or was recorded (as h.waitStatus) by a previous operation
|
||||||
*/
|
* (note: this uses sign-check of waitStatus because
|
||||||
|
* PROPAGATE status may transition to SIGNAL.)
|
||||||
|
* and
|
||||||
|
* The next node is waiting in shared mode,
|
||||||
|
* or we don't know, because it appears null
|
||||||
|
*
|
||||||
|
* The conservatism in both of these checks may cause
|
||||||
|
* unnecessary wake-ups, but only when there are multiple
|
||||||
|
* racing acquires/releases, so most need signals now or soon
|
||||||
|
* anyway.
|
||||||
|
*/
|
||||||
|
if (propagate > 0 || h == null || h.waitStatus < 0) {
|
||||||
Node s = node.next;
|
Node s = node.next;
|
||||||
if (s == null || s.isShared())
|
if (s == null || s.isShared())
|
||||||
unparkSuccessor(node);
|
doReleaseShared();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,23 +526,27 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
while (pred.waitStatus > 0)
|
while (pred.waitStatus > 0)
|
||||||
node.prev = pred = pred.prev;
|
node.prev = pred = pred.prev;
|
||||||
|
|
||||||
// Getting this before setting waitStatus ensures staleness
|
// predNext is the apparent node to unsplice. CASes below will
|
||||||
|
// fail if not, in which case, we lost race vs another cancel
|
||||||
|
// or signal, so no further action is necessary.
|
||||||
Node predNext = pred.next;
|
Node predNext = pred.next;
|
||||||
|
|
||||||
// Can use unconditional write instead of CAS here
|
// Can use unconditional write instead of CAS here.
|
||||||
|
// After this atomic step, other Nodes can skip past us.
|
||||||
|
// Before, we are free of interference from other threads.
|
||||||
node.waitStatus = Node.CANCELLED;
|
node.waitStatus = Node.CANCELLED;
|
||||||
|
|
||||||
// If we are the tail, remove ourselves
|
// If we are the tail, remove ourselves.
|
||||||
if (node == tail && compareAndSetTail(node, pred)) {
|
if (node == tail && compareAndSetTail(node, pred)) {
|
||||||
compareAndSetNext(pred, predNext, null);
|
compareAndSetNext(pred, predNext, null);
|
||||||
} else {
|
} else {
|
||||||
// If "active" predecessor found...
|
// If successor needs signal, try to set pred's next-link
|
||||||
if (pred != head
|
// so it will get one. Otherwise wake it up to propagate.
|
||||||
&& (pred.waitStatus == Node.SIGNAL
|
int ws;
|
||||||
|| compareAndSetWaitStatus(pred, 0, Node.SIGNAL))
|
if (pred != head &&
|
||||||
&& pred.thread != null) {
|
((ws = pred.waitStatus) == Node.SIGNAL ||
|
||||||
|
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
|
||||||
// If successor is active, set predecessor's next link
|
pred.thread != null) {
|
||||||
Node next = node.next;
|
Node next = node.next;
|
||||||
if (next != null && next.waitStatus <= 0)
|
if (next != null && next.waitStatus <= 0)
|
||||||
compareAndSetNext(pred, predNext, next);
|
compareAndSetNext(pred, predNext, next);
|
||||||
|
@ -503,14 +568,14 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
* @return {@code true} if thread should block
|
* @return {@code true} if thread should block
|
||||||
*/
|
*/
|
||||||
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
|
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
|
||||||
int s = pred.waitStatus;
|
int ws = pred.waitStatus;
|
||||||
if (s < 0)
|
if (ws == Node.SIGNAL)
|
||||||
/*
|
/*
|
||||||
* This node has already set status asking a release
|
* This node has already set status asking a release
|
||||||
* to signal it, so it can safely park.
|
* to signal it, so it can safely park.
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
if (s > 0) {
|
if (ws > 0) {
|
||||||
/*
|
/*
|
||||||
* Predecessor was cancelled. Skip over predecessors and
|
* Predecessor was cancelled. Skip over predecessors and
|
||||||
* indicate retry.
|
* indicate retry.
|
||||||
|
@ -519,14 +584,14 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
node.prev = pred = pred.prev;
|
node.prev = pred = pred.prev;
|
||||||
} while (pred.waitStatus > 0);
|
} while (pred.waitStatus > 0);
|
||||||
pred.next = node;
|
pred.next = node;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
/*
|
/*
|
||||||
* Indicate that we need a signal, but don't park yet. Caller
|
* waitStatus must be 0 or PROPAGATE. Indicate that we
|
||||||
* will need to retry to make sure it cannot acquire before
|
* need a signal, but don't park yet. Caller will need to
|
||||||
* parking.
|
* retry to make sure it cannot acquire before parking.
|
||||||
*/
|
*/
|
||||||
compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
|
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,9 +1111,7 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
*/
|
*/
|
||||||
public final boolean releaseShared(long arg) {
|
public final boolean releaseShared(long arg) {
|
||||||
if (tryReleaseShared(arg)) {
|
if (tryReleaseShared(arg)) {
|
||||||
Node h = head;
|
doReleaseShared();
|
||||||
if (h != null && h.waitStatus != 0)
|
|
||||||
unparkSuccessor(h);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1390,8 +1453,8 @@ public abstract class AbstractQueuedLongSynchronizer
|
||||||
* case the waitStatus can be transiently and harmlessly wrong).
|
* case the waitStatus can be transiently and harmlessly wrong).
|
||||||
*/
|
*/
|
||||||
Node p = enq(node);
|
Node p = enq(node);
|
||||||
int c = p.waitStatus;
|
int ws = p.waitStatus;
|
||||||
if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
|
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
|
||||||
LockSupport.unpark(node.thread);
|
LockSupport.unpark(node.thread);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,6 +389,11 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
static final int SIGNAL = -1;
|
static final int SIGNAL = -1;
|
||||||
/** waitStatus value to indicate thread is waiting on condition */
|
/** waitStatus value to indicate thread is waiting on condition */
|
||||||
static final int CONDITION = -2;
|
static final int CONDITION = -2;
|
||||||
|
/**
|
||||||
|
* waitStatus value to indicate the next acquireShared should
|
||||||
|
* unconditionally propagate
|
||||||
|
*/
|
||||||
|
static final int PROPAGATE = -3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status field, taking on only the values:
|
* Status field, taking on only the values:
|
||||||
|
@ -403,10 +408,16 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
* Nodes never leave this state. In particular,
|
* Nodes never leave this state. In particular,
|
||||||
* a thread with cancelled node never again blocks.
|
* a thread with cancelled node never again blocks.
|
||||||
* CONDITION: This node is currently on a condition queue.
|
* CONDITION: This node is currently on a condition queue.
|
||||||
* It will not be used as a sync queue node until
|
* It will not be used as a sync queue node
|
||||||
* transferred. (Use of this value here
|
* until transferred, at which time the status
|
||||||
* has nothing to do with the other uses
|
* will be set to 0. (Use of this value here has
|
||||||
* of the field, but simplifies mechanics.)
|
* nothing to do with the other uses of the
|
||||||
|
* field, but simplifies mechanics.)
|
||||||
|
* PROPAGATE: A releaseShared should be propagated to other
|
||||||
|
* nodes. This is set (for head node only) in
|
||||||
|
* doReleaseShared to ensure propagation
|
||||||
|
* continues, even if other operations have
|
||||||
|
* since intervened.
|
||||||
* 0: None of the above
|
* 0: None of the above
|
||||||
*
|
*
|
||||||
* The values are arranged numerically to simplify use.
|
* The values are arranged numerically to simplify use.
|
||||||
|
@ -626,10 +637,13 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
*/
|
*/
|
||||||
private void unparkSuccessor(Node node) {
|
private void unparkSuccessor(Node node) {
|
||||||
/*
|
/*
|
||||||
* Try to clear status in anticipation of signalling. It is
|
* If status is negative (i.e., possibly needing signal) try
|
||||||
* OK if this fails or if status is changed by waiting thread.
|
* to clear in anticipation of signalling. It is OK if this
|
||||||
|
* fails or if status is changed by waiting thread.
|
||||||
*/
|
*/
|
||||||
compareAndSetWaitStatus(node, Node.SIGNAL, 0);
|
int ws = node.waitStatus;
|
||||||
|
if (ws < 0)
|
||||||
|
compareAndSetWaitStatus(node, ws, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Thread to unpark is held in successor, which is normally
|
* Thread to unpark is held in successor, which is normally
|
||||||
|
@ -648,24 +662,71 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
LockSupport.unpark(s.thread);
|
LockSupport.unpark(s.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release action for shared mode -- signal successor and ensure
|
||||||
|
* propagation. (Note: For exclusive mode, release just amounts
|
||||||
|
* to calling unparkSuccessor of head if it needs signal.)
|
||||||
|
*/
|
||||||
|
private void doReleaseShared() {
|
||||||
|
/*
|
||||||
|
* Ensure that a release propagates, even if there are other
|
||||||
|
* in-progress acquires/releases. This proceeds in the usual
|
||||||
|
* way of trying to unparkSuccessor of head if it needs
|
||||||
|
* signal. But if it does not, status is set to PROPAGATE to
|
||||||
|
* ensure that upon release, propagation continues.
|
||||||
|
* Additionally, we must loop in case a new node is added
|
||||||
|
* while we are doing this. Also, unlike other uses of
|
||||||
|
* unparkSuccessor, we need to know if CAS to reset status
|
||||||
|
* fails, if so rechecking.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
Node h = head;
|
||||||
|
if (h != null && h != tail) {
|
||||||
|
int ws = h.waitStatus;
|
||||||
|
if (ws == Node.SIGNAL) {
|
||||||
|
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
|
||||||
|
continue; // loop to recheck cases
|
||||||
|
unparkSuccessor(h);
|
||||||
|
}
|
||||||
|
else if (ws == 0 &&
|
||||||
|
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
|
||||||
|
continue; // loop on failed CAS
|
||||||
|
}
|
||||||
|
if (h == head) // loop if head changed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets head of queue, and checks if successor may be waiting
|
* Sets head of queue, and checks if successor may be waiting
|
||||||
* in shared mode, if so propagating if propagate > 0.
|
* in shared mode, if so propagating if either propagate > 0 or
|
||||||
|
* PROPAGATE status was set.
|
||||||
*
|
*
|
||||||
* @param pred the node holding waitStatus for node
|
|
||||||
* @param node the node
|
* @param node the node
|
||||||
* @param propagate the return value from a tryAcquireShared
|
* @param propagate the return value from a tryAcquireShared
|
||||||
*/
|
*/
|
||||||
private void setHeadAndPropagate(Node node, int propagate) {
|
private void setHeadAndPropagate(Node node, int propagate) {
|
||||||
|
Node h = head; // Record old head for check below
|
||||||
setHead(node);
|
setHead(node);
|
||||||
if (propagate > 0 && node.waitStatus != 0) {
|
/*
|
||||||
/*
|
* Try to signal next queued node if:
|
||||||
* Don't bother fully figuring out successor. If it
|
* Propagation was indicated by caller,
|
||||||
* looks null, call unparkSuccessor anyway to be safe.
|
* or was recorded (as h.waitStatus) by a previous operation
|
||||||
*/
|
* (note: this uses sign-check of waitStatus because
|
||||||
|
* PROPAGATE status may transition to SIGNAL.)
|
||||||
|
* and
|
||||||
|
* The next node is waiting in shared mode,
|
||||||
|
* or we don't know, because it appears null
|
||||||
|
*
|
||||||
|
* The conservatism in both of these checks may cause
|
||||||
|
* unnecessary wake-ups, but only when there are multiple
|
||||||
|
* racing acquires/releases, so most need signals now or soon
|
||||||
|
* anyway.
|
||||||
|
*/
|
||||||
|
if (propagate > 0 || h == null || h.waitStatus < 0) {
|
||||||
Node s = node.next;
|
Node s = node.next;
|
||||||
if (s == null || s.isShared())
|
if (s == null || s.isShared())
|
||||||
unparkSuccessor(node);
|
doReleaseShared();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,23 +749,27 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
while (pred.waitStatus > 0)
|
while (pred.waitStatus > 0)
|
||||||
node.prev = pred = pred.prev;
|
node.prev = pred = pred.prev;
|
||||||
|
|
||||||
// Getting this before setting waitStatus ensures staleness
|
// predNext is the apparent node to unsplice. CASes below will
|
||||||
|
// fail if not, in which case, we lost race vs another cancel
|
||||||
|
// or signal, so no further action is necessary.
|
||||||
Node predNext = pred.next;
|
Node predNext = pred.next;
|
||||||
|
|
||||||
// Can use unconditional write instead of CAS here
|
// Can use unconditional write instead of CAS here.
|
||||||
|
// After this atomic step, other Nodes can skip past us.
|
||||||
|
// Before, we are free of interference from other threads.
|
||||||
node.waitStatus = Node.CANCELLED;
|
node.waitStatus = Node.CANCELLED;
|
||||||
|
|
||||||
// If we are the tail, remove ourselves
|
// If we are the tail, remove ourselves.
|
||||||
if (node == tail && compareAndSetTail(node, pred)) {
|
if (node == tail && compareAndSetTail(node, pred)) {
|
||||||
compareAndSetNext(pred, predNext, null);
|
compareAndSetNext(pred, predNext, null);
|
||||||
} else {
|
} else {
|
||||||
// If "active" predecessor found...
|
// If successor needs signal, try to set pred's next-link
|
||||||
if (pred != head
|
// so it will get one. Otherwise wake it up to propagate.
|
||||||
&& (pred.waitStatus == Node.SIGNAL
|
int ws;
|
||||||
|| compareAndSetWaitStatus(pred, 0, Node.SIGNAL))
|
if (pred != head &&
|
||||||
&& pred.thread != null) {
|
((ws = pred.waitStatus) == Node.SIGNAL ||
|
||||||
|
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
|
||||||
// If successor is active, set predecessor's next link
|
pred.thread != null) {
|
||||||
Node next = node.next;
|
Node next = node.next;
|
||||||
if (next != null && next.waitStatus <= 0)
|
if (next != null && next.waitStatus <= 0)
|
||||||
compareAndSetNext(pred, predNext, next);
|
compareAndSetNext(pred, predNext, next);
|
||||||
|
@ -726,14 +791,14 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
* @return {@code true} if thread should block
|
* @return {@code true} if thread should block
|
||||||
*/
|
*/
|
||||||
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
|
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
|
||||||
int s = pred.waitStatus;
|
int ws = pred.waitStatus;
|
||||||
if (s < 0)
|
if (ws == Node.SIGNAL)
|
||||||
/*
|
/*
|
||||||
* This node has already set status asking a release
|
* This node has already set status asking a release
|
||||||
* to signal it, so it can safely park.
|
* to signal it, so it can safely park.
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
if (s > 0) {
|
if (ws > 0) {
|
||||||
/*
|
/*
|
||||||
* Predecessor was cancelled. Skip over predecessors and
|
* Predecessor was cancelled. Skip over predecessors and
|
||||||
* indicate retry.
|
* indicate retry.
|
||||||
|
@ -742,14 +807,14 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
node.prev = pred = pred.prev;
|
node.prev = pred = pred.prev;
|
||||||
} while (pred.waitStatus > 0);
|
} while (pred.waitStatus > 0);
|
||||||
pred.next = node;
|
pred.next = node;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
/*
|
/*
|
||||||
* Indicate that we need a signal, but don't park yet. Caller
|
* waitStatus must be 0 or PROPAGATE. Indicate that we
|
||||||
* will need to retry to make sure it cannot acquire before
|
* need a signal, but don't park yet. Caller will need to
|
||||||
* parking.
|
* retry to make sure it cannot acquire before parking.
|
||||||
*/
|
*/
|
||||||
compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
|
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,9 +1334,7 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
*/
|
*/
|
||||||
public final boolean releaseShared(int arg) {
|
public final boolean releaseShared(int arg) {
|
||||||
if (tryReleaseShared(arg)) {
|
if (tryReleaseShared(arg)) {
|
||||||
Node h = head;
|
doReleaseShared();
|
||||||
if (h != null && h.waitStatus != 0)
|
|
||||||
unparkSuccessor(h);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1613,8 +1676,8 @@ public abstract class AbstractQueuedSynchronizer
|
||||||
* case the waitStatus can be transiently and harmlessly wrong).
|
* case the waitStatus can be transiently and harmlessly wrong).
|
||||||
*/
|
*/
|
||||||
Node p = enq(node);
|
Node p = enq(node);
|
||||||
int c = p.waitStatus;
|
int ws = p.waitStatus;
|
||||||
if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
|
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
|
||||||
LockSupport.unpark(node.thread);
|
LockSupport.unpark(node.thread);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
* Maintained as a ThreadLocal; cached in cachedHoldCounter
|
* Maintained as a ThreadLocal; cached in cachedHoldCounter
|
||||||
*/
|
*/
|
||||||
static final class HoldCounter {
|
static final class HoldCounter {
|
||||||
int count;
|
int count = 0;
|
||||||
// Use id, not reference, to avoid garbage retention
|
// Use id, not reference, to avoid garbage retention
|
||||||
final long tid = Thread.currentThread().getId();
|
final long tid = Thread.currentThread().getId();
|
||||||
}
|
}
|
||||||
|
@ -293,8 +293,9 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of read locks held by current thread.
|
* The number of reentrant read locks held by current thread.
|
||||||
* Initialized only in constructor and readObject.
|
* Initialized only in constructor and readObject.
|
||||||
|
* Removed whenever a thread's read hold count drops to 0.
|
||||||
*/
|
*/
|
||||||
private transient ThreadLocalHoldCounter readHolds;
|
private transient ThreadLocalHoldCounter readHolds;
|
||||||
|
|
||||||
|
@ -304,17 +305,35 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
* where the next thread to release is the last one to
|
* where the next thread to release is the last one to
|
||||||
* acquire. This is non-volatile since it is just used
|
* acquire. This is non-volatile since it is just used
|
||||||
* as a heuristic, and would be great for threads to cache.
|
* as a heuristic, and would be great for threads to cache.
|
||||||
|
*
|
||||||
|
* <p>Can outlive the Thread for which it is caching the read
|
||||||
|
* hold count, but avoids garbage retention by not retaining a
|
||||||
|
* reference to the Thread.
|
||||||
|
*
|
||||||
|
* <p>Accessed via a benign data race; relies on the memory
|
||||||
|
* model's final field and out-of-thin-air guarantees.
|
||||||
*/
|
*/
|
||||||
private transient HoldCounter cachedHoldCounter;
|
private transient HoldCounter cachedHoldCounter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* firstReader is the first thread to have acquired the read lock.
|
* firstReader is the first thread to have acquired the read lock.
|
||||||
* firstReaderHoldCount is firstReader's hold count.
|
* firstReaderHoldCount is firstReader's hold count.
|
||||||
* This allows tracking of read holds for uncontended read
|
*
|
||||||
|
* <p>More precisely, firstReader is the unique thread that last
|
||||||
|
* changed the shared count from 0 to 1, and has not released the
|
||||||
|
* read lock since then; null if there is no such thread.
|
||||||
|
*
|
||||||
|
* <p>Cannot cause garbage retention unless the thread terminated
|
||||||
|
* without relinquishing its read locks, since tryReleaseShared
|
||||||
|
* sets it to null.
|
||||||
|
*
|
||||||
|
* <p>Accessed via a benign data race; relies on the memory
|
||||||
|
* model's out-of-thin-air guarantees for references.
|
||||||
|
*
|
||||||
|
* <p>This allows tracking of read holds for uncontended read
|
||||||
* locks to be very cheap.
|
* locks to be very cheap.
|
||||||
*/
|
*/
|
||||||
private final static long INVALID_THREAD_ID = -1;
|
private transient Thread firstReader = null;
|
||||||
private transient long firstReader = INVALID_THREAD_ID;
|
|
||||||
private transient int firstReaderHoldCount;
|
private transient int firstReaderHoldCount;
|
||||||
|
|
||||||
Sync() {
|
Sync() {
|
||||||
|
@ -393,16 +412,16 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final boolean tryReleaseShared(int unused) {
|
protected final boolean tryReleaseShared(int unused) {
|
||||||
long tid = Thread.currentThread().getId();
|
Thread current = Thread.currentThread();
|
||||||
if (firstReader == tid) {
|
if (firstReader == current) {
|
||||||
// assert firstReaderHoldCount > 0;
|
// assert firstReaderHoldCount > 0;
|
||||||
if (firstReaderHoldCount == 1)
|
if (firstReaderHoldCount == 1)
|
||||||
firstReader = INVALID_THREAD_ID;
|
firstReader = null;
|
||||||
else
|
else
|
||||||
firstReaderHoldCount--;
|
firstReaderHoldCount--;
|
||||||
} else {
|
} else {
|
||||||
HoldCounter rh = cachedHoldCounter;
|
HoldCounter rh = cachedHoldCounter;
|
||||||
if (rh == null || rh.tid != tid)
|
if (rh == null || rh.tid != current.getId())
|
||||||
rh = readHolds.get();
|
rh = readHolds.get();
|
||||||
int count = rh.count;
|
int count = rh.count;
|
||||||
if (count <= 1) {
|
if (count <= 1) {
|
||||||
|
@ -416,6 +435,9 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
int c = getState();
|
int c = getState();
|
||||||
int nextc = c - SHARED_UNIT;
|
int nextc = c - SHARED_UNIT;
|
||||||
if (compareAndSetState(c, nextc))
|
if (compareAndSetState(c, nextc))
|
||||||
|
// Releasing the read lock has no effect on readers,
|
||||||
|
// but it may allow waiting writers to proceed if
|
||||||
|
// both read and write locks are now free.
|
||||||
return nextc == 0;
|
return nextc == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,15 +472,14 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
if (!readerShouldBlock() &&
|
if (!readerShouldBlock() &&
|
||||||
r < MAX_COUNT &&
|
r < MAX_COUNT &&
|
||||||
compareAndSetState(c, c + SHARED_UNIT)) {
|
compareAndSetState(c, c + SHARED_UNIT)) {
|
||||||
long tid = current.getId();
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
firstReader = tid;
|
firstReader = current;
|
||||||
firstReaderHoldCount = 1;
|
firstReaderHoldCount = 1;
|
||||||
} else if (firstReader == tid) {
|
} else if (firstReader == current) {
|
||||||
firstReaderHoldCount++;
|
firstReaderHoldCount++;
|
||||||
} else {
|
} else {
|
||||||
HoldCounter rh = cachedHoldCounter;
|
HoldCounter rh = cachedHoldCounter;
|
||||||
if (rh == null || rh.tid != tid)
|
if (rh == null || rh.tid != current.getId())
|
||||||
cachedHoldCounter = rh = readHolds.get();
|
cachedHoldCounter = rh = readHolds.get();
|
||||||
else if (rh.count == 0)
|
else if (rh.count == 0)
|
||||||
readHolds.set(rh);
|
readHolds.set(rh);
|
||||||
|
@ -485,19 +506,17 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
int c = getState();
|
int c = getState();
|
||||||
if (exclusiveCount(c) != 0) {
|
if (exclusiveCount(c) != 0) {
|
||||||
if (getExclusiveOwnerThread() != current)
|
if (getExclusiveOwnerThread() != current)
|
||||||
//if (removeNeeded) readHolds.remove();
|
|
||||||
return -1;
|
return -1;
|
||||||
// else we hold the exclusive lock; blocking here
|
// else we hold the exclusive lock; blocking here
|
||||||
// would cause deadlock.
|
// would cause deadlock.
|
||||||
} else if (readerShouldBlock()) {
|
} else if (readerShouldBlock()) {
|
||||||
// Make sure we're not acquiring read lock reentrantly
|
// Make sure we're not acquiring read lock reentrantly
|
||||||
long tid = current.getId();
|
if (firstReader == current) {
|
||||||
if (firstReader == tid) {
|
|
||||||
// assert firstReaderHoldCount > 0;
|
// assert firstReaderHoldCount > 0;
|
||||||
} else {
|
} else {
|
||||||
if (rh == null) {
|
if (rh == null) {
|
||||||
rh = cachedHoldCounter;
|
rh = cachedHoldCounter;
|
||||||
if (rh == null || rh.tid != tid) {
|
if (rh == null || rh.tid != current.getId()) {
|
||||||
rh = readHolds.get();
|
rh = readHolds.get();
|
||||||
if (rh.count == 0)
|
if (rh.count == 0)
|
||||||
readHolds.remove();
|
readHolds.remove();
|
||||||
|
@ -510,25 +529,20 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
if (sharedCount(c) == MAX_COUNT)
|
if (sharedCount(c) == MAX_COUNT)
|
||||||
throw new Error("Maximum lock count exceeded");
|
throw new Error("Maximum lock count exceeded");
|
||||||
if (compareAndSetState(c, c + SHARED_UNIT)) {
|
if (compareAndSetState(c, c + SHARED_UNIT)) {
|
||||||
long tid = current.getId();
|
|
||||||
if (sharedCount(c) == 0) {
|
if (sharedCount(c) == 0) {
|
||||||
firstReader = tid;
|
firstReader = current;
|
||||||
firstReaderHoldCount = 1;
|
firstReaderHoldCount = 1;
|
||||||
} else if (firstReader == tid) {
|
} else if (firstReader == current) {
|
||||||
firstReaderHoldCount++;
|
firstReaderHoldCount++;
|
||||||
} else {
|
} else {
|
||||||
if (rh == null) {
|
if (rh == null)
|
||||||
rh = cachedHoldCounter;
|
rh = cachedHoldCounter;
|
||||||
if (rh != null && rh.tid == tid) {
|
if (rh == null || rh.tid != current.getId())
|
||||||
if (rh.count == 0)
|
rh = readHolds.get();
|
||||||
readHolds.set(rh);
|
else if (rh.count == 0)
|
||||||
} else {
|
|
||||||
rh = readHolds.get();
|
|
||||||
}
|
|
||||||
} else if (rh.count == 0)
|
|
||||||
readHolds.set(rh);
|
readHolds.set(rh);
|
||||||
cachedHoldCounter = rh; // cache for release
|
|
||||||
rh.count++;
|
rh.count++;
|
||||||
|
cachedHoldCounter = rh; // cache for release
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -572,15 +586,14 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
if (r == MAX_COUNT)
|
if (r == MAX_COUNT)
|
||||||
throw new Error("Maximum lock count exceeded");
|
throw new Error("Maximum lock count exceeded");
|
||||||
if (compareAndSetState(c, c + SHARED_UNIT)) {
|
if (compareAndSetState(c, c + SHARED_UNIT)) {
|
||||||
long tid = current.getId();
|
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
firstReader = tid;
|
firstReader = current;
|
||||||
firstReaderHoldCount = 1;
|
firstReaderHoldCount = 1;
|
||||||
} else if (firstReader == tid) {
|
} else if (firstReader == current) {
|
||||||
firstReaderHoldCount++;
|
firstReaderHoldCount++;
|
||||||
} else {
|
} else {
|
||||||
HoldCounter rh = cachedHoldCounter;
|
HoldCounter rh = cachedHoldCounter;
|
||||||
if (rh == null || rh.tid != tid)
|
if (rh == null || rh.tid != current.getId())
|
||||||
cachedHoldCounter = rh = readHolds.get();
|
cachedHoldCounter = rh = readHolds.get();
|
||||||
else if (rh.count == 0)
|
else if (rh.count == 0)
|
||||||
readHolds.set(rh);
|
readHolds.set(rh);
|
||||||
|
@ -626,12 +639,12 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
if (getReadLockCount() == 0)
|
if (getReadLockCount() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
long tid = Thread.currentThread().getId();
|
Thread current = Thread.currentThread();
|
||||||
if (firstReader == tid)
|
if (firstReader == current)
|
||||||
return firstReaderHoldCount;
|
return firstReaderHoldCount;
|
||||||
|
|
||||||
HoldCounter rh = cachedHoldCounter;
|
HoldCounter rh = cachedHoldCounter;
|
||||||
if (rh != null && rh.tid == tid)
|
if (rh != null && rh.tid == current.getId())
|
||||||
return rh.count;
|
return rh.count;
|
||||||
|
|
||||||
int count = readHolds.get().count;
|
int count = readHolds.get().count;
|
||||||
|
@ -647,7 +660,6 @@ public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializab
|
||||||
throws java.io.IOException, ClassNotFoundException {
|
throws java.io.IOException, ClassNotFoundException {
|
||||||
s.defaultReadObject();
|
s.defaultReadObject();
|
||||||
readHolds = new ThreadLocalHoldCounter();
|
readHolds = new ThreadLocalHoldCounter();
|
||||||
firstReader = INVALID_THREAD_ID;
|
|
||||||
setState(0); // reset to unlocked state
|
setState(0); // reset to unlocked state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
77
jdk/src/share/classes/java/util/zip/ZipConstants64.java
Normal file
77
jdk/src/share/classes/java/util/zip/ZipConstants64.java
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 1995-1996 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package java.util.zip;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class defines the constants that are used by the classes
|
||||||
|
* which manipulate Zip64 files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ZipConstants64 {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ZIP64 constants
|
||||||
|
*/
|
||||||
|
static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
|
||||||
|
static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
|
||||||
|
static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
|
||||||
|
static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
|
||||||
|
static final int ZIP64_EXTHDR = 24; // EXT header size
|
||||||
|
static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
|
||||||
|
|
||||||
|
static final int ZIP64_MAGICCOUNT = 0xFFFF;
|
||||||
|
static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip64 End of central directory (END) header field offsets
|
||||||
|
*/
|
||||||
|
static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
|
||||||
|
static final int ZIP64_ENDVEM = 12; // version made by
|
||||||
|
static final int ZIP64_ENDVER = 14; // version needed to extract
|
||||||
|
static final int ZIP64_ENDNMD = 16; // number of this disk
|
||||||
|
static final int ZIP64_ENDDSK = 20; // disk number of start
|
||||||
|
static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
|
||||||
|
static final int ZIP64_ENDTOT = 32; // total number of entries
|
||||||
|
static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
|
||||||
|
static final int ZIP64_ENDOFF = 48; // offset of first CEN header
|
||||||
|
static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip64 End of central directory locator field offsets
|
||||||
|
*/
|
||||||
|
static final int ZIP64_LOCDSK = 4; // disk number start
|
||||||
|
static final int ZIP64_LOCOFF = 8; // offset of zip64 end
|
||||||
|
static final int ZIP64_LOCTOT = 16; // total number of disks
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip64 Extra local (EXT) header field offsets
|
||||||
|
*/
|
||||||
|
static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
|
||||||
|
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
|
||||||
|
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
|
||||||
|
|
||||||
|
private ZipConstants64() {}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1995-2009 Sun Microsystems, Inc. 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
|
||||||
|
@ -144,11 +144,13 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||||
* Sets the uncompressed size of the entry data.
|
* Sets the uncompressed size of the entry data.
|
||||||
* @param size the uncompressed size in bytes
|
* @param size the uncompressed size in bytes
|
||||||
* @exception IllegalArgumentException if the specified size is less
|
* @exception IllegalArgumentException if the specified size is less
|
||||||
* than 0 or greater than 0xFFFFFFFF bytes
|
* than 0, is greater than 0xFFFFFFFF when
|
||||||
|
* <a href="package-summary.html#zip64">ZIP64 format</a> is not supported,
|
||||||
|
* or is less than 0 when ZIP64 is supported
|
||||||
* @see #getSize()
|
* @see #getSize()
|
||||||
*/
|
*/
|
||||||
public void setSize(long size) {
|
public void setSize(long size) {
|
||||||
if (size < 0 || size > 0xFFFFFFFFL) {
|
if (size < 0) {
|
||||||
throw new IllegalArgumentException("invalid entry size");
|
throw new IllegalArgumentException("invalid entry size");
|
||||||
}
|
}
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1996-2009 Sun Microsystems, Inc. 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
|
||||||
|
@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.PushbackInputStream;
|
import java.io.PushbackInputStream;
|
||||||
|
import static java.util.zip.ZipConstants64.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements an input stream filter for reading files in the
|
* This class implements an input stream filter for reading files in the
|
||||||
|
@ -285,6 +286,29 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||||
byte[] bb = new byte[len];
|
byte[] bb = new byte[len];
|
||||||
readFully(bb, 0, len);
|
readFully(bb, 0, len);
|
||||||
e.setExtra(bb);
|
e.setExtra(bb);
|
||||||
|
// extra fields are in "HeaderID(2)DataSize(2)Data... format
|
||||||
|
if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
|
||||||
|
int off = 0;
|
||||||
|
while (off + 4 < len) {
|
||||||
|
int sz = get16(bb, off + 2);
|
||||||
|
if (get16(bb, off) == ZIP64_EXTID) {
|
||||||
|
off += 4;
|
||||||
|
// LOC extra zip64 entry MUST include BOTH original and
|
||||||
|
// compressed file size fields
|
||||||
|
if (sz < 16 || (off + sz) > len ) {
|
||||||
|
// Invalid zip64 extra fields, simply skip. Even it's
|
||||||
|
// rare, it's possible the entry size happens to be
|
||||||
|
// the magic value and it "accidnetly" has some bytes
|
||||||
|
// in extra match the id.
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e.size = get64(bb, off);
|
||||||
|
e.csize = get64(bb, off + 8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
off += (sz + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -375,18 +399,36 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||||
}
|
}
|
||||||
if ((flag & 8) == 8) {
|
if ((flag & 8) == 8) {
|
||||||
/* "Data Descriptor" present */
|
/* "Data Descriptor" present */
|
||||||
readFully(tmpbuf, 0, EXTHDR);
|
if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
|
||||||
long sig = get32(tmpbuf, 0);
|
inf.getBytesRead() > ZIP64_MAGICVAL) {
|
||||||
if (sig != EXTSIG) { // no EXTSIG present
|
// ZIP64 format
|
||||||
e.crc = sig;
|
readFully(tmpbuf, 0, ZIP64_EXTHDR);
|
||||||
e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
|
long sig = get32(tmpbuf, 0);
|
||||||
e.size = get32(tmpbuf, EXTLEN - EXTCRC);
|
if (sig != EXTSIG) { // no EXTSIG present
|
||||||
((PushbackInputStream)in).unread(
|
e.crc = sig;
|
||||||
tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
|
e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
|
||||||
|
e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
|
||||||
|
((PushbackInputStream)in).unread(
|
||||||
|
tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
|
||||||
|
} else {
|
||||||
|
e.crc = get32(tmpbuf, ZIP64_EXTCRC);
|
||||||
|
e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
|
||||||
|
e.size = get64(tmpbuf, ZIP64_EXTLEN);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
e.crc = get32(tmpbuf, EXTCRC);
|
readFully(tmpbuf, 0, EXTHDR);
|
||||||
e.csize = get32(tmpbuf, EXTSIZ);
|
long sig = get32(tmpbuf, 0);
|
||||||
e.size = get32(tmpbuf, EXTLEN);
|
if (sig != EXTSIG) { // no EXTSIG present
|
||||||
|
e.crc = sig;
|
||||||
|
e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
|
||||||
|
e.size = get32(tmpbuf, EXTLEN - EXTCRC);
|
||||||
|
((PushbackInputStream)in).unread(
|
||||||
|
tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
|
||||||
|
} else {
|
||||||
|
e.crc = get32(tmpbuf, EXTCRC);
|
||||||
|
e.csize = get32(tmpbuf, EXTSIZ);
|
||||||
|
e.size = get32(tmpbuf, EXTLEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.size != inf.getBytesWritten()) {
|
if (e.size != inf.getBytesWritten()) {
|
||||||
|
@ -433,6 +475,14 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||||
* The bytes are assumed to be in Intel (little-endian) byte order.
|
* The bytes are assumed to be in Intel (little-endian) byte order.
|
||||||
*/
|
*/
|
||||||
private static final long get32(byte b[], int off) {
|
private static final long get32(byte b[], int off) {
|
||||||
return get16(b, off) | ((long)get16(b, off+2) << 16);
|
return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetches signed 64-bit value from byte array at specified offset.
|
||||||
|
* The bytes are assumed to be in Intel (little-endian) byte order.
|
||||||
|
*/
|
||||||
|
private static final long get64(byte b[], int off) {
|
||||||
|
return get32(b, off) | (get32(b, off+4) << 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1996-2009 Sun Microsystems, Inc. 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
|
||||||
|
@ -29,6 +29,7 @@ import java.io.OutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import static java.util.zip.ZipConstants64.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements an output stream filter for writing files in the
|
* This class implements an output stream filter for writing files in the
|
||||||
|
@ -343,26 +344,52 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
private void writeLOC(XEntry xentry) throws IOException {
|
private void writeLOC(XEntry xentry) throws IOException {
|
||||||
ZipEntry e = xentry.entry;
|
ZipEntry e = xentry.entry;
|
||||||
int flag = xentry.flag;
|
int flag = xentry.flag;
|
||||||
|
int elen = (e.extra != null) ? e.extra.length : 0;
|
||||||
|
boolean hasZip64 = false;
|
||||||
|
|
||||||
writeInt(LOCSIG); // LOC header signature
|
writeInt(LOCSIG); // LOC header signature
|
||||||
writeShort(version(e)); // version needed to extract
|
|
||||||
writeShort(flag); // general purpose bit flag
|
|
||||||
writeShort(e.method); // compression method
|
|
||||||
writeInt(e.time); // last modification time
|
|
||||||
if ((flag & 8) == 8) {
|
if ((flag & 8) == 8) {
|
||||||
|
writeShort(version(e)); // version needed to extract
|
||||||
|
writeShort(flag); // general purpose bit flag
|
||||||
|
writeShort(e.method); // compression method
|
||||||
|
writeInt(e.time); // last modification time
|
||||||
|
|
||||||
// store size, uncompressed size, and crc-32 in data descriptor
|
// store size, uncompressed size, and crc-32 in data descriptor
|
||||||
// immediately following compressed entry data
|
// immediately following compressed entry data
|
||||||
writeInt(0);
|
writeInt(0);
|
||||||
writeInt(0);
|
writeInt(0);
|
||||||
writeInt(0);
|
writeInt(0);
|
||||||
} else {
|
} else {
|
||||||
writeInt(e.crc); // crc-32
|
if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
|
||||||
writeInt(e.csize); // compressed size
|
hasZip64 = true;
|
||||||
writeInt(e.size); // uncompressed size
|
writeShort(45); // ver 4.5 for zip64
|
||||||
|
} else {
|
||||||
|
writeShort(version(e)); // version needed to extract
|
||||||
|
}
|
||||||
|
writeShort(flag); // general purpose bit flag
|
||||||
|
writeShort(e.method); // compression method
|
||||||
|
writeInt(e.time); // last modification time
|
||||||
|
writeInt(e.crc); // crc-32
|
||||||
|
if (hasZip64) {
|
||||||
|
writeInt(ZIP64_MAGICVAL);
|
||||||
|
writeInt(ZIP64_MAGICVAL);
|
||||||
|
elen += 20; //headid(2) + size(2) + size(8) + csize(8)
|
||||||
|
} else {
|
||||||
|
writeInt(e.csize); // compressed size
|
||||||
|
writeInt(e.size); // uncompressed size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||||
writeShort(nameBytes.length);
|
writeShort(nameBytes.length);
|
||||||
writeShort(e.extra != null ? e.extra.length : 0);
|
writeShort(elen);
|
||||||
writeBytes(nameBytes, 0, nameBytes.length);
|
writeBytes(nameBytes, 0, nameBytes.length);
|
||||||
|
if (hasZip64) {
|
||||||
|
writeShort(ZIP64_EXTID);
|
||||||
|
writeShort(16);
|
||||||
|
writeLong(e.size);
|
||||||
|
writeLong(e.csize);
|
||||||
|
}
|
||||||
if (e.extra != null) {
|
if (e.extra != null) {
|
||||||
writeBytes(e.extra, 0, e.extra.length);
|
writeBytes(e.extra, 0, e.extra.length);
|
||||||
}
|
}
|
||||||
|
@ -375,8 +402,13 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
private void writeEXT(ZipEntry e) throws IOException {
|
private void writeEXT(ZipEntry e) throws IOException {
|
||||||
writeInt(EXTSIG); // EXT header signature
|
writeInt(EXTSIG); // EXT header signature
|
||||||
writeInt(e.crc); // crc-32
|
writeInt(e.crc); // crc-32
|
||||||
writeInt(e.csize); // compressed size
|
if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
|
||||||
writeInt(e.size); // uncompressed size
|
writeLong(e.csize);
|
||||||
|
writeLong(e.size);
|
||||||
|
} else {
|
||||||
|
writeInt(e.csize); // compressed size
|
||||||
|
writeInt(e.size); // uncompressed size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -387,18 +419,49 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
ZipEntry e = xentry.entry;
|
ZipEntry e = xentry.entry;
|
||||||
int flag = xentry.flag;
|
int flag = xentry.flag;
|
||||||
int version = version(e);
|
int version = version(e);
|
||||||
|
|
||||||
|
long csize = e.csize;
|
||||||
|
long size = e.size;
|
||||||
|
long offset = xentry.offset;
|
||||||
|
int e64len = 0;
|
||||||
|
boolean hasZip64 = false;
|
||||||
|
if (e.csize >= ZIP64_MAGICVAL) {
|
||||||
|
csize = ZIP64_MAGICVAL;
|
||||||
|
e64len += 8; // csize(8)
|
||||||
|
hasZip64 = true;
|
||||||
|
}
|
||||||
|
if (e.size >= ZIP64_MAGICVAL) {
|
||||||
|
size = ZIP64_MAGICVAL; // size(8)
|
||||||
|
e64len += 8;
|
||||||
|
hasZip64 = true;
|
||||||
|
}
|
||||||
|
if (xentry.offset >= ZIP64_MAGICVAL) {
|
||||||
|
offset = ZIP64_MAGICVAL;
|
||||||
|
e64len += 8; // offset(8)
|
||||||
|
hasZip64 = true;
|
||||||
|
}
|
||||||
writeInt(CENSIG); // CEN header signature
|
writeInt(CENSIG); // CEN header signature
|
||||||
writeShort(version); // version made by
|
if (hasZip64) {
|
||||||
writeShort(version); // version needed to extract
|
writeShort(45); // ver 4.5 for zip64
|
||||||
|
writeShort(45);
|
||||||
|
} else {
|
||||||
|
writeShort(version); // version made by
|
||||||
|
writeShort(version); // version needed to extract
|
||||||
|
}
|
||||||
writeShort(flag); // general purpose bit flag
|
writeShort(flag); // general purpose bit flag
|
||||||
writeShort(e.method); // compression method
|
writeShort(e.method); // compression method
|
||||||
writeInt(e.time); // last modification time
|
writeInt(e.time); // last modification time
|
||||||
writeInt(e.crc); // crc-32
|
writeInt(e.crc); // crc-32
|
||||||
writeInt(e.csize); // compressed size
|
writeInt(csize); // compressed size
|
||||||
writeInt(e.size); // uncompressed size
|
writeInt(size); // uncompressed size
|
||||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||||
writeShort(nameBytes.length);
|
writeShort(nameBytes.length);
|
||||||
writeShort(e.extra != null ? e.extra.length : 0);
|
if (hasZip64) {
|
||||||
|
// + headid(2) + datasize(2)
|
||||||
|
writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0));
|
||||||
|
} else {
|
||||||
|
writeShort(e.extra != null ? e.extra.length : 0);
|
||||||
|
}
|
||||||
byte[] commentBytes;
|
byte[] commentBytes;
|
||||||
if (e.comment != null) {
|
if (e.comment != null) {
|
||||||
commentBytes = getUTF8Bytes(e.comment);
|
commentBytes = getUTF8Bytes(e.comment);
|
||||||
|
@ -410,8 +473,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
writeShort(0); // starting disk number
|
writeShort(0); // starting disk number
|
||||||
writeShort(0); // internal file attributes (unused)
|
writeShort(0); // internal file attributes (unused)
|
||||||
writeInt(0); // external file attributes (unused)
|
writeInt(0); // external file attributes (unused)
|
||||||
writeInt(xentry.offset); // relative offset of local header
|
writeInt(offset); // relative offset of local header
|
||||||
writeBytes(nameBytes, 0, nameBytes.length);
|
writeBytes(nameBytes, 0, nameBytes.length);
|
||||||
|
if (hasZip64) {
|
||||||
|
writeShort(ZIP64_EXTID);// Zip64 extra
|
||||||
|
writeShort(e64len);
|
||||||
|
if (size == ZIP64_MAGICVAL)
|
||||||
|
writeLong(e.size);
|
||||||
|
if (csize == ZIP64_MAGICVAL)
|
||||||
|
writeLong(e.csize);
|
||||||
|
if (offset == ZIP64_MAGICVAL)
|
||||||
|
writeLong(xentry.offset);
|
||||||
|
}
|
||||||
if (e.extra != null) {
|
if (e.extra != null) {
|
||||||
writeBytes(e.extra, 0, e.extra.length);
|
writeBytes(e.extra, 0, e.extra.length);
|
||||||
}
|
}
|
||||||
|
@ -424,15 +497,50 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
* Writes end of central directory (END) header.
|
* Writes end of central directory (END) header.
|
||||||
*/
|
*/
|
||||||
private void writeEND(long off, long len) throws IOException {
|
private void writeEND(long off, long len) throws IOException {
|
||||||
|
boolean hasZip64 = false;
|
||||||
|
long xlen = len;
|
||||||
|
long xoff = off;
|
||||||
|
if (xlen >= ZIP64_MAGICVAL) {
|
||||||
|
xlen = ZIP64_MAGICVAL;
|
||||||
|
hasZip64 = true;
|
||||||
|
}
|
||||||
|
if (xoff >= ZIP64_MAGICVAL) {
|
||||||
|
xoff = ZIP64_MAGICVAL;
|
||||||
|
hasZip64 = true;
|
||||||
|
}
|
||||||
int count = xentries.size();
|
int count = xentries.size();
|
||||||
writeInt(ENDSIG); // END record signature
|
if (count >= ZIP64_MAGICCOUNT) {
|
||||||
writeShort(0); // number of this disk
|
count = ZIP64_MAGICCOUNT;
|
||||||
writeShort(0); // central directory start disk
|
hasZip64 = true;
|
||||||
writeShort(count); // number of directory entries on disk
|
}
|
||||||
writeShort(count); // total number of directory entries
|
if (hasZip64) {
|
||||||
writeInt(len); // length of central directory
|
long off64 = written;
|
||||||
writeInt(off); // offset of central directory
|
//zip64 end of central directory record
|
||||||
if (comment != null) { // zip file comment
|
writeInt(ZIP64_ENDSIG); // zip64 END record signature
|
||||||
|
writeLong(ZIP64_ENDHDR - 12); // size of zip64 end
|
||||||
|
writeShort(45); // version made by
|
||||||
|
writeShort(45); // version needed to extract
|
||||||
|
writeInt(0); // number of this disk
|
||||||
|
writeInt(0); // central directory start disk
|
||||||
|
writeLong(xentries.size()); // number of directory entires on disk
|
||||||
|
writeLong(xentries.size()); // number of directory entires
|
||||||
|
writeLong(len); // length of central directory
|
||||||
|
writeLong(off); // offset of central directory
|
||||||
|
|
||||||
|
//zip64 end of central directory locator
|
||||||
|
writeInt(ZIP64_LOCSIG); // zip64 END locator signature
|
||||||
|
writeInt(0); // zip64 END start disk
|
||||||
|
writeLong(off64); // offset of zip64 END
|
||||||
|
writeInt(1); // total number of disks (?)
|
||||||
|
}
|
||||||
|
writeInt(ENDSIG); // END record signature
|
||||||
|
writeShort(0); // number of this disk
|
||||||
|
writeShort(0); // central directory start disk
|
||||||
|
writeShort(count); // number of directory entries on disk
|
||||||
|
writeShort(count); // total number of directory entries
|
||||||
|
writeInt(xlen); // length of central directory
|
||||||
|
writeInt(xoff); // offset of central directory
|
||||||
|
if (comment != null) { // zip file comment
|
||||||
byte[] b = getUTF8Bytes(comment);
|
byte[] b = getUTF8Bytes(comment);
|
||||||
writeShort(b.length);
|
writeShort(b.length);
|
||||||
writeBytes(b, 0, b.length);
|
writeBytes(b, 0, b.length);
|
||||||
|
@ -463,6 +571,22 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||||
written += 4;
|
written += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a 64-bit int to the output stream in little-endian byte order.
|
||||||
|
*/
|
||||||
|
private void writeLong(long v) throws IOException {
|
||||||
|
OutputStream out = this.out;
|
||||||
|
out.write((int)((v >>> 0) & 0xff));
|
||||||
|
out.write((int)((v >>> 8) & 0xff));
|
||||||
|
out.write((int)((v >>> 16) & 0xff));
|
||||||
|
out.write((int)((v >>> 24) & 0xff));
|
||||||
|
out.write((int)((v >>> 32) & 0xff));
|
||||||
|
out.write((int)((v >>> 40) & 0xff));
|
||||||
|
out.write((int)((v >>> 48) & 0xff));
|
||||||
|
out.write((int)((v >>> 56) & 0xff));
|
||||||
|
written += 8;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Writes an array of bytes to the output stream.
|
* Writes an array of bytes to the output stream.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,13 @@ input streams.
|
||||||
Info-ZIP Application Note 970311
|
Info-ZIP Application Note 970311
|
||||||
</a> - a detailed description of the Info-ZIP format upon which
|
</a> - a detailed description of the Info-ZIP format upon which
|
||||||
the <code>java.util.zip</code> classes are based.
|
the <code>java.util.zip</code> classes are based.
|
||||||
|
<p>
|
||||||
|
<a name="zip64">
|
||||||
|
<li>An implementation may optionally support the ZIP64(tm) format extensions
|
||||||
|
defined by the
|
||||||
|
<a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
|
||||||
|
PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
|
||||||
|
are used to overcome the size limitations of the original ZIP format.
|
||||||
<p>
|
<p>
|
||||||
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
|
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
|
||||||
ZLIB Compressed Data Format Specification version 3.3</a>
|
ZLIB Compressed Data Format Specification version 3.3</a>
|
||||||
|
@ -70,7 +77,6 @@ input streams.
|
||||||
<li>CRC-32 checksum is described in RFC 1952 (above)
|
<li>CRC-32 checksum is described in RFC 1952 (above)
|
||||||
<p>
|
<p>
|
||||||
<li>Adler-32 checksum is described in RFC 1950 (above)
|
<li>Adler-32 checksum is described in RFC 1950 (above)
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
};
|
};
|
||||||
|
|
||||||
private static boolean hasSystemProxies = false;
|
private static boolean hasSystemProxies = false;
|
||||||
private static Properties defprops = new Properties();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
final String key = "java.net.useSystemProxies";
|
final String key = "java.net.useSystemProxies";
|
||||||
|
@ -107,6 +106,9 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
RegexpPool hostsPool;
|
RegexpPool hostsPool;
|
||||||
String property;
|
String property;
|
||||||
|
|
||||||
|
static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
|
||||||
|
static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
|
||||||
|
|
||||||
NonProxyInfo(String p, String s, RegexpPool pool) {
|
NonProxyInfo(String p, String s, RegexpPool pool) {
|
||||||
property = p;
|
property = p;
|
||||||
hostsSource = s;
|
hostsSource = s;
|
||||||
|
@ -114,8 +116,6 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
|
|
||||||
private static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* select() method. Where all the hard work is done.
|
* select() method. Where all the hard work is done.
|
||||||
|
@ -175,13 +175,13 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
NonProxyInfo pinfo = null;
|
NonProxyInfo pinfo = null;
|
||||||
|
|
||||||
if ("http".equalsIgnoreCase(protocol)) {
|
if ("http".equalsIgnoreCase(protocol)) {
|
||||||
pinfo = httpNonProxyInfo;
|
pinfo = NonProxyInfo.httpNonProxyInfo;
|
||||||
} else if ("https".equalsIgnoreCase(protocol)) {
|
} else if ("https".equalsIgnoreCase(protocol)) {
|
||||||
// HTTPS uses the same property as HTTP, for backward
|
// HTTPS uses the same property as HTTP, for backward
|
||||||
// compatibility
|
// compatibility
|
||||||
pinfo = httpNonProxyInfo;
|
pinfo = NonProxyInfo.httpNonProxyInfo;
|
||||||
} else if ("ftp".equalsIgnoreCase(protocol)) {
|
} else if ("ftp".equalsIgnoreCase(protocol)) {
|
||||||
pinfo = ftpNonProxyInfo;
|
pinfo = NonProxyInfo.ftpNonProxyInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -334,7 +334,6 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
|
|
||||||
private boolean isLoopback(String host) {
|
private boolean isLoopback(String host) {
|
||||||
if (host == null || host.length() == 0)
|
if (host == null || host.length() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -364,6 +363,7 @@ public class DefaultProxySelector extends ProxySelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (host.endsWith(":1")) {
|
if (host.endsWith(":1")) {
|
||||||
|
final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
|
||||||
return p6.matcher(host).matches();
|
return p6.matcher(host).matches();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -313,11 +313,9 @@ class DatagramChannelImpl
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
synchronized (readLock) {
|
synchronized (readLock) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
// If socket is not bound then behave as if nothing received
|
// Socket was not bound before attempting receive
|
||||||
// Will be fixed by 6621699
|
if (localAddress() == null)
|
||||||
if (localAddress() == null) {
|
bind(null);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
ByteBuffer bb = null;
|
ByteBuffer bb = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
package sun.nio.ch;
|
package sun.nio.ch;
|
||||||
|
|
||||||
|
import java.nio.channels.Channel;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ import java.io.IOException;
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface SelChImpl {
|
interface SelChImpl extends Channel {
|
||||||
|
|
||||||
FileDescriptor getFD();
|
FileDescriptor getFD();
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2009 Sun Microsystems, Inc. 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
|
||||||
|
@ -54,8 +54,8 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"If keystore is not password protected, then -storepass and -keypass must not be specified"},
|
"If keystore is not password protected, then -storepass and -keypass must not be specified"},
|
||||||
{"Usage: jarsigner [options] jar-file alias",
|
{"Usage: jarsigner [options] jar-file alias",
|
||||||
"Usage: jarsigner [options] jar-file alias"},
|
"Usage: jarsigner [options] jar-file alias"},
|
||||||
{" jarsigner -verify [options] jar-file",
|
{" jarsigner -verify [options] jar-file [alias...]",
|
||||||
" jarsigner -verify [options] jar-file"},
|
" jarsigner -verify [options] jar-file [alias...]"},
|
||||||
{"[-keystore <url>] keystore location",
|
{"[-keystore <url>] keystore location",
|
||||||
"[-keystore <url>] keystore location"},
|
"[-keystore <url>] keystore location"},
|
||||||
{"[-storepass <password>] password for keystore integrity",
|
{"[-storepass <password>] password for keystore integrity",
|
||||||
|
@ -64,6 +64,8 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"[-storetype <type>] keystore type"},
|
"[-storetype <type>] keystore type"},
|
||||||
{"[-keypass <password>] password for private key (if different)",
|
{"[-keypass <password>] password for private key (if different)",
|
||||||
"[-keypass <password>] password for private key (if different)"},
|
"[-keypass <password>] password for private key (if different)"},
|
||||||
|
{"[-certchain <file>] name of alternative certchain file",
|
||||||
|
"[-certchain <file>] name of alternative certchain file"},
|
||||||
{"[-sigfile <file>] name of .SF/.DSA file",
|
{"[-sigfile <file>] name of .SF/.DSA file",
|
||||||
"[-sigfile <file>] name of .SF/.DSA file"},
|
"[-sigfile <file>] name of .SF/.DSA file"},
|
||||||
{"[-signedjar <file>] name of signed JAR file",
|
{"[-signedjar <file>] name of signed JAR file",
|
||||||
|
@ -74,8 +76,10 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"[-sigalg <algorithm>] name of signature algorithm"},
|
"[-sigalg <algorithm>] name of signature algorithm"},
|
||||||
{"[-verify] verify a signed JAR file",
|
{"[-verify] verify a signed JAR file",
|
||||||
"[-verify] verify a signed JAR file"},
|
"[-verify] verify a signed JAR file"},
|
||||||
{"[-verbose] verbose output when signing/verifying",
|
{"[-verbose[:suboptions]] verbose output when signing/verifying.",
|
||||||
"[-verbose] verbose output when signing/verifying"},
|
"[-verbose[:suboptions]] verbose output when signing/verifying."},
|
||||||
|
{" suboptions can be all, grouped or summary",
|
||||||
|
" suboptions can be all, grouped or summary"},
|
||||||
{"[-certs] display certificates when verbose and verifying",
|
{"[-certs] display certificates when verbose and verifying",
|
||||||
"[-certs] display certificates when verbose and verifying"},
|
"[-certs] display certificates when verbose and verifying"},
|
||||||
{"[-tsa <url>] location of the Timestamping Authority",
|
{"[-tsa <url>] location of the Timestamping Authority",
|
||||||
|
@ -98,10 +102,22 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"[-providerClass <class> name of cryptographic service provider's"},
|
"[-providerClass <class> name of cryptographic service provider's"},
|
||||||
{" [-providerArg <arg>]] ... master class file and constructor argument",
|
{" [-providerArg <arg>]] ... master class file and constructor argument",
|
||||||
" [-providerArg <arg>]] ... master class file and constructor argument"},
|
" [-providerArg <arg>]] ... master class file and constructor argument"},
|
||||||
|
{"[-strict] treat warnings as errors",
|
||||||
|
"[-strict] treat warnings as errors"},
|
||||||
|
{"Option lacks argument", "Option lacks argument"},
|
||||||
|
{"Please type jarsigner -help for usage", "Please type jarsigner -help for usage"},
|
||||||
|
{"Please specify jarfile name", "Please specify jarfile name"},
|
||||||
|
{"Please specify alias name", "Please specify alias name"},
|
||||||
|
{"Only one alias can be specified", "Only one alias can be specified"},
|
||||||
|
{"This jar contains signed entries which is not signed by the specified alias(es).",
|
||||||
|
"This jar contains signed entries which is not signed by the specified alias(es)."},
|
||||||
|
{"This jar contains signed entries that's not signed by alias in this keystore.",
|
||||||
|
"This jar contains signed entries that's not signed by alias in this keystore."},
|
||||||
{"s", "s"},
|
{"s", "s"},
|
||||||
{"m", "m"},
|
{"m", "m"},
|
||||||
{"k", "k"},
|
{"k", "k"},
|
||||||
{"i", "i"},
|
{"i", "i"},
|
||||||
|
{"(and %d more)", "(and %d more)"},
|
||||||
{" s = signature was verified ",
|
{" s = signature was verified ",
|
||||||
" s = signature was verified "},
|
" s = signature was verified "},
|
||||||
{" m = entry is listed in manifest",
|
{" m = entry is listed in manifest",
|
||||||
|
@ -110,7 +126,11 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
" k = at least one certificate was found in keystore"},
|
" k = at least one certificate was found in keystore"},
|
||||||
{" i = at least one certificate was found in identity scope",
|
{" i = at least one certificate was found in identity scope",
|
||||||
" i = at least one certificate was found in identity scope"},
|
" i = at least one certificate was found in identity scope"},
|
||||||
|
{" X = not signed by specified alias(es)",
|
||||||
|
" X = not signed by specified alias(es)"},
|
||||||
{"no manifest.", "no manifest."},
|
{"no manifest.", "no manifest."},
|
||||||
|
{"(Signature related entries)","(Signature related entries)"},
|
||||||
|
{"(Unsigned entries)", "(Unsigned entries)"},
|
||||||
{"jar is unsigned. (signatures missing or not parsable)",
|
{"jar is unsigned. (signatures missing or not parsable)",
|
||||||
"jar is unsigned. (signatures missing or not parsable)"},
|
"jar is unsigned. (signatures missing or not parsable)"},
|
||||||
{"jar verified.", "jar verified."},
|
{"jar verified.", "jar verified."},
|
||||||
|
@ -134,6 +154,12 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"unable to instantiate keystore class: "},
|
"unable to instantiate keystore class: "},
|
||||||
{"Certificate chain not found for: alias. alias must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.",
|
{"Certificate chain not found for: alias. alias must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.",
|
||||||
"Certificate chain not found for: {0}. {1} must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."},
|
"Certificate chain not found for: {0}. {1} must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain."},
|
||||||
|
{"File specified by -certchain does not exist",
|
||||||
|
"File specified by -certchain does not exist"},
|
||||||
|
{"Cannot restore certchain from file specified",
|
||||||
|
"Cannot restore certchain from file specified"},
|
||||||
|
{"Certificate chain not found in the file specified.",
|
||||||
|
"Certificate chain not found in the file specified."},
|
||||||
{"found non-X.509 certificate in signer's chain",
|
{"found non-X.509 certificate in signer's chain",
|
||||||
"found non-X.509 certificate in signer's chain"},
|
"found non-X.509 certificate in signer's chain"},
|
||||||
{"incomplete certificate chain", "incomplete certificate chain"},
|
{"incomplete certificate chain", "incomplete certificate chain"},
|
||||||
|
@ -149,6 +175,7 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
{"certificate is not valid until",
|
{"certificate is not valid until",
|
||||||
"certificate is not valid until {0}"},
|
"certificate is not valid until {0}"},
|
||||||
{"certificate will expire on", "certificate will expire on {0}"},
|
{"certificate will expire on", "certificate will expire on {0}"},
|
||||||
|
{"[CertPath not validated: ", "[CertPath not validated: "},
|
||||||
{"requesting a signature timestamp",
|
{"requesting a signature timestamp",
|
||||||
"requesting a signature timestamp"},
|
"requesting a signature timestamp"},
|
||||||
{"TSA location: ", "TSA location: "},
|
{"TSA location: ", "TSA location: "},
|
||||||
|
@ -189,14 +216,18 @@ public class JarSignerResources extends java.util.ListResourceBundle {
|
||||||
"The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
|
"The signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
|
||||||
{"The signer certificate's NetscapeCertType extension doesn't allow code signing.",
|
{"The signer certificate's NetscapeCertType extension doesn't allow code signing.",
|
||||||
"The signer certificate's NetscapeCertType extension doesn't allow code signing."},
|
"The signer certificate's NetscapeCertType extension doesn't allow code signing."},
|
||||||
{"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing.",
|
{"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing.",
|
||||||
"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
|
"This jar contains entries whose signer certificate's KeyUsage extension doesn't allow code signing."},
|
||||||
{"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing.",
|
{"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing.",
|
||||||
"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
|
"This jar contains entries whose signer certificate's ExtendedKeyUsage extension doesn't allow code signing."},
|
||||||
{"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing.",
|
{"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing.",
|
||||||
"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
|
"This jar contains entries whose signer certificate's NetscapeCertType extension doesn't allow code signing."},
|
||||||
{"[{0} extension does not support code signing]",
|
{"[{0} extension does not support code signing]",
|
||||||
"[{0} extension does not support code signing]"},
|
"[{0} extension does not support code signing]"},
|
||||||
|
{"The signer's certificate chain is not validated.",
|
||||||
|
"The signer's certificate chain is not validated."},
|
||||||
|
{"This jar contains entries whose certificate chain is not validated.",
|
||||||
|
"This jar contains entries whose certificate chain is not validated."},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2545,7 +2545,19 @@ public final class KeyTool {
|
||||||
* Returns true if the certificate is self-signed, false otherwise.
|
* Returns true if the certificate is self-signed, false otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean isSelfSigned(X509Certificate cert) {
|
private boolean isSelfSigned(X509Certificate cert) {
|
||||||
return cert.getSubjectDN().equals(cert.getIssuerDN());
|
return signedBy(cert, cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean signedBy(X509Certificate end, X509Certificate ca) {
|
||||||
|
if (!ca.getSubjectDN().equals(end.getIssuerDN())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
end.verify(ca.getPublicKey());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2869,20 +2881,18 @@ public final class KeyTool {
|
||||||
Certificate tmpCert = replyCerts[0];
|
Certificate tmpCert = replyCerts[0];
|
||||||
replyCerts[0] = replyCerts[i];
|
replyCerts[0] = replyCerts[i];
|
||||||
replyCerts[i] = tmpCert;
|
replyCerts[i] = tmpCert;
|
||||||
Principal issuer = ((X509Certificate)replyCerts[0]).getIssuerDN();
|
|
||||||
|
X509Certificate thisCert = (X509Certificate)replyCerts[0];
|
||||||
|
|
||||||
for (i=1; i < replyCerts.length-1; i++) {
|
for (i=1; i < replyCerts.length-1; i++) {
|
||||||
// find a cert in the reply whose "subject" is the same as the
|
// find a cert in the reply who signs thisCert
|
||||||
// given "issuer"
|
|
||||||
int j;
|
int j;
|
||||||
for (j=i; j<replyCerts.length; j++) {
|
for (j=i; j<replyCerts.length; j++) {
|
||||||
Principal subject;
|
if (signedBy(thisCert, (X509Certificate)replyCerts[j])) {
|
||||||
subject = ((X509Certificate)replyCerts[j]).getSubjectDN();
|
|
||||||
if (subject.equals(issuer)) {
|
|
||||||
tmpCert = replyCerts[i];
|
tmpCert = replyCerts[i];
|
||||||
replyCerts[i] = replyCerts[j];
|
replyCerts[i] = replyCerts[j];
|
||||||
replyCerts[j] = tmpCert;
|
replyCerts[j] = tmpCert;
|
||||||
issuer = ((X509Certificate)replyCerts[i]).getIssuerDN();
|
thisCert = (X509Certificate)replyCerts[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2892,18 +2902,6 @@ public final class KeyTool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now verify each cert in the ordered chain
|
|
||||||
for (i=0; i<replyCerts.length-1; i++) {
|
|
||||||
PublicKey pubKey = replyCerts[i+1].getPublicKey();
|
|
||||||
try {
|
|
||||||
replyCerts[i].verify(pubKey);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new Exception(rb.getString
|
|
||||||
("Certificate chain in reply does not verify: ") +
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noprompt) {
|
if (noprompt) {
|
||||||
return replyCerts;
|
return replyCerts;
|
||||||
}
|
}
|
||||||
|
@ -3035,9 +3033,8 @@ public final class KeyTool {
|
||||||
private boolean buildChain(X509Certificate certToVerify,
|
private boolean buildChain(X509Certificate certToVerify,
|
||||||
Vector<Certificate> chain,
|
Vector<Certificate> chain,
|
||||||
Hashtable<Principal, Vector<Certificate>> certs) {
|
Hashtable<Principal, Vector<Certificate>> certs) {
|
||||||
Principal subject = certToVerify.getSubjectDN();
|
|
||||||
Principal issuer = certToVerify.getIssuerDN();
|
Principal issuer = certToVerify.getIssuerDN();
|
||||||
if (subject.equals(issuer)) {
|
if (isSelfSigned(certToVerify)) {
|
||||||
// reached self-signed root cert;
|
// reached self-signed root cert;
|
||||||
// no verification needed because it's trusted.
|
// no verification needed because it's trusted.
|
||||||
chain.addElement(certToVerify);
|
chain.addElement(certToVerify);
|
||||||
|
@ -3108,7 +3105,7 @@ public final class KeyTool {
|
||||||
/**
|
/**
|
||||||
* Returns the keystore with the configured CA certificates.
|
* Returns the keystore with the configured CA certificates.
|
||||||
*/
|
*/
|
||||||
private KeyStore getCacertsKeyStore()
|
public static KeyStore getCacertsKeyStore()
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
String sep = File.separator;
|
String sep = File.separator;
|
||||||
|
|
|
@ -44,8 +44,6 @@ public class ManifestEntryVerifier {
|
||||||
|
|
||||||
private static final Debug debug = Debug.getInstance("jar");
|
private static final Debug debug = Debug.getInstance("jar");
|
||||||
|
|
||||||
private static final Provider digestProvider = Providers.getSunProvider();
|
|
||||||
|
|
||||||
/** the created digest objects */
|
/** the created digest objects */
|
||||||
HashMap<String, MessageDigest> createdDigests;
|
HashMap<String, MessageDigest> createdDigests;
|
||||||
|
|
||||||
|
@ -127,7 +125,7 @@ public class ManifestEntryVerifier {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
digest = MessageDigest.getInstance
|
digest = MessageDigest.getInstance
|
||||||
(algorithm, digestProvider);
|
(algorithm, Providers.getSunProvider());
|
||||||
createdDigests.put(algorithm, digest);
|
createdDigests.put(algorithm, digest);
|
||||||
} catch (NoSuchAlgorithmException nsae) {
|
} catch (NoSuchAlgorithmException nsae) {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
|
@ -312,6 +312,38 @@ findEND(jzfile *zip, void *endbuf)
|
||||||
return -1; /* END header not found */
|
return -1; /* END header not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Searches for the ZIP64 end of central directory (END) header. The
|
||||||
|
* contents of the ZIP64 END header will be read and placed in end64buf.
|
||||||
|
* Returns the file position of the ZIP64 END header, otherwise returns
|
||||||
|
* -1 if the END header was not found or an error occurred.
|
||||||
|
*
|
||||||
|
* The ZIP format specifies the "position" of each related record as
|
||||||
|
* ...
|
||||||
|
* [central directory]
|
||||||
|
* [zip64 end of central directory record]
|
||||||
|
* [zip64 end of central directory locator]
|
||||||
|
* [end of central directory record]
|
||||||
|
*
|
||||||
|
* The offset of zip64 end locator can be calculated from endpos as
|
||||||
|
* "endpos - ZIP64_LOCHDR".
|
||||||
|
* The "offset" of zip64 end record is stored in zip64 end locator.
|
||||||
|
*/
|
||||||
|
static jlong
|
||||||
|
findEND64(jzfile *zip, void *end64buf, jlong endpos)
|
||||||
|
{
|
||||||
|
char loc64[ZIP64_LOCHDR];
|
||||||
|
jlong end64pos;
|
||||||
|
if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
|
||||||
|
return -1; // end64 locator not found
|
||||||
|
}
|
||||||
|
end64pos = ZIP64_LOCOFF(loc64);
|
||||||
|
if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) {
|
||||||
|
return -1; // end64 record not found
|
||||||
|
}
|
||||||
|
return end64pos;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a hash code value for a C-style NUL-terminated string.
|
* Returns a hash code value for a C-style NUL-terminated string.
|
||||||
*/
|
*/
|
||||||
|
@ -463,7 +495,7 @@ static jlong
|
||||||
readCEN(jzfile *zip, jint knownTotal)
|
readCEN(jzfile *zip, jint knownTotal)
|
||||||
{
|
{
|
||||||
/* Following are unsigned 32-bit */
|
/* Following are unsigned 32-bit */
|
||||||
jlong endpos, cenpos, cenlen;
|
jlong endpos, end64pos, cenpos, cenlen, cenoff;
|
||||||
/* Following are unsigned 16-bit */
|
/* Following are unsigned 16-bit */
|
||||||
jint total, tablelen, i, j;
|
jint total, tablelen, i, j;
|
||||||
unsigned char *cenbuf = NULL;
|
unsigned char *cenbuf = NULL;
|
||||||
|
@ -474,6 +506,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||||
jlong offset;
|
jlong offset;
|
||||||
#endif
|
#endif
|
||||||
unsigned char endbuf[ENDHDR];
|
unsigned char endbuf[ENDHDR];
|
||||||
|
jint endhdrlen = ENDHDR;
|
||||||
jzcell *entries;
|
jzcell *entries;
|
||||||
jint *table;
|
jint *table;
|
||||||
|
|
||||||
|
@ -490,13 +523,27 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||||
|
|
||||||
/* Get position and length of central directory */
|
/* Get position and length of central directory */
|
||||||
cenlen = ENDSIZ(endbuf);
|
cenlen = ENDSIZ(endbuf);
|
||||||
|
cenoff = ENDOFF(endbuf);
|
||||||
|
total = ENDTOT(endbuf);
|
||||||
|
if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
|
||||||
|
total == ZIP64_MAGICCOUNT) {
|
||||||
|
unsigned char end64buf[ZIP64_ENDHDR];
|
||||||
|
if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
|
||||||
|
cenlen = ZIP64_ENDSIZ(end64buf);
|
||||||
|
cenoff = ZIP64_ENDOFF(end64buf);
|
||||||
|
total = (jint)ZIP64_ENDTOT(end64buf);
|
||||||
|
endpos = end64pos;
|
||||||
|
endhdrlen = ZIP64_ENDHDR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cenlen > endpos)
|
if (cenlen > endpos)
|
||||||
ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
|
ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
|
||||||
cenpos = endpos - cenlen;
|
cenpos = endpos - cenlen;
|
||||||
|
|
||||||
/* Get position of first local file (LOC) header, taking into
|
/* Get position of first local file (LOC) header, taking into
|
||||||
* account that there may be a stub prefixed to the zip file. */
|
* account that there may be a stub prefixed to the zip file. */
|
||||||
zip->locpos = cenpos - ENDOFF(endbuf);
|
zip->locpos = cenpos - cenoff;
|
||||||
if (zip->locpos < 0)
|
if (zip->locpos < 0)
|
||||||
ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
|
ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
|
||||||
|
|
||||||
|
@ -527,7 +574,7 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||||
out the page size in order to make offset to be multiples of
|
out the page size in order to make offset to be multiples of
|
||||||
page size.
|
page size.
|
||||||
*/
|
*/
|
||||||
zip->mlen = cenpos - offset + cenlen + ENDHDR;
|
zip->mlen = cenpos - offset + cenlen + endhdrlen;
|
||||||
zip->offset = offset;
|
zip->offset = offset;
|
||||||
mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
|
mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
|
||||||
zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
|
zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
|
||||||
|
@ -551,8 +598,13 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||||
* is a 2-byte field, but we (and other zip implementations)
|
* is a 2-byte field, but we (and other zip implementations)
|
||||||
* support approx. 2**31 entries, we do not trust ENDTOT, but
|
* support approx. 2**31 entries, we do not trust ENDTOT, but
|
||||||
* treat it only as a strong hint. When we call ourselves
|
* treat it only as a strong hint. When we call ourselves
|
||||||
* recursively, knownTotal will have the "true" value. */
|
* recursively, knownTotal will have the "true" value.
|
||||||
total = (knownTotal != -1) ? knownTotal : ENDTOT(endbuf);
|
*
|
||||||
|
* Keep this path alive even with the Zip64 END support added, just
|
||||||
|
* for zip files that have more than 0xffff entries but don't have
|
||||||
|
* the Zip64 enabled.
|
||||||
|
*/
|
||||||
|
total = (knownTotal != -1) ? knownTotal : total;
|
||||||
entries = zip->entries = calloc(total, sizeof(entries[0]));
|
entries = zip->entries = calloc(total, sizeof(entries[0]));
|
||||||
tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
|
tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
|
||||||
table = zip->table = malloc(tablelen * sizeof(table[0]));
|
table = zip->table = malloc(tablelen * sizeof(table[0]));
|
||||||
|
@ -854,6 +906,7 @@ typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
|
||||||
static jzentry *
|
static jzentry *
|
||||||
newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
|
newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
|
||||||
{
|
{
|
||||||
|
jlong locoff;
|
||||||
jint nlen, elen, clen;
|
jint nlen, elen, clen;
|
||||||
jzentry *ze;
|
jzentry *ze;
|
||||||
char *cen;
|
char *cen;
|
||||||
|
@ -880,18 +933,55 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
|
||||||
ze->size = CENLEN(cen);
|
ze->size = CENLEN(cen);
|
||||||
ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
|
ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
|
||||||
ze->crc = CENCRC(cen);
|
ze->crc = CENCRC(cen);
|
||||||
ze->pos = -(zip->locpos + CENOFF(cen));
|
locoff = CENOFF(cen);
|
||||||
|
ze->pos = -(zip->locpos + locoff);
|
||||||
|
|
||||||
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
|
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
|
||||||
memcpy(ze->name, cen + CENHDR, nlen);
|
memcpy(ze->name, cen + CENHDR, nlen);
|
||||||
ze->name[nlen] = '\0';
|
ze->name[nlen] = '\0';
|
||||||
|
|
||||||
if (elen > 0) {
|
if (elen > 0) {
|
||||||
|
char *extra = cen + CENHDR + nlen;
|
||||||
|
|
||||||
/* This entry has "extra" data */
|
/* This entry has "extra" data */
|
||||||
if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
|
if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
|
||||||
ze->extra[0] = (unsigned char) elen;
|
ze->extra[0] = (unsigned char) elen;
|
||||||
ze->extra[1] = (unsigned char) (elen >> 8);
|
ze->extra[1] = (unsigned char) (elen >> 8);
|
||||||
memcpy(ze->extra+2, cen + CENHDR + nlen, elen);
|
memcpy(ze->extra+2, extra, elen);
|
||||||
|
if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
|
||||||
|
locoff == ZIP64_MAGICVAL) {
|
||||||
|
jint off = 0;
|
||||||
|
while ((off + 4) < elen) { // spec: HeaderID+DataSize+Data
|
||||||
|
jint sz = SH(extra, off + 2);
|
||||||
|
if (SH(extra, off) == ZIP64_EXTID) {
|
||||||
|
off += 4;
|
||||||
|
if (ze->size == ZIP64_MAGICVAL) {
|
||||||
|
// if invalid zip64 extra fields, just skip
|
||||||
|
if (sz < 8 || (off + 8) > elen)
|
||||||
|
break;
|
||||||
|
ze->size = LL(extra, off);
|
||||||
|
sz -= 8;
|
||||||
|
off += 8;
|
||||||
|
}
|
||||||
|
if (ze->csize == ZIP64_MAGICVAL) {
|
||||||
|
if (sz < 8 || (off + 8) > elen)
|
||||||
|
break;
|
||||||
|
ze->csize = LL(extra, off);
|
||||||
|
sz -= 8;
|
||||||
|
off += 8;
|
||||||
|
}
|
||||||
|
if (locoff == ZIP64_MAGICVAL) {
|
||||||
|
if (sz < 8 || (off + 8) > elen)
|
||||||
|
break;
|
||||||
|
ze->pos = -(zip->locpos + LL(extra, off));
|
||||||
|
sz -= 8;
|
||||||
|
off += 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
off += (sz + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clen > 0) {
|
if (clen > 0) {
|
||||||
|
|
|
@ -38,9 +38,13 @@
|
||||||
#define CENSIG 0x02014b50L /* "PK\001\002" */
|
#define CENSIG 0x02014b50L /* "PK\001\002" */
|
||||||
#define ENDSIG 0x06054b50L /* "PK\005\006" */
|
#define ENDSIG 0x06054b50L /* "PK\005\006" */
|
||||||
|
|
||||||
|
#define ZIP64_ENDSIG 0x06064b50L /* "PK\006\006" */
|
||||||
|
#define ZIP64_LOCSIG 0x07064b50L /* "PK\006\007" */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header sizes including signatures
|
* Header sizes including signatures
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_MMAP
|
#ifdef USE_MMAP
|
||||||
#define SIGSIZ 4
|
#define SIGSIZ 4
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,12 +53,22 @@
|
||||||
#define CENHDR 46
|
#define CENHDR 46
|
||||||
#define ENDHDR 22
|
#define ENDHDR 22
|
||||||
|
|
||||||
|
#define ZIP64_ENDHDR 56 // ZIP64 end header size
|
||||||
|
#define ZIP64_LOCHDR 20 // ZIP64 end loc header size
|
||||||
|
#define ZIP64_EXTHDR 24 // EXT header size
|
||||||
|
#define ZIP64_EXTID 1 // Extra field Zip64 header ID
|
||||||
|
|
||||||
|
#define ZIP64_MAGICVAL 0xffffffffLL
|
||||||
|
#define ZIP64_MAGICCOUNT 0xffff
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header field access macros
|
* Header field access macros
|
||||||
*/
|
*/
|
||||||
#define CH(b, n) (((unsigned char *)(b))[n])
|
#define CH(b, n) (((unsigned char *)(b))[n])
|
||||||
#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
|
#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
|
||||||
#define LG(b, n) (SH(b, n) | (SH(b, n+2) << 16))
|
#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL)
|
||||||
|
#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32))
|
||||||
#define GETSIG(b) LG(b, 0)
|
#define GETSIG(b) LG(b, 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -105,6 +119,26 @@
|
||||||
#define ENDOFF(b) LG(b, 16) /* central directory offset */
|
#define ENDOFF(b) LG(b, 16) /* central directory offset */
|
||||||
#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
|
#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for getting Zip64 end of central directory header fields
|
||||||
|
*/
|
||||||
|
#define ZIP64_ENDLEN(b) LL(b, 4) /* size of zip64 end of central dir */
|
||||||
|
#define ZIP64_ENDVEM(b) SH(b, 12) /* version made by */
|
||||||
|
#define ZIP64_ENDVER(b) SH(b, 14) /* version needed to extract */
|
||||||
|
#define ZIP64_ENDNMD(b) LG(b, 16) /* number of this disk */
|
||||||
|
#define ZIP64_ENDDSK(b) LG(b, 20) /* disk number of start */
|
||||||
|
#define ZIP64_ENDTOD(b) LL(b, 24) /* total number of entries on this disk */
|
||||||
|
#define ZIP64_ENDTOT(b) LL(b, 32) /* total number of entries */
|
||||||
|
#define ZIP64_ENDSIZ(b) LL(b, 40) /* central directory size in bytes */
|
||||||
|
#define ZIP64_ENDOFF(b) LL(b, 48) /* offset of first CEN header */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros for getting Zip64 end of central directory locator fields
|
||||||
|
*/
|
||||||
|
#define ZIP64_LOCDSK(b) LG(b, 4) /* disk number start */
|
||||||
|
#define ZIP64_LOCOFF(b) LL(b, 8) /* offset of zip64 end */
|
||||||
|
#define ZIP64_LOCTOT(b) LG(b, 16) /* total number of disks */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Supported compression methods
|
* Supported compression methods
|
||||||
*/
|
*/
|
||||||
|
@ -145,7 +179,7 @@ typedef struct jzentry { /* Zip file entry */
|
||||||
*/
|
*/
|
||||||
typedef struct jzcell {
|
typedef struct jzcell {
|
||||||
unsigned int hash; /* 32 bit hashcode on name */
|
unsigned int hash; /* 32 bit hashcode on name */
|
||||||
unsigned int cenpos; /* Offset of central directory file header */
|
jlong cenpos; /* Offset of central directory file header */
|
||||||
unsigned int next; /* hash chain: index into jzfile->entries */
|
unsigned int next; /* hash chain: index into jzfile->entries */
|
||||||
} jzcell;
|
} jzcell;
|
||||||
|
|
||||||
|
|
|
@ -106,11 +106,11 @@ struct internal_state;
|
||||||
typedef struct z_stream_s {
|
typedef struct z_stream_s {
|
||||||
Bytef *next_in; /* next input byte */
|
Bytef *next_in; /* next input byte */
|
||||||
uInt avail_in; /* number of bytes available at next_in */
|
uInt avail_in; /* number of bytes available at next_in */
|
||||||
uLong total_in; /* total nb of input bytes read so far */
|
long long total_in; /* total nb of input bytes read so far */
|
||||||
|
|
||||||
Bytef *next_out; /* next output byte should be put there */
|
Bytef *next_out; /* next output byte should be put there */
|
||||||
uInt avail_out; /* remaining free space at next_out */
|
uInt avail_out; /* remaining free space at next_out */
|
||||||
uLong total_out; /* total nb of bytes output so far */
|
long long total_out; /* total nb of bytes output so far */
|
||||||
|
|
||||||
char *msg; /* last error message, NULL if no error */
|
char *msg; /* last error message, NULL if no error */
|
||||||
struct internal_state FAR *state; /* not visible by applications */
|
struct internal_state FAR *state; /* not visible by applications */
|
||||||
|
|
|
@ -78,8 +78,8 @@ class EPollArrayWrapper {
|
||||||
// Base address of the native pollArray
|
// Base address of the native pollArray
|
||||||
private final long pollArrayAddress;
|
private final long pollArrayAddress;
|
||||||
|
|
||||||
// Set of "idle" file descriptors
|
// Set of "idle" channels
|
||||||
private final HashSet<Integer> idleSet;
|
private final HashSet<SelChImpl> idleSet;
|
||||||
|
|
||||||
EPollArrayWrapper() {
|
EPollArrayWrapper() {
|
||||||
// creates the epoll file descriptor
|
// creates the epoll file descriptor
|
||||||
|
@ -96,19 +96,22 @@ class EPollArrayWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create idle set
|
// create idle set
|
||||||
idleSet = new HashSet<Integer>();
|
idleSet = new HashSet<SelChImpl>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to update file description registrations
|
// Used to update file description registrations
|
||||||
private static class Updator {
|
private static class Updator {
|
||||||
|
SelChImpl channel;
|
||||||
int opcode;
|
int opcode;
|
||||||
int fd;
|
|
||||||
int events;
|
int events;
|
||||||
Updator(int opcode, int fd, int events) {
|
Updator(SelChImpl channel, int opcode, int events) {
|
||||||
|
this.channel = channel;
|
||||||
this.opcode = opcode;
|
this.opcode = opcode;
|
||||||
this.fd = fd;
|
|
||||||
this.events = events;
|
this.events = events;
|
||||||
}
|
}
|
||||||
|
Updator(SelChImpl channel, int opcode) {
|
||||||
|
this(channel, opcode, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedList<Updator> updateList = new LinkedList<Updator>();
|
private LinkedList<Updator> updateList = new LinkedList<Updator>();
|
||||||
|
@ -163,60 +166,54 @@ class EPollArrayWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the events for a given file descriptor.
|
* Update the events for a given channel.
|
||||||
*/
|
*/
|
||||||
void setInterest(int fd, int mask) {
|
void setInterest(SelChImpl channel, int mask) {
|
||||||
synchronized (updateList) {
|
synchronized (updateList) {
|
||||||
|
|
||||||
// if the interest events are 0 then add to idle set, and delete
|
|
||||||
// from epoll if registered (or pending)
|
|
||||||
if (mask == 0) {
|
|
||||||
if (idleSet.add(fd)) {
|
|
||||||
updateList.add(new Updator(EPOLL_CTL_DEL, fd, 0));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if file descriptor is idle then add to epoll
|
|
||||||
if (!idleSet.isEmpty() && idleSet.remove(fd)) {
|
|
||||||
updateList.add(new Updator(EPOLL_CTL_ADD, fd, mask));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the previous pending operation is to add this file descriptor
|
// if the previous pending operation is to add this file descriptor
|
||||||
// to epoll then update its event set
|
// to epoll then update its event set
|
||||||
if (updateList.size() > 0) {
|
if (updateList.size() > 0) {
|
||||||
Updator last = updateList.getLast();
|
Updator last = updateList.getLast();
|
||||||
if (last.fd == fd && last.opcode == EPOLL_CTL_ADD) {
|
if (last.channel == channel && last.opcode == EPOLL_CTL_ADD) {
|
||||||
last.events = mask;
|
last.events = mask;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update existing registration
|
// update existing registration
|
||||||
updateList.add(new Updator(EPOLL_CTL_MOD, fd, mask));
|
updateList.add(new Updator(channel, EPOLL_CTL_MOD, mask));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new file descriptor to epoll
|
* Add a channel's file descriptor to epoll
|
||||||
*/
|
*/
|
||||||
void add(int fd) {
|
void add(SelChImpl channel) {
|
||||||
synchronized (updateList) {
|
synchronized (updateList) {
|
||||||
updateList.add(new Updator(EPOLL_CTL_ADD, fd, 0));
|
updateList.add(new Updator(channel, EPOLL_CTL_ADD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a file descriptor from epoll
|
* Remove a channel's file descriptor from epoll
|
||||||
*/
|
*/
|
||||||
void release(int fd) {
|
void release(SelChImpl channel) {
|
||||||
synchronized (updateList) {
|
synchronized (updateList) {
|
||||||
// if file descriptor is idle then remove from idle set, otherwise
|
// flush any pending updates
|
||||||
// delete from epoll
|
int i = 0;
|
||||||
if (!idleSet.remove(fd)) {
|
while (i < updateList.size()) {
|
||||||
updateList.add(new Updator(EPOLL_CTL_DEL, fd, 0));
|
if (updateList.get(i).channel == channel) {
|
||||||
|
updateList.remove(i);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove from the idle set (if present)
|
||||||
|
idleSet.remove(channel);
|
||||||
|
|
||||||
|
// remove from epoll (if registered)
|
||||||
|
epollCtl(epfd, EPOLL_CTL_DEL, channel.getFDVal(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +245,26 @@ class EPollArrayWrapper {
|
||||||
synchronized (updateList) {
|
synchronized (updateList) {
|
||||||
Updator u = null;
|
Updator u = null;
|
||||||
while ((u = updateList.poll()) != null) {
|
while ((u = updateList.poll()) != null) {
|
||||||
epollCtl(epfd, u.opcode, u.fd, u.events);
|
SelChImpl ch = u.channel;
|
||||||
|
if (!ch.isOpen())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if the events are 0 then file descriptor is put into "idle
|
||||||
|
// set" to prevent it being polled
|
||||||
|
if (u.events == 0) {
|
||||||
|
boolean added = idleSet.add(u.channel);
|
||||||
|
// if added to idle set then remove from epoll if registered
|
||||||
|
if (added && (u.opcode == EPOLL_CTL_MOD))
|
||||||
|
epollCtl(epfd, EPOLL_CTL_DEL, ch.getFDVal(), 0);
|
||||||
|
} else {
|
||||||
|
// events are specified. If file descriptor was in idle set
|
||||||
|
// it must be re-registered (by converting opcode to ADD)
|
||||||
|
boolean idle = false;
|
||||||
|
if (!idleSet.isEmpty())
|
||||||
|
idle = idleSet.remove(u.channel);
|
||||||
|
int opcode = (idle) ? EPOLL_CTL_ADD : u.opcode;
|
||||||
|
epollCtl(epfd, opcode, ch.getFDVal(), u.events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,6 @@ class EPollSelectorImpl
|
||||||
FileDispatcherImpl.closeIntFD(fd0);
|
FileDispatcherImpl.closeIntFD(fd0);
|
||||||
FileDispatcherImpl.closeIntFD(fd1);
|
FileDispatcherImpl.closeIntFD(fd1);
|
||||||
|
|
||||||
pollWrapper.release(fd0);
|
|
||||||
pollWrapper.closeEPollFD();
|
pollWrapper.closeEPollFD();
|
||||||
// it is possible
|
// it is possible
|
||||||
selectedKeys = null;
|
selectedKeys = null;
|
||||||
|
@ -162,17 +161,18 @@ class EPollSelectorImpl
|
||||||
protected void implRegister(SelectionKeyImpl ski) {
|
protected void implRegister(SelectionKeyImpl ski) {
|
||||||
if (closed)
|
if (closed)
|
||||||
throw new ClosedSelectorException();
|
throw new ClosedSelectorException();
|
||||||
int fd = IOUtil.fdVal(ski.channel.getFD());
|
SelChImpl ch = ski.channel;
|
||||||
fdToKey.put(Integer.valueOf(fd), ski);
|
fdToKey.put(Integer.valueOf(ch.getFDVal()), ski);
|
||||||
pollWrapper.add(fd);
|
pollWrapper.add(ch);
|
||||||
keys.add(ski);
|
keys.add(ski);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||||
assert (ski.getIndex() >= 0);
|
assert (ski.getIndex() >= 0);
|
||||||
int fd = ski.channel.getFDVal();
|
SelChImpl ch = ski.channel;
|
||||||
|
int fd = ch.getFDVal();
|
||||||
fdToKey.remove(Integer.valueOf(fd));
|
fdToKey.remove(Integer.valueOf(fd));
|
||||||
pollWrapper.release(fd);
|
pollWrapper.release(ch);
|
||||||
ski.setIndex(-1);
|
ski.setIndex(-1);
|
||||||
keys.remove(ski);
|
keys.remove(ski);
|
||||||
selectedKeys.remove(ski);
|
selectedKeys.remove(ski);
|
||||||
|
@ -185,8 +185,7 @@ class EPollSelectorImpl
|
||||||
void putEventOps(SelectionKeyImpl sk, int ops) {
|
void putEventOps(SelectionKeyImpl sk, int ops) {
|
||||||
if (closed)
|
if (closed)
|
||||||
throw new ClosedSelectorException();
|
throw new ClosedSelectorException();
|
||||||
int fd = IOUtil.fdVal(sk.channel.getFD());
|
pollWrapper.setInterest(sk.channel, ops);
|
||||||
pollWrapper.setInterest(fd, ops);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Selector wakeup() {
|
public Selector wakeup() {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "jlong.h"
|
#include "jlong.h"
|
||||||
#include "sun_nio_ch_DevPollArrayWrapper.h"
|
#include "sun_nio_ch_DevPollArrayWrapper.h"
|
||||||
|
#include "java_lang_Integer.h"
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -192,7 +193,11 @@ Java_sun_nio_ch_DevPollArrayWrapper_fdLimit(JNIEnv *env, jclass this)
|
||||||
JNU_ThrowIOExceptionWithLastError(env,
|
JNU_ThrowIOExceptionWithLastError(env,
|
||||||
"getrlimit failed");
|
"getrlimit failed");
|
||||||
}
|
}
|
||||||
return (jint)rlp.rlim_max;
|
if (rlp.rlim_max < 0 || rlp.rlim_max > java_lang_Integer_MAX_VALUE) {
|
||||||
|
return java_lang_Integer_MAX_VALUE;
|
||||||
|
} else {
|
||||||
|
return (jint)rlp.rlim_max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
|
|
|
@ -309,12 +309,13 @@ Java_java_io_WinNTFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
|
||||||
/* No template file */
|
/* No template file */
|
||||||
NULL);
|
NULL);
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
GetFileTime(h, NULL, NULL, &t);
|
if (GetFileTime(h, NULL, NULL, &t)) {
|
||||||
|
modTime.LowPart = (DWORD) t.dwLowDateTime;
|
||||||
|
modTime.HighPart = (LONG) t.dwHighDateTime;
|
||||||
|
rv = modTime.QuadPart / 10000;
|
||||||
|
rv -= 11644473600000;
|
||||||
|
}
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
modTime.LowPart = (DWORD) t.dwLowDateTime;
|
|
||||||
modTime.HighPart = (LONG) t.dwHighDateTime;
|
|
||||||
rv = modTime.QuadPart / 10000;
|
|
||||||
rv -= 11644473600000;
|
|
||||||
}
|
}
|
||||||
free(pathbuf);
|
free(pathbuf);
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -717,6 +717,7 @@ GetJavaProperties(JNIEnv* env)
|
||||||
* Windows Vista family 6 0
|
* Windows Vista family 6 0
|
||||||
* Windows 2008 6 0
|
* Windows 2008 6 0
|
||||||
* where ((&ver.wServicePackMinor) + 2) = 1
|
* where ((&ver.wServicePackMinor) + 2) = 1
|
||||||
|
* Windows 7 6 1
|
||||||
*
|
*
|
||||||
* This mapping will presumably be augmented as new Windows
|
* This mapping will presumably be augmented as new Windows
|
||||||
* versions are released.
|
* versions are released.
|
||||||
|
@ -773,13 +774,18 @@ GetJavaProperties(JNIEnv* env)
|
||||||
* and Windows Vista are identical, you must also test
|
* and Windows Vista are identical, you must also test
|
||||||
* whether the wProductType member is VER_NT_WORKSTATION.
|
* whether the wProductType member is VER_NT_WORKSTATION.
|
||||||
* If wProductType is VER_NT_WORKSTATION, the operating
|
* If wProductType is VER_NT_WORKSTATION, the operating
|
||||||
* system is Windows Vista; otherwise, it is Windows
|
* system is Windows Vista or 7; otherwise, it is Windows
|
||||||
* Server 2008."
|
* Server 2008."
|
||||||
*/
|
*/
|
||||||
if (ver.wProductType == VER_NT_WORKSTATION)
|
if (ver.wProductType == VER_NT_WORKSTATION) {
|
||||||
sprops.os_name = "Windows Vista";
|
switch (ver.dwMinorVersion) {
|
||||||
else
|
case 0: sprops.os_name = "Windows Vista"; break;
|
||||||
|
case 1: sprops.os_name = "Windows 7"; break;
|
||||||
|
default: sprops.os_name = "Windows NT (unknown)";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
sprops.os_name = "Windows Server 2008";
|
sprops.os_name = "Windows Server 2008";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sprops.os_name = "Windows NT (unknown)";
|
sprops.os_name = "Windows NT (unknown)";
|
||||||
}
|
}
|
||||||
|
|
55
jdk/test/java/lang/Integer/ValueOf.java
Normal file
55
jdk/test/java/lang/Integer/ValueOf.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 6807702
|
||||||
|
* @summary Basic test for Integer.valueOf
|
||||||
|
* @run main ValueOf
|
||||||
|
* @run main/othervm -esa -XX:+AggressiveOpts ValueOf
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ValueOf {
|
||||||
|
|
||||||
|
// test Integer.valueOf over this range (inclusive)
|
||||||
|
private static final int TEST_LOW = -1024;
|
||||||
|
private static final int TEST_HIGH = 24576;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int i = TEST_LOW;
|
||||||
|
while (i <= TEST_HIGH) {
|
||||||
|
// check that valueOf stores i
|
||||||
|
if (Integer.valueOf(i).intValue() != i)
|
||||||
|
throw new RuntimeException();
|
||||||
|
|
||||||
|
// check that the same object is returned for integral values
|
||||||
|
// in the range -128 to 127 (inclusive)
|
||||||
|
if (i >= -128 && i <= 127) {
|
||||||
|
if (Integer.valueOf(i) != Integer.valueOf(i))
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,27 +22,110 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4512723
|
* @bug 4512723 6621689
|
||||||
* @summary Unit test for datagram-socket-channel adaptors
|
* @summary Test that connect/send/receive with unbound DatagramChannel causes
|
||||||
|
* the channel's socket to be bound to a local address
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.*;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
class NotBound {
|
public class NotBound {
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
test1(false);
|
static void checkBound(DatagramChannel dc) throws IOException {
|
||||||
test1(true);
|
if (dc.getLocalAddress() == null)
|
||||||
|
throw new RuntimeException("Not bound??");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test1(boolean blocking) throws Exception {
|
// starts a thread to send a datagram to the given channel once the channel
|
||||||
ByteBuffer bb = ByteBuffer.allocateDirect(256);
|
// is bound to a local address
|
||||||
DatagramChannel dc1 = DatagramChannel.open();
|
static void wakeupWhenBound(final DatagramChannel dc) {
|
||||||
dc1.configureBlocking(false);
|
Runnable wakeupTask = new Runnable() {
|
||||||
SocketAddress isa = dc1.receive(bb);
|
public void run() {
|
||||||
if (isa != null)
|
try {
|
||||||
throw new Exception("Unbound dc returned non-null");
|
// poll for local address
|
||||||
dc1.close();
|
InetSocketAddress local;
|
||||||
|
do {
|
||||||
|
Thread.sleep(50);
|
||||||
|
local = (InetSocketAddress)dc.getLocalAddress();
|
||||||
|
} while (local == null);
|
||||||
|
|
||||||
|
// send message to channel to wakeup receiver
|
||||||
|
DatagramChannel sender = DatagramChannel.open();
|
||||||
|
try {
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap("hello".getBytes());
|
||||||
|
InetAddress lh = InetAddress.getLocalHost();
|
||||||
|
SocketAddress target =
|
||||||
|
new InetSocketAddress(lh, local.getPort());
|
||||||
|
sender.send(bb, target);
|
||||||
|
} finally {
|
||||||
|
sender.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception x) {
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
new Thread(wakeupTask).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
DatagramChannel dc;
|
||||||
|
|
||||||
|
// connect
|
||||||
|
dc = DatagramChannel.open();
|
||||||
|
try {
|
||||||
|
DatagramChannel peer = DatagramChannel.open()
|
||||||
|
.bind(new InetSocketAddress(0));
|
||||||
|
int peerPort = ((InetSocketAddress)(peer.getLocalAddress())).getPort();
|
||||||
|
try {
|
||||||
|
dc.connect(new InetSocketAddress(InetAddress.getLocalHost(), peerPort));
|
||||||
|
checkBound(dc);
|
||||||
|
} finally {
|
||||||
|
peer.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
dc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// send
|
||||||
|
dc = DatagramChannel.open();
|
||||||
|
try {
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap("ignore this".getBytes());
|
||||||
|
SocketAddress target =
|
||||||
|
new InetSocketAddress(InetAddress.getLocalHost(), 5000);
|
||||||
|
dc.send(bb, target);
|
||||||
|
checkBound(dc);
|
||||||
|
} finally {
|
||||||
|
dc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive (blocking)
|
||||||
|
dc = DatagramChannel.open();
|
||||||
|
try {
|
||||||
|
ByteBuffer bb = ByteBuffer.allocateDirect(128);
|
||||||
|
wakeupWhenBound(dc);
|
||||||
|
SocketAddress sender = dc.receive(bb);
|
||||||
|
if (sender == null)
|
||||||
|
throw new RuntimeException("Sender should not be null");
|
||||||
|
checkBound(dc);
|
||||||
|
} finally {
|
||||||
|
dc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive (non-blocking)
|
||||||
|
dc = DatagramChannel.open();
|
||||||
|
try {
|
||||||
|
dc.configureBlocking(false);
|
||||||
|
ByteBuffer bb = ByteBuffer.allocateDirect(128);
|
||||||
|
SocketAddress sender = dc.receive(bb);
|
||||||
|
if (sender != null)
|
||||||
|
throw new RuntimeException("Sender should be null");
|
||||||
|
checkBound(dc);
|
||||||
|
} finally {
|
||||||
|
dc.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
127
jdk/test/java/nio/channels/Selector/RegAfterPreClose.java
Normal file
127
jdk/test/java/nio/channels/Selector/RegAfterPreClose.java
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @test
|
||||||
|
* @bug 6693490
|
||||||
|
* @summary Pre-close file descriptor may inadvertently get registered with
|
||||||
|
* epoll during close
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.channels.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RegAfterPreClose {
|
||||||
|
|
||||||
|
static volatile boolean done;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that continuously connects to a given address and immediately
|
||||||
|
* closes the connection.
|
||||||
|
*/
|
||||||
|
static class Connector implements Runnable {
|
||||||
|
private final SocketAddress sa;
|
||||||
|
Connector(int port) throws IOException {
|
||||||
|
InetAddress lh = InetAddress.getLocalHost();
|
||||||
|
this.sa = new InetSocketAddress(lh, port);
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
while (!done) {
|
||||||
|
try {
|
||||||
|
SocketChannel.open(sa).close();
|
||||||
|
} catch (IOException x) {
|
||||||
|
// back-off as probably resource related
|
||||||
|
try {
|
||||||
|
Thread.sleep(10);
|
||||||
|
} catch (InterruptedException ignore) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that closes a channel.
|
||||||
|
*/
|
||||||
|
static class Closer implements Runnable {
|
||||||
|
private final Channel channel;
|
||||||
|
Closer(Channel sc) {
|
||||||
|
this.channel = sc;
|
||||||
|
}
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
channel.close();
|
||||||
|
} catch (IOException ignore) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// create listener
|
||||||
|
InetSocketAddress isa = new InetSocketAddress(0);
|
||||||
|
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||||
|
ssc.socket().bind(isa);
|
||||||
|
|
||||||
|
// register with Selector
|
||||||
|
final Selector sel = Selector.open();
|
||||||
|
ssc.configureBlocking(false);
|
||||||
|
SelectionKey key = ssc.register(sel, SelectionKey.OP_ACCEPT);
|
||||||
|
|
||||||
|
ThreadFactory factory = new ThreadFactory() {
|
||||||
|
@Override
|
||||||
|
public Thread newThread(Runnable r) {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// schedule test to run for 1 minute
|
||||||
|
Executors.newScheduledThreadPool(1, factory).schedule(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
done = true;
|
||||||
|
sel.wakeup();
|
||||||
|
}}, 1, TimeUnit.MINUTES);
|
||||||
|
|
||||||
|
// create Executor that handles tasks that closes channels
|
||||||
|
// "asynchronously" - this creates the conditions to provoke the bug.
|
||||||
|
Executor executor = Executors.newFixedThreadPool(2, factory);
|
||||||
|
|
||||||
|
// submit task that connects to listener
|
||||||
|
executor.execute(new Connector(ssc.socket().getLocalPort()));
|
||||||
|
|
||||||
|
// loop accepting connections until done (or an IOException is thrown)
|
||||||
|
while (!done) {
|
||||||
|
sel.select();
|
||||||
|
if (key.isAcceptable()) {
|
||||||
|
SocketChannel sc = ssc.accept();
|
||||||
|
if (sc != null) {
|
||||||
|
sc.configureBlocking(false);
|
||||||
|
sc.register(sel, SelectionKey.OP_READ);
|
||||||
|
executor.execute(new Closer(sc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sel.selectedKeys().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -555,6 +555,7 @@ public class MOAT {
|
||||||
|
|
||||||
NavigableMap<Integer,Integer> nm =
|
NavigableMap<Integer,Integer> nm =
|
||||||
(NavigableMap<Integer,Integer>) m;
|
(NavigableMap<Integer,Integer>) m;
|
||||||
|
testNavigableMapRemovers(nm);
|
||||||
testNavigableMap(nm);
|
testNavigableMap(nm);
|
||||||
testNavigableMap(nm.headMap(6, false));
|
testNavigableMap(nm.headMap(6, false));
|
||||||
testNavigableMap(nm.headMap(5, true));
|
testNavigableMap(nm.headMap(5, true));
|
||||||
|
@ -742,6 +743,97 @@ public class MOAT {
|
||||||
equal(it.next(), expected);
|
equal(it.next(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void equalMaps(Map m1, Map m2) {
|
||||||
|
equal(m1, m2);
|
||||||
|
equal(m2, m1);
|
||||||
|
equal(m1.size(), m2.size());
|
||||||
|
equal(m1.isEmpty(), m2.isEmpty());
|
||||||
|
equal(m1.toString(), m2.toString());
|
||||||
|
check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
static void testNavigableMapRemovers(NavigableMap m)
|
||||||
|
{
|
||||||
|
final Map emptyMap = new HashMap();
|
||||||
|
|
||||||
|
final Map singletonMap = new HashMap();
|
||||||
|
singletonMap.put(1, 2);
|
||||||
|
|
||||||
|
abstract class NavigableMapView {
|
||||||
|
abstract NavigableMap view(NavigableMap m);
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigableMapView[] views = {
|
||||||
|
new NavigableMapView() { NavigableMap view(NavigableMap m) {
|
||||||
|
return m; }},
|
||||||
|
new NavigableMapView() { NavigableMap view(NavigableMap m) {
|
||||||
|
return m.headMap(99, true); }},
|
||||||
|
new NavigableMapView() { NavigableMap view(NavigableMap m) {
|
||||||
|
return m.tailMap(-99, false); }},
|
||||||
|
new NavigableMapView() { NavigableMap view(NavigableMap m) {
|
||||||
|
return m.subMap(-99, true, 99, false); }},
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract class Remover {
|
||||||
|
abstract void remove(NavigableMap m, Object k, Object v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Remover[] removers = {
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.remove(k), v); }},
|
||||||
|
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.descendingMap().remove(k), v); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.descendingMap().headMap(-86, false).remove(k), v); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.descendingMap().tailMap(86, true).remove(k), v); }},
|
||||||
|
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.headMap(86, true).remove(k), v); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.tailMap(-86, true).remove(k), v); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
equal(m.subMap(-86, false, 86, true).remove(k), v); }},
|
||||||
|
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.keySet().remove(k)); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.navigableKeySet().remove(k)); }},
|
||||||
|
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.navigableKeySet().headSet(86, true).remove(k)); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.navigableKeySet().tailSet(-86, false).remove(k)); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.navigableKeySet().subSet(-86, true, 86, false)
|
||||||
|
.remove(k)); }},
|
||||||
|
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.descendingKeySet().headSet(-86, false).remove(k)); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.descendingKeySet().tailSet(86, true).remove(k)); }},
|
||||||
|
new Remover() { void remove(NavigableMap m, Object k, Object v) {
|
||||||
|
check(m.descendingKeySet().subSet(86, true, -86, false)
|
||||||
|
.remove(k)); }},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (NavigableMapView view : views) {
|
||||||
|
for (Remover remover : removers) {
|
||||||
|
try {
|
||||||
|
m.clear();
|
||||||
|
equalMaps(m, emptyMap);
|
||||||
|
equal(m.put(1, 2), null);
|
||||||
|
equalMaps(m, singletonMap);
|
||||||
|
NavigableMap v = view.view(m);
|
||||||
|
remover.remove(v, 1, 2);
|
||||||
|
equalMaps(m, emptyMap);
|
||||||
|
} catch (Throwable t) { unexpected(t); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void testNavigableMap(NavigableMap<Integer,Integer> m)
|
private static void testNavigableMap(NavigableMap<Integer,Integer> m)
|
||||||
{
|
{
|
||||||
clear(m);
|
clear(m);
|
||||||
|
|
116
jdk/test/java/util/concurrent/Semaphore/RacingReleases.java
Normal file
116
jdk/test/java/util/concurrent/Semaphore/RacingReleases.java
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is available under and governed by the GNU General Public
|
||||||
|
* License version 2 only, as published by the Free Software Foundation.
|
||||||
|
* However, the following notice accompanied the original version of this
|
||||||
|
* file:
|
||||||
|
*
|
||||||
|
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||||
|
* Expert Group and released to the public domain, as explained at
|
||||||
|
* http://creativecommons.org/licenses/publicdomain
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6801020 6803402
|
||||||
|
* @summary Try to tickle race conditions in
|
||||||
|
* AbstractQueuedSynchronizer "shared" code
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
public class RacingReleases {
|
||||||
|
|
||||||
|
/** Increase this for better chance of tickling races */
|
||||||
|
static final int iterations = 1000;
|
||||||
|
|
||||||
|
public static void test(final boolean fair,
|
||||||
|
final boolean interruptibly)
|
||||||
|
throws Throwable {
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
final Semaphore sem = new Semaphore(0, fair);
|
||||||
|
final Throwable[] badness = new Throwable[1];
|
||||||
|
Runnable blocker = interruptibly ?
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
sem.acquire();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
badness[0] = t;
|
||||||
|
throw new Error(t);
|
||||||
|
}}}
|
||||||
|
:
|
||||||
|
new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
sem.acquireUninterruptibly();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
badness[0] = t;
|
||||||
|
throw new Error(t);
|
||||||
|
}}};
|
||||||
|
|
||||||
|
Thread b1 = new Thread(blocker);
|
||||||
|
Thread b2 = new Thread(blocker);
|
||||||
|
Runnable signaller = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
sem.release();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
badness[0] = t;
|
||||||
|
throw new Error(t);
|
||||||
|
}}};
|
||||||
|
Thread s1 = new Thread(signaller);
|
||||||
|
Thread s2 = new Thread(signaller);
|
||||||
|
Thread[] threads = { b1, b2, s1, s2 };
|
||||||
|
java.util.Collections.shuffle(java.util.Arrays.asList(threads));
|
||||||
|
for (Thread thread : threads)
|
||||||
|
thread.start();
|
||||||
|
for (Thread thread : threads) {
|
||||||
|
thread.join(60 * 1000);
|
||||||
|
if (thread.isAlive())
|
||||||
|
throw new Error
|
||||||
|
(String.format
|
||||||
|
("Semaphore stuck: permits %d, thread waiting %s%n",
|
||||||
|
sem.availablePermits(),
|
||||||
|
sem.hasQueuedThreads() ? "true" : "false"));
|
||||||
|
}
|
||||||
|
if (badness[0] != null)
|
||||||
|
throw new Error(badness[0]);
|
||||||
|
if (sem.availablePermits() != 0)
|
||||||
|
throw new Error(String.valueOf(sem.availablePermits()));
|
||||||
|
if (sem.hasQueuedThreads())
|
||||||
|
throw new Error(String.valueOf(sem.hasQueuedThreads()));
|
||||||
|
if (sem.getQueueLength() != 0)
|
||||||
|
throw new Error(String.valueOf(sem.getQueueLength()));
|
||||||
|
if (sem.isFair() != fair)
|
||||||
|
throw new Error(String.valueOf(sem.isFair()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
for (boolean fair : new boolean[] { true, false })
|
||||||
|
for (boolean interruptibly : new boolean[] { true, false })
|
||||||
|
test(fair, interruptibly);
|
||||||
|
}
|
||||||
|
}
|
193
jdk/test/java/util/zip/LargeZip.java
Normal file
193
jdk/test/java/util/zip/LargeZip.java
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Sun designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Sun in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
|
public class LargeZip {
|
||||||
|
// If true, don't delete large ZIP file created for test.
|
||||||
|
static final boolean debug = System.getProperty("debug") != null;
|
||||||
|
|
||||||
|
//static final int DATA_LEN = 1024 * 1024;
|
||||||
|
static final int DATA_LEN = 80 * 1024;
|
||||||
|
static final int DATA_SIZE = 8;
|
||||||
|
|
||||||
|
static long fileSize = 6L * 1024L * 1024L * 1024L; // 6GB
|
||||||
|
|
||||||
|
static boolean userFile = false;
|
||||||
|
|
||||||
|
static byte[] data;
|
||||||
|
static File largeFile;
|
||||||
|
static String lastEntryName;
|
||||||
|
|
||||||
|
/* args can be empty, in which case check a 3 GB file which is created for
|
||||||
|
* this test (and then deleted). Or it can be a number, in which case
|
||||||
|
* that designates the size of the file that's created for this test (and
|
||||||
|
* then deleted). Or it can be the name of a file to use for the test, in
|
||||||
|
* which case it is *not* deleted. Note that in this last case, the data
|
||||||
|
* comparison might fail.
|
||||||
|
*/
|
||||||
|
static void realMain (String[] args) throws Throwable {
|
||||||
|
if (args.length > 0) {
|
||||||
|
try {
|
||||||
|
fileSize = Long.parseLong(args[0]);
|
||||||
|
System.out.println("Testing with file of size " + fileSize);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
largeFile = new File(args[0]);
|
||||||
|
if (!largeFile.exists()) {
|
||||||
|
throw new Exception("Specified file " + args[0] + " does not exist");
|
||||||
|
}
|
||||||
|
userFile = true;
|
||||||
|
System.out.println("Testing with user-provided file " + largeFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File testDir = null;
|
||||||
|
if (largeFile == null) {
|
||||||
|
testDir = new File(System.getProperty("test.scratch", "."),
|
||||||
|
"LargeZip");
|
||||||
|
if (testDir.exists()) {
|
||||||
|
if (!testDir.delete()) {
|
||||||
|
throw new Exception("Cannot delete already-existing test directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check(!testDir.exists() && testDir.mkdirs());
|
||||||
|
largeFile = new File(testDir, "largezip.zip");
|
||||||
|
createLargeZip();
|
||||||
|
}
|
||||||
|
|
||||||
|
readLargeZip1();
|
||||||
|
readLargeZip2();
|
||||||
|
|
||||||
|
if (!userFile && !debug) {
|
||||||
|
check(largeFile.delete());
|
||||||
|
check(testDir.delete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void createLargeZip() throws Throwable {
|
||||||
|
int iterations = DATA_LEN / DATA_SIZE;
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE);
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
bb.putDouble(0, Math.random());
|
||||||
|
baos.write(bb.array(), 0, DATA_SIZE);
|
||||||
|
}
|
||||||
|
data = baos.toByteArray();
|
||||||
|
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(
|
||||||
|
new BufferedOutputStream(new FileOutputStream(largeFile)));
|
||||||
|
long length = 0;
|
||||||
|
while (length < fileSize) {
|
||||||
|
ZipEntry ze = new ZipEntry("entry-" + length);
|
||||||
|
lastEntryName = ze.getName();
|
||||||
|
zos.putNextEntry(ze);
|
||||||
|
zos.write(data, 0, data.length);
|
||||||
|
zos.closeEntry();
|
||||||
|
length = largeFile.length();
|
||||||
|
}
|
||||||
|
System.out.println("Last entry written is " + lastEntryName);
|
||||||
|
zos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readLargeZip1() throws Throwable {
|
||||||
|
ZipFile zipFile = new ZipFile(largeFile);
|
||||||
|
ZipEntry entry = null;
|
||||||
|
String entryName = null;
|
||||||
|
int count = 0;
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
entry = entries.nextElement();
|
||||||
|
entryName = entry.getName();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
System.out.println("Number of entries read: " + count);
|
||||||
|
System.out.println("Last entry read is " + entryName);
|
||||||
|
check(!entry.isDirectory());
|
||||||
|
if (check(entryName.equals(lastEntryName))) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
InputStream is = zipFile.getInputStream(entry);
|
||||||
|
byte buf[] = new byte[4096];
|
||||||
|
int len;
|
||||||
|
while ((len = is.read(buf)) >= 0) {
|
||||||
|
baos.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
baos.close();
|
||||||
|
is.close();
|
||||||
|
check(Arrays.equals(data, baos.toByteArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void readLargeZip2() throws Throwable {
|
||||||
|
ZipInputStream zis = new ZipInputStream(
|
||||||
|
new BufferedInputStream(new FileInputStream(largeFile)));
|
||||||
|
ZipEntry entry = null;
|
||||||
|
String entryName = null;
|
||||||
|
int count = 0;
|
||||||
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
|
entryName = entry.getName();
|
||||||
|
if (entryName.equals(lastEntryName)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
System.out.println("Number of entries read: " + count);
|
||||||
|
System.out.println("Last entry read is " + entryName);
|
||||||
|
check(!entry.isDirectory());
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
byte buf[] = new byte[4096];
|
||||||
|
int len;
|
||||||
|
while ((len = zis.read(buf)) >= 0) {
|
||||||
|
baos.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
baos.close();
|
||||||
|
check(Arrays.equals(data, baos.toByteArray()));
|
||||||
|
check(zis.getNextEntry() == null);
|
||||||
|
zis.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------- Infrastructure ---------------------------
|
||||||
|
static volatile int passed = 0, failed = 0;
|
||||||
|
static void pass() {passed++;}
|
||||||
|
static void pass(String msg) {System.out.println(msg); passed++;}
|
||||||
|
static void fail() {failed++; Thread.dumpStack();}
|
||||||
|
static void fail(String msg) {System.out.println(msg); fail();}
|
||||||
|
static void unexpected(Throwable t) {failed++; t.printStackTrace();}
|
||||||
|
static void unexpected(Throwable t, String msg) {
|
||||||
|
System.out.println(msg); failed++; t.printStackTrace();}
|
||||||
|
static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
|
||||||
|
static void equal(Object x, Object y) {
|
||||||
|
if (x == null ? y == null : x.equals(y)) pass();
|
||||||
|
else fail(x + " not equal to " + y);}
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
try {realMain(args);} catch (Throwable t) {unexpected(t);}
|
||||||
|
System.out.println("\nPassed = " + passed + " failed = " + failed);
|
||||||
|
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||||
|
}
|
|
@ -158,4 +158,3 @@ public class LargeZipFile {
|
||||||
System.out.println("\nPassed = " + passed + " failed = " + failed);
|
System.out.println("\nPassed = " + passed + " failed = " + failed);
|
||||||
if (failed > 0) throw new AssertionError("Some tests failed");}
|
if (failed > 0) throw new AssertionError("Some tests failed");}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
200
jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh
Normal file
200
jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
#
|
||||||
|
# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
#
|
||||||
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License version 2 only, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
# accompanied this code).
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License version
|
||||||
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
# have any questions.
|
||||||
|
#
|
||||||
|
|
||||||
|
# @test
|
||||||
|
# @bug 6802846
|
||||||
|
# @summary jarsigner needs enhanced cert validation(options)
|
||||||
|
#
|
||||||
|
# @run shell concise_jarsigner.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ "${TESTJAVA}" = "" ] ; then
|
||||||
|
JAVAC_CMD=`which javac`
|
||||||
|
TESTJAVA=`dirname $JAVAC_CMD`/..
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set platform-dependent variables
|
||||||
|
OS=`uname -s`
|
||||||
|
case "$OS" in
|
||||||
|
Windows_* )
|
||||||
|
FS="\\"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
FS="/"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore js.jks"
|
||||||
|
JAR=$TESTJAVA${FS}bin${FS}jar
|
||||||
|
JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
|
||||||
|
JAVAC=$TESTJAVA${FS}bin${FS}javac
|
||||||
|
|
||||||
|
rm js.jks
|
||||||
|
|
||||||
|
echo class A1 {} > A1.java
|
||||||
|
echo class A2 {} > A2.java
|
||||||
|
echo class A3 {} > A3.java
|
||||||
|
echo class A4 {} > A4.java
|
||||||
|
echo class A5 {} > A5.java
|
||||||
|
echo class A6 {} > A6.java
|
||||||
|
|
||||||
|
$JAVAC A1.java A2.java A3.java A4.java A5.java A6.java
|
||||||
|
YEAR=`date +%Y`
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# First part: output format
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
$KT -genkeypair -alias a1 -dname CN=a1 -validity 365
|
||||||
|
$KT -genkeypair -alias a2 -dname CN=a2 -validity 365
|
||||||
|
|
||||||
|
# a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3
|
||||||
|
$JAR cvf a.jar A1.class A2.class
|
||||||
|
$JARSIGNER -keystore js.jks -storepass changeit a.jar a1
|
||||||
|
$JAR uvf a.jar A3.class A4.class
|
||||||
|
$JARSIGNER -keystore js.jks -storepass changeit a.jar a2
|
||||||
|
$JAR uvf a.jar A5.class A6.class
|
||||||
|
|
||||||
|
# Verify OK
|
||||||
|
$JARSIGNER -verify a.jar
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 4(chainNotValidated)+16(hasUnsignedEntry)+32(aliasNotInStore)
|
||||||
|
$JARSIGNER -verify a.jar -strict
|
||||||
|
[ $? = 52 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 16(hasUnsignedEntry)
|
||||||
|
$JARSIGNER -verify a.jar -strict -keystore js.jks
|
||||||
|
[ $? = 16 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 16(hasUnsignedEntry)+32(notSignedByAlias)
|
||||||
|
$JARSIGNER -verify a.jar a1 -strict -keystore js.jks
|
||||||
|
[ $? = 48 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 16(hasUnsignedEntry)
|
||||||
|
$JARSIGNER -verify a.jar a1 a2 -strict -keystore js.jks
|
||||||
|
[ $? = 16 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 12 entries all together
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose | grep $YEAR | wc -l`
|
||||||
|
[ $LINES = 12 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 12 entries all listed
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:grouped | grep $YEAR | wc -l`
|
||||||
|
[ $LINES = 12 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 3 groups: unrelated, signed, unsigned
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:summary | grep $YEAR | wc -l`
|
||||||
|
[ $LINES = 3 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 4 groups: unrelated, signed by a1/a2, signed by a2, unsigned
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep $YEAR | wc -l`
|
||||||
|
[ $LINES = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 2*2 for A1/A2, 2 for A3/A4
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose -certs | grep "\[certificate" | wc -l`
|
||||||
|
[ $LINES = 6 ] || exit $LINENO
|
||||||
|
|
||||||
|
# a1,a2 for A1/A2, a2 for A3/A4
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:grouped -certs | grep "\[certificate" | wc -l`
|
||||||
|
[ $LINES = 3 ] || exit $LINENO
|
||||||
|
|
||||||
|
# a1,a2 for A1/A2, a2 for A3/A4
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "\[certificate" | wc -l`
|
||||||
|
[ $LINES = 3 ] || exit $LINENO
|
||||||
|
|
||||||
|
# 4 groups
|
||||||
|
LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l`
|
||||||
|
[ $LINES = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Second part: exit code 2, 4, 8
|
||||||
|
# 16 and 32 already covered in the first part
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
$KT -genkeypair -alias expiring -dname CN=expiring -startdate -1m
|
||||||
|
$KT -genkeypair -alias expired -dname CN=expired -startdate -10m
|
||||||
|
$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m
|
||||||
|
$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365
|
||||||
|
$KT -genkeypair -alias badeku -dname CN=badeku -ext EKU=sa -validity 365
|
||||||
|
$KT -genkeypair -alias goodku -dname CN=goodku -ext KU=dig -validity 365
|
||||||
|
$KT -genkeypair -alias goodeku -dname CN=goodeku -ext EKU=codesign -validity 365
|
||||||
|
|
||||||
|
# badchain signed by ca, but ca is removed later
|
||||||
|
$KT -genkeypair -alias badchain -dname CN=badchain -validity 365
|
||||||
|
$KT -genkeypair -alias ca -dname CN=ca -ext bc -validity 365
|
||||||
|
$KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \
|
||||||
|
$KT -importcert -alias badchain
|
||||||
|
$KT -delete -alias ca
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expiring
|
||||||
|
[ $? = 2 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired
|
||||||
|
[ $? = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar notyetvalid
|
||||||
|
[ $? = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badku
|
||||||
|
[ $? = 8 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badeku
|
||||||
|
[ $? = 8 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodku
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar goodeku
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar badchain
|
||||||
|
[ $? = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -verify a.jar
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
# ==========================================================
|
||||||
|
# Third part: -certchain test
|
||||||
|
# ==========================================================
|
||||||
|
|
||||||
|
# altchain signed by ca2, but ca2 is removed later
|
||||||
|
$KT -genkeypair -alias altchain -dname CN=altchain -validity 365
|
||||||
|
$KT -genkeypair -alias ca2 -dname CN=ca2 -ext bc -validity 365
|
||||||
|
$KT -certreq -alias altchain | $KT -gencert -alias ca2 -validity 365 -rfc > certchain
|
||||||
|
$KT -exportcert -alias ca2 -rfc >> certchain
|
||||||
|
$KT -delete -alias ca2
|
||||||
|
|
||||||
|
# Now altchain is still self-signed
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar altchain
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
# If -certchain is used, then it's bad
|
||||||
|
$JARSIGNER -strict -keystore js.jks -storepass changeit -certchain certchain a.jar altchain
|
||||||
|
[ $? = 4 ] || exit $LINENO
|
||||||
|
|
||||||
|
$JARSIGNER -verify a.jar
|
||||||
|
[ $? = 0 ] || exit $LINENO
|
||||||
|
|
||||||
|
echo OK
|
||||||
|
exit 0
|
69
jdk/test/sun/security/tools/keytool/selfissued.sh
Normal file
69
jdk/test/sun/security/tools/keytool/selfissued.sh
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#
|
||||||
|
# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
#
|
||||||
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License version 2 only, as
|
||||||
|
# published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
# version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
# accompanied this code).
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License version
|
||||||
|
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
# have any questions.
|
||||||
|
#
|
||||||
|
|
||||||
|
# @test
|
||||||
|
# @bug 6825352
|
||||||
|
# @summary support self-issued certificate in keytool
|
||||||
|
#
|
||||||
|
# @run shell selfissued.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ "${TESTJAVA}" = "" ] ; then
|
||||||
|
JAVAC_CMD=`which javac`
|
||||||
|
TESTJAVA=`dirname $JAVAC_CMD`/..
|
||||||
|
fi
|
||||||
|
|
||||||
|
# set platform-dependent variables
|
||||||
|
OS=`uname -s`
|
||||||
|
case "$OS" in
|
||||||
|
Windows_* )
|
||||||
|
FS="\\"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
FS="/"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
KS=selfsigned.jks
|
||||||
|
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
|
||||||
|
|
||||||
|
rm $KS
|
||||||
|
|
||||||
|
$KT -alias ca -dname CN=CA -genkeypair
|
||||||
|
$KT -alias me -dname CN=CA -genkeypair
|
||||||
|
$KT -alias e1 -dname CN=E1 -genkeypair
|
||||||
|
$KT -alias e2 -dname CN=E2 -genkeypair
|
||||||
|
|
||||||
|
# me signed by ca, self-issued
|
||||||
|
$KT -alias me -certreq | $KT -alias ca -gencert | $KT -alias me -importcert
|
||||||
|
|
||||||
|
# Import e1 signed by me, should add me and ca
|
||||||
|
$KT -alias e1 -certreq | $KT -alias me -gencert | $KT -alias e1 -importcert
|
||||||
|
$KT -alias e1 -list -v | grep '\[3\]' || { echo Bad E1; exit 1; }
|
||||||
|
|
||||||
|
# Import (e2 signed by me,ca,me), should reorder to (e2,me,ca)
|
||||||
|
( $KT -alias e2 -certreq | $KT -alias me -gencert; $KT -exportcert -alias ca; $KT -exportcert -alias me ) | $KT -alias e2 -importcert
|
||||||
|
$KT -alias e2 -list -v | grep '\[3\]' || { echo Bad E2; exit 1; }
|
||||||
|
|
||||||
|
echo Good
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue