提交 9b97cf00 编写于 作者: L lana

Merge

...@@ -71,7 +71,7 @@ include $(BUILDDIR)/common/internal/ImportComponents.gmk ...@@ -71,7 +71,7 @@ include $(BUILDDIR)/common/internal/ImportComponents.gmk
ifeq ($(ARCH_DATA_MODEL),64) ifeq ($(ARCH_DATA_MODEL),64)
MAX_VM_MEMORY = 1024 MAX_VM_MEMORY = 1024
else else
MAX_VM_MEMORY = 512 MAX_VM_MEMORY = 612
endif endif
# List of all possible directories for javadoc to look for sources # List of all possible directories for javadoc to look for sources
......
...@@ -124,7 +124,7 @@ class FileInputStream extends InputStream ...@@ -124,7 +124,7 @@ class FileInputStream extends InputStream
throw new NullPointerException(); throw new NullPointerException();
} }
fd = new FileDescriptor(); fd = new FileDescriptor();
fd.incrementAndGetUseCount(); fd.attach(this);
open(name); open(name);
} }
...@@ -164,10 +164,9 @@ class FileInputStream extends InputStream ...@@ -164,10 +164,9 @@ class FileInputStream extends InputStream
/* /*
* FileDescriptor is being shared by streams. * FileDescriptor is being shared by streams.
* Ensure that it's GC'ed only when all the streams/channels are done * Register this stream with FileDescriptor tracker.
* using it.
*/ */
fd.incrementAndGetUseCount(); fd.attach(this);
} }
/** /**
...@@ -294,27 +293,14 @@ class FileInputStream extends InputStream ...@@ -294,27 +293,14 @@ class FileInputStream extends InputStream
closed = true; closed = true;
} }
if (channel != null) { if (channel != null) {
/*
* Decrement the FD use count associated with the channel
* The use count is incremented whenever a new channel
* is obtained from this stream.
*/
fd.decrementAndGetUseCount();
channel.close(); channel.close();
} }
/* fd.closeAll(new Closeable() {
* Decrement the FD use count associated with this stream public void close() throws IOException {
*/
int useCount = fd.decrementAndGetUseCount();
/*
* If FileDescriptor is still in use by another stream, we
* will not close it.
*/
if (useCount <= 0) {
close0(); close0();
} }
});
} }
/** /**
...@@ -328,7 +314,9 @@ class FileInputStream extends InputStream ...@@ -328,7 +314,9 @@ class FileInputStream extends InputStream
* @see java.io.FileDescriptor * @see java.io.FileDescriptor
*/ */
public final FileDescriptor getFD() throws IOException { public final FileDescriptor getFD() throws IOException {
if (fd != null) return fd; if (fd != null) {
return fd;
}
throw new IOException(); throw new IOException();
} }
...@@ -352,13 +340,6 @@ class FileInputStream extends InputStream ...@@ -352,13 +340,6 @@ class FileInputStream extends InputStream
synchronized (this) { synchronized (this) {
if (channel == null) { if (channel == null) {
channel = FileChannelImpl.open(fd, true, false, this); channel = FileChannelImpl.open(fd, true, false, this);
/*
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
} }
return channel; return channel;
} }
...@@ -381,6 +362,11 @@ class FileInputStream extends InputStream ...@@ -381,6 +362,11 @@ class FileInputStream extends InputStream
*/ */
protected void finalize() throws IOException { protected void finalize() throws IOException {
if ((fd != null) && (fd != FileDescriptor.in)) { if ((fd != null) && (fd != FileDescriptor.in)) {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close(); close();
} }
} }
......
...@@ -197,9 +197,9 @@ class FileOutputStream extends OutputStream ...@@ -197,9 +197,9 @@ class FileOutputStream extends OutputStream
throw new NullPointerException(); throw new NullPointerException();
} }
this.fd = new FileDescriptor(); this.fd = new FileDescriptor();
fd.attach(this);
this.append = append; this.append = append;
fd.incrementAndGetUseCount();
open(name, append); open(name, append);
} }
...@@ -237,12 +237,7 @@ class FileOutputStream extends OutputStream ...@@ -237,12 +237,7 @@ class FileOutputStream extends OutputStream
this.fd = fdObj; this.fd = fdObj;
this.append = false; this.append = false;
/* fd.attach(this);
* FileDescriptor is being shared by streams.
* Ensure that it's GC'ed only when all the streams/channels are done
* using it.
*/
fd.incrementAndGetUseCount();
} }
/** /**
...@@ -331,27 +326,14 @@ class FileOutputStream extends OutputStream ...@@ -331,27 +326,14 @@ class FileOutputStream extends OutputStream
} }
if (channel != null) { if (channel != null) {
/*
* Decrement FD use count associated with the channel
* The use count is incremented whenever a new channel
* is obtained from this stream.
*/
fd.decrementAndGetUseCount();
channel.close(); channel.close();
} }
/* fd.closeAll(new Closeable() {
* Decrement FD use count associated with this stream public void close() throws IOException {
*/
int useCount = fd.decrementAndGetUseCount();
/*
* If FileDescriptor is still in use by another stream, we
* will not close it.
*/
if (useCount <= 0) {
close0(); close0();
} }
});
} }
/** /**
...@@ -365,7 +347,9 @@ class FileOutputStream extends OutputStream ...@@ -365,7 +347,9 @@ class FileOutputStream extends OutputStream
* @see java.io.FileDescriptor * @see java.io.FileDescriptor
*/ */
public final FileDescriptor getFD() throws IOException { public final FileDescriptor getFD() throws IOException {
if (fd != null) return fd; if (fd != null) {
return fd;
}
throw new IOException(); throw new IOException();
} }
...@@ -390,13 +374,6 @@ class FileOutputStream extends OutputStream ...@@ -390,13 +374,6 @@ class FileOutputStream extends OutputStream
synchronized (this) { synchronized (this) {
if (channel == null) { if (channel == null) {
channel = FileChannelImpl.open(fd, false, true, append, this); channel = FileChannelImpl.open(fd, false, true, append, this);
/*
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
} }
return channel; return channel;
} }
...@@ -415,6 +392,11 @@ class FileOutputStream extends OutputStream ...@@ -415,6 +392,11 @@ class FileOutputStream extends OutputStream
if (fd == FileDescriptor.out || fd == FileDescriptor.err) { if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush(); flush();
} else { } else {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close(); close();
} }
} }
......
...@@ -229,7 +229,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { ...@@ -229,7 +229,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
throw new NullPointerException(); throw new NullPointerException();
} }
fd = new FileDescriptor(); fd = new FileDescriptor();
fd.incrementAndGetUseCount(); fd.attach(this);
open(name, imode); open(name, imode);
} }
...@@ -242,7 +242,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { ...@@ -242,7 +242,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @see java.io.FileDescriptor * @see java.io.FileDescriptor
*/ */
public final FileDescriptor getFD() throws IOException { public final FileDescriptor getFD() throws IOException {
if (fd != null) return fd; if (fd != null) {
return fd;
}
throw new IOException(); throw new IOException();
} }
...@@ -268,17 +270,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { ...@@ -268,17 +270,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
synchronized (this) { synchronized (this) {
if (channel == null) { if (channel == null) {
channel = FileChannelImpl.open(fd, true, rw, this); channel = FileChannelImpl.open(fd, true, rw, this);
/*
* FileDescriptor could be shared by FileInputStream or
* FileOutputStream.
* Ensure that FD is GC'ed only when all the streams/channels
* are done using it.
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
} }
return channel; return channel;
} }
...@@ -577,28 +568,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { ...@@ -577,28 +568,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
closed = true; closed = true;
} }
if (channel != null) { if (channel != null) {
/*
* Decrement FD use count associated with the channel. The FD use
* count is incremented whenever a new channel is obtained from
* this stream.
*/
fd.decrementAndGetUseCount();
channel.close(); channel.close();
} }
/* fd.closeAll(new Closeable() {
* Decrement FD use count associated with this stream. public void close() throws IOException {
* The count got incremented by FileDescriptor during its construction.
*/
int useCount = fd.decrementAndGetUseCount();
/*
* If FileDescriptor is still in use by another stream, we
* will not close it.
*/
if (useCount <= 0) {
close0(); close0();
} }
});
} }
// //
......
...@@ -57,7 +57,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { ...@@ -57,7 +57,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
/** /**
* Size of writeBuffer, must be >= 1 * Size of writeBuffer, must be >= 1
*/ */
private final int writeBufferSize = 1024; private static final int WRITE_BUFFER_SIZE = 1024;
/** /**
* The object used to synchronize operations on this stream. For * The object used to synchronize operations on this stream. For
...@@ -107,7 +107,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable { ...@@ -107,7 +107,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
public void write(int c) throws IOException { public void write(int c) throws IOException {
synchronized (lock) { synchronized (lock) {
if (writeBuffer == null){ if (writeBuffer == null){
writeBuffer = new char[writeBufferSize]; writeBuffer = new char[WRITE_BUFFER_SIZE];
} }
writeBuffer[0] = (char) c; writeBuffer[0] = (char) c;
write(writeBuffer, 0, 1); write(writeBuffer, 0, 1);
...@@ -180,9 +180,9 @@ public abstract class Writer implements Appendable, Closeable, Flushable { ...@@ -180,9 +180,9 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
public void write(String str, int off, int len) throws IOException { public void write(String str, int off, int len) throws IOException {
synchronized (lock) { synchronized (lock) {
char cbuf[]; char cbuf[];
if (len <= writeBufferSize) { if (len <= WRITE_BUFFER_SIZE) {
if (writeBuffer == null) { if (writeBuffer == null) {
writeBuffer = new char[writeBufferSize]; writeBuffer = new char[WRITE_BUFFER_SIZE];
} }
cbuf = writeBuffer; cbuf = writeBuffer;
} else { // Don't permanently allocate very large buffers. } else { // Don't permanently allocate very large buffers.
......
...@@ -71,7 +71,7 @@ public class AssertionError extends Error { ...@@ -71,7 +71,7 @@ public class AssertionError extends Error {
* @see Throwable#getCause() * @see Throwable#getCause()
*/ */
public AssertionError(Object detailMessage) { public AssertionError(Object detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
if (detailMessage instanceof Throwable) if (detailMessage instanceof Throwable)
initCause((Throwable) detailMessage); initCause((Throwable) detailMessage);
} }
...@@ -85,7 +85,7 @@ public class AssertionError extends Error { ...@@ -85,7 +85,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(boolean detailMessage) { public AssertionError(boolean detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
...@@ -97,7 +97,7 @@ public class AssertionError extends Error { ...@@ -97,7 +97,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(char detailMessage) { public AssertionError(char detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
...@@ -109,7 +109,7 @@ public class AssertionError extends Error { ...@@ -109,7 +109,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(int detailMessage) { public AssertionError(int detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
...@@ -121,7 +121,7 @@ public class AssertionError extends Error { ...@@ -121,7 +121,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(long detailMessage) { public AssertionError(long detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
...@@ -133,7 +133,7 @@ public class AssertionError extends Error { ...@@ -133,7 +133,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(float detailMessage) { public AssertionError(float detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
...@@ -145,7 +145,7 @@ public class AssertionError extends Error { ...@@ -145,7 +145,7 @@ public class AssertionError extends Error {
* @param detailMessage value to be used in constructing detail message * @param detailMessage value to be used in constructing detail message
*/ */
public AssertionError(double detailMessage) { public AssertionError(double detailMessage) {
this("" + detailMessage); this(String.valueOf(detailMessage));
} }
/** /**
......
...@@ -3008,7 +3008,7 @@ public final ...@@ -3008,7 +3008,7 @@ public final
/** /**
* Casts this {@code Class} object to represent a subclass of the class * Casts this {@code Class} object to represent a subclass of the class
* represented by the specified class object. Checks that that the cast * represented by the specified class object. Checks that the cast
* is valid, and throws a {@code ClassCastException} if it is not. If * is valid, and throws a {@code ClassCastException} if it is not. If
* this method succeeds, it always returns a reference to this class object. * this method succeeds, it always returns a reference to this class object.
* *
......
...@@ -607,8 +607,7 @@ public final class Double extends Number implements Comparable<Double> { ...@@ -607,8 +607,7 @@ public final class Double extends Number implements Comparable<Double> {
* @see java.lang.Double#valueOf(java.lang.String) * @see java.lang.Double#valueOf(java.lang.String)
*/ */
public Double(String s) throws NumberFormatException { public Double(String s) throws NumberFormatException {
// REMIND: this is inefficient value = parseDouble(s);
this(valueOf(s).doubleValue());
} }
/** /**
......
...@@ -529,8 +529,7 @@ public final class Float extends Number implements Comparable<Float> { ...@@ -529,8 +529,7 @@ public final class Float extends Number implements Comparable<Float> {
* @see java.lang.Float#valueOf(java.lang.String) * @see java.lang.Float#valueOf(java.lang.String)
*/ */
public Float(String s) throws NumberFormatException { public Float(String s) throws NumberFormatException {
// REMIND: this is inefficient value = parseFloat(s);
this(valueOf(s).floatValue());
} }
/** /**
......
...@@ -28,6 +28,7 @@ package java.security; ...@@ -28,6 +28,7 @@ package java.security;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.atomic.AtomicReference;
import sun.security.jca.GetInstance; import sun.security.jca.GetInstance;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -60,8 +61,8 @@ import sun.security.util.SecurityConstants; ...@@ -60,8 +61,8 @@ import sun.security.util.SecurityConstants;
* with a standard type. The default policy type is "JavaPolicy". * with a standard type. The default policy type is "JavaPolicy".
* *
* <p> Once a Policy instance has been installed (either by default, or by * <p> Once a Policy instance has been installed (either by default, or by
* calling <code>setPolicy</code>), * calling <code>setPolicy</code>), the Java runtime invokes its
* the Java runtime invokes its <code>implies</code> when it needs to * <code>implies</code> method when it needs to
* determine whether executing code (encapsulated in a ProtectionDomain) * determine whether executing code (encapsulated in a ProtectionDomain)
* can perform SecurityManager-protected operations. How a Policy object * can perform SecurityManager-protected operations. How a Policy object
* retrieves its policy data is up to the Policy implementation itself. * retrieves its policy data is up to the Policy implementation itself.
...@@ -94,18 +95,33 @@ public abstract class Policy { ...@@ -94,18 +95,33 @@ public abstract class Policy {
public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
new UnsupportedEmptyCollection(); new UnsupportedEmptyCollection();
/** the system-wide policy. */ // Information about the system-wide policy.
private static Policy policy; // package private for AccessControlContext private static class PolicyInfo {
// the system-wide policy
final Policy policy;
// a flag indicating if the system-wide policy has been initialized
final boolean initialized;
PolicyInfo(Policy policy, boolean initialized) {
this.policy = policy;
this.initialized = initialized;
}
}
// PolicyInfo is stored in an AtomicReference
private static AtomicReference<PolicyInfo> policy =
new AtomicReference<>(new PolicyInfo(null, false));
private static final Debug debug = Debug.getInstance("policy"); private static final Debug debug = Debug.getInstance("policy");
// Cache mapping ProtectionDomain.Key to PermissionCollection // Cache mapping ProtectionDomain.Key to PermissionCollection
private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping; private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
/** package private for AccessControlContext */ /** package private for AccessControlContext and ProtectionDomain */
static boolean isSet() static boolean isSet()
{ {
return policy != null; PolicyInfo pi = policy.get();
return pi.policy != null && pi.initialized == true;
} }
private static void checkPermission(String type) { private static void checkPermission(String type) {
...@@ -143,16 +159,20 @@ public abstract class Policy { ...@@ -143,16 +159,20 @@ public abstract class Policy {
/** /**
* Returns the installed Policy object, skipping the security check. * Returns the installed Policy object, skipping the security check.
* Used by SecureClassLoader and getPolicy. * Used by ProtectionDomain and getPolicy.
* *
* @return the installed Policy. * @return the installed Policy.
*
*/ */
static synchronized Policy getPolicyNoCheck() static Policy getPolicyNoCheck()
{ {
if (policy == null) { PolicyInfo pi = policy.get();
String policy_class = null; // Use double-check idiom to avoid locking if system-wide policy is
policy_class = AccessController.doPrivileged( // already initialized
if (pi.initialized == false || pi.policy == null) {
synchronized (Policy.class) {
PolicyInfo pinfo = policy.get();
if (pinfo.policy == null) {
String policy_class = AccessController.doPrivileged(
new PrivilegedAction<String>() { new PrivilegedAction<String>() {
public String run() { public String run() {
return Security.getProperty("policy.provider"); return Security.getProperty("policy.provider");
...@@ -163,22 +183,25 @@ public abstract class Policy { ...@@ -163,22 +183,25 @@ public abstract class Policy {
} }
try { try {
policy = (Policy) pinfo = new PolicyInfo(
Class.forName(policy_class).newInstance(); (Policy) Class.forName(policy_class).newInstance(),
true);
} catch (Exception e) { } catch (Exception e) {
/* /*
* The policy_class seems to be an extension * The policy_class seems to be an extension
* so we have to bootstrap loading it via a policy * so we have to bootstrap loading it via a policy
* provider that is on the bootclasspath * provider that is on the bootclasspath.
* If it loads then shift gears to using the configured * If it loads then shift gears to using the configured
* provider. * provider.
*/ */
// install the bootstrap provider to avoid recursion // install the bootstrap provider to avoid recursion
policy = new sun.security.provider.PolicyFile(); Policy polFile = new sun.security.provider.PolicyFile();
pinfo = new PolicyInfo(polFile, false);
policy.set(pinfo);
final String pc = policy_class; final String pc = policy_class;
Policy p = AccessController.doPrivileged( Policy pol = AccessController.doPrivileged(
new PrivilegedAction<Policy>() { new PrivilegedAction<Policy>() {
public Policy run() { public Policy run() {
try { try {
...@@ -207,16 +230,21 @@ public abstract class Policy { ...@@ -207,16 +230,21 @@ public abstract class Policy {
* if it loaded install it as the policy provider. Otherwise * if it loaded install it as the policy provider. Otherwise
* continue to use the system default implementation * continue to use the system default implementation
*/ */
if (p != null) { if (pol != null) {
policy = p; pinfo = new PolicyInfo(pol, true);
} else { } else {
if (debug != null) { if (debug != null) {
debug.println("using sun.security.provider.PolicyFile"); debug.println("using sun.security.provider.PolicyFile");
} }
pinfo = new PolicyInfo(polFile, true);
}
}
policy.set(pinfo);
} }
return pinfo.policy;
} }
} }
return policy; return pi.policy;
} }
/** /**
...@@ -245,7 +273,7 @@ public abstract class Policy { ...@@ -245,7 +273,7 @@ public abstract class Policy {
initPolicy(p); initPolicy(p);
} }
synchronized (Policy.class) { synchronized (Policy.class) {
Policy.policy = p; policy.set(new PolicyInfo(p, p != null));
} }
} }
...@@ -292,14 +320,14 @@ public abstract class Policy { ...@@ -292,14 +320,14 @@ public abstract class Policy {
PermissionCollection policyPerms = null; PermissionCollection policyPerms = null;
synchronized (p) { synchronized (p) {
if (p.pdMapping == null) { if (p.pdMapping == null) {
p.pdMapping = p.pdMapping = new WeakHashMap<>();
new WeakHashMap<ProtectionDomain.Key, PermissionCollection>();
} }
} }
if (policyDomain.getCodeSource() != null) { if (policyDomain.getCodeSource() != null) {
if (Policy.isSet()) { Policy pol = policy.get().policy;
policyPerms = policy.getPermissions(policyDomain); if (pol != null) {
policyPerms = pol.getPermissions(policyDomain);
} }
if (policyPerms == null) { // assume it has all if (policyPerms == null) { // assume it has all
...@@ -434,7 +462,7 @@ public abstract class Policy { ...@@ -434,7 +462,7 @@ public abstract class Policy {
type, type,
params); params);
} catch (NoSuchAlgorithmException nsae) { } catch (NoSuchAlgorithmException nsae) {
return handleException (nsae); return handleException(nsae);
} }
} }
...@@ -494,7 +522,7 @@ public abstract class Policy { ...@@ -494,7 +522,7 @@ public abstract class Policy {
type, type,
params); params);
} catch (NoSuchAlgorithmException nsae) { } catch (NoSuchAlgorithmException nsae) {
return handleException (nsae); return handleException(nsae);
} }
} }
......
...@@ -767,7 +767,7 @@ public interface PreparedStatement extends Statement { ...@@ -767,7 +767,7 @@ public interface PreparedStatement extends Statement {
/** /**
* Sets the designated paramter to the given <code>String</code> object. * Sets the designated parameter to the given <code>String</code> object.
* The driver converts this to a SQL <code>NCHAR</code> or * The driver converts this to a SQL <code>NCHAR</code> or
* <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
* (depending on the argument's * (depending on the argument's
......
...@@ -991,7 +991,7 @@ public interface Statement extends Wrapper, AutoCloseable { ...@@ -991,7 +991,7 @@ public interface Statement extends Wrapper, AutoCloseable {
/** /**
* Requests that a <code>Statement</code> be pooled or not pooled. The value * Requests that a <code>Statement</code> be pooled or not pooled. The value
* specified is a hint to the statement pool implementation indicating * specified is a hint to the statement pool implementation indicating
* whether the applicaiton wants the statement to be pooled. It is up to * whether the application wants the statement to be pooled. It is up to
* the statement pool manager as to whether the hint is used. * the statement pool manager as to whether the hint is used.
* <p> * <p>
* The poolable value of a statement is applicable to both internal * The poolable value of a statement is applicable to both internal
......
...@@ -742,6 +742,8 @@ public class LinkedBlockingDeque<E> ...@@ -742,6 +742,8 @@ public class LinkedBlockingDeque<E>
throw new NullPointerException(); throw new NullPointerException();
if (c == this) if (c == this)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
final ReentrantLock lock = this.lock; final ReentrantLock lock = this.lock;
lock.lock(); lock.lock();
try { try {
......
...@@ -332,7 +332,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E> ...@@ -332,7 +332,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
// Note: convention in all put/take/etc is to preset local var // Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set. // holding count negative to indicate failure unless set.
int c = -1; int c = -1;
Node<E> node = new Node(e); Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock; final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count; final AtomicInteger count = this.count;
putLock.lockInterruptibly(); putLock.lockInterruptibly();
...@@ -412,7 +412,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E> ...@@ -412,7 +412,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
if (count.get() == capacity) if (count.get() == capacity)
return false; return false;
int c = -1; int c = -1;
Node<E> node = new Node(e); Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock; final ReentrantLock putLock = this.putLock;
putLock.lock(); putLock.lock();
try { try {
...@@ -728,6 +728,8 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E> ...@@ -728,6 +728,8 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
throw new NullPointerException(); throw new NullPointerException();
if (c == this) if (c == this)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
boolean signalNotFull = false; boolean signalNotFull = false;
final ReentrantLock takeLock = this.takeLock; final ReentrantLock takeLock = this.takeLock;
takeLock.lock(); takeLock.lock();
......
...@@ -629,7 +629,7 @@ public class Attributes implements Map<Object,Object>, Cloneable { ...@@ -629,7 +629,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id"); public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
/** /**
* <code>Name</code> object for <code>Implementation-Vendor-URL</code> * <code>Name</code> object for <code>Implementation-URL</code>
* manifest attribute used for package versioning. * manifest attribute used for package versioning.
* @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779"> * @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
* Java Product Versioning Specification</a> * Java Product Versioning Specification</a>
......
...@@ -402,10 +402,10 @@ class ServerImpl implements TimeSource { ...@@ -402,10 +402,10 @@ class ServerImpl implements TimeSource {
} catch (IOException e) { } catch (IOException e) {
logger.log (Level.FINER, "Dispatcher (4)", e); logger.log (Level.FINER, "Dispatcher (4)", e);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
logger.log (Level.FINER, "Dispatcher (7)", e); logger.log (Level.FINER, "Dispatcher (7)", e);
} }
} }
try {selector.close(); } catch (Exception e) {}
} }
private void handleException (SelectionKey key, Exception e) { private void handleException (SelectionKey key, Exception e) {
......
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,6 +29,7 @@ import java.util.Enumeration; ...@@ -29,6 +29,7 @@ import java.util.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.io.FilePermission;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.*;
import java.rmi.*; import java.rmi.*;
...@@ -54,7 +55,6 @@ import sun.rmi.server.UnicastServerRef2; ...@@ -54,7 +55,6 @@ import sun.rmi.server.UnicastServerRef2;
import sun.rmi.transport.LiveRef; import sun.rmi.transport.LiveRef;
import sun.rmi.transport.ObjectTable; import sun.rmi.transport.ObjectTable;
import sun.rmi.transport.Target; import sun.rmi.transport.Target;
import sun.security.action.GetPropertyAction;
/** /**
* A "registry" exists on every node that allows RMI connections to * A "registry" exists on every node that allows RMI connections to
...@@ -335,19 +335,6 @@ public class RegistryImpl extends java.rmi.server.RemoteServer ...@@ -335,19 +335,6 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp); URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp);
ClassLoader cl = new URLClassLoader(urls); ClassLoader cl = new URLClassLoader(urls);
String codebaseProperty = null;
String prop = java.security.AccessController.doPrivileged(
new GetPropertyAction("java.rmi.server.codebase"));
if (prop != null && prop.trim().length() > 0) {
codebaseProperty = prop;
}
URL[] codebaseURLs = null;
if (codebaseProperty != null) {
codebaseURLs = sun.misc.URLClassPath.pathToURLs(codebaseProperty);
} else {
codebaseURLs = new URL[0];
}
/* /*
* Fix bugid 4242317: Classes defined by this class loader should * Fix bugid 4242317: Classes defined by this class loader should
* be annotated with the value of the "java.rmi.server.codebase" * be annotated with the value of the "java.rmi.server.codebase"
...@@ -365,7 +352,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer ...@@ -365,7 +352,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
public RegistryImpl run() throws RemoteException { public RegistryImpl run() throws RemoteException {
return new RegistryImpl(regPort); return new RegistryImpl(regPort);
} }
}, getAccessControlContext(codebaseURLs)); }, getAccessControlContext());
} catch (PrivilegedActionException ex) { } catch (PrivilegedActionException ex) {
throw (RemoteException) ex.getException(); throw (RemoteException) ex.getException();
} }
...@@ -391,11 +378,11 @@ public class RegistryImpl extends java.rmi.server.RemoteServer ...@@ -391,11 +378,11 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
} }
/** /**
* Generates an AccessControlContext from several URLs. * Generates an AccessControlContext with minimal permissions.
* The approach used here is taken from the similar method * The approach used here is taken from the similar method
* getAccessControlContext() in the sun.applet.AppletPanel class. * getAccessControlContext() in the sun.applet.AppletPanel class.
*/ */
private static AccessControlContext getAccessControlContext(URL[] urls) { private static AccessControlContext getAccessControlContext() {
// begin with permissions granted to all code in current policy // begin with permissions granted to all code in current policy
PermissionCollection perms = AccessController.doPrivileged( PermissionCollection perms = AccessController.doPrivileged(
new java.security.PrivilegedAction<PermissionCollection>() { new java.security.PrivilegedAction<PermissionCollection>() {
...@@ -420,17 +407,15 @@ public class RegistryImpl extends java.rmi.server.RemoteServer ...@@ -420,17 +407,15 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
perms.add(new RuntimePermission("accessClassInPackage.sun.*")); perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
// add permissions required to load from codebase URL path perms.add(new FilePermission("<<ALL FILES>>", "read"));
LoaderHandler.addPermissionsForURLs(urls, perms, false);
/* /*
* Create an AccessControlContext that consists of a single * Create an AccessControlContext that consists of a single
* protection domain with only the permissions calculated above. * protection domain with only the permissions calculated above.
*/ */
ProtectionDomain pd = new ProtectionDomain( ProtectionDomain pd = new ProtectionDomain(
new CodeSource((urls.length > 0 ? urls[0] : null), new CodeSource(null,
(java.security.cert.Certificate[]) null), (java.security.cert.Certificate[]) null), perms);
perms);
return new AccessControlContext(new ProtectionDomain[] { pd }); return new AccessControlContext(new ProtectionDomain[] { pd });
} }
} }
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1031,7 +1031,7 @@ public final class LoaderHandler { ...@@ -1031,7 +1031,7 @@ public final class LoaderHandler {
* loader. A given permission is only added to the collection if * loader. A given permission is only added to the collection if
* it is not already implied by the collection. * it is not already implied by the collection.
*/ */
public static void addPermissionsForURLs(URL[] urls, private static void addPermissionsForURLs(URL[] urls,
PermissionCollection perms, PermissionCollection perms,
boolean forLoader) boolean forLoader)
{ {
......
...@@ -68,8 +68,8 @@ public class KerberosTime implements Cloneable { ...@@ -68,8 +68,8 @@ public class KerberosTime implements Cloneable {
private int microSeconds; // the last three digits of the microsecond value private int microSeconds; // the last three digits of the microsecond value
// The time when this class is loaded. Used in setNow() // The time when this class is loaded. Used in setNow()
private static final long initMilli = System.currentTimeMillis(); private static long initMilli = System.currentTimeMillis();
private static final long initMicro = System.nanoTime() / 1000; private static long initMicro = System.nanoTime() / 1000;
private static long syncTime; private static long syncTime;
private static boolean DEBUG = Krb5.DEBUG; private static boolean DEBUG = Krb5.DEBUG;
...@@ -212,10 +212,23 @@ public class KerberosTime implements Cloneable { ...@@ -212,10 +212,23 @@ public class KerberosTime implements Cloneable {
} }
public void setNow() { public void setNow() {
long microElapsed = System.nanoTime() / 1000 - initMicro; long newMilli = System.currentTimeMillis();
setTime(initMilli + microElapsed/1000); long newMicro = System.nanoTime() / 1000;
long microElapsed = newMicro - initMicro;
long calcMilli = initMilli + microElapsed/1000;
if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
if (DEBUG) {
System.out.println("System time adjusted");
}
initMilli = newMilli;
initMicro = newMicro;
setTime(newMilli);
microSeconds = 0;
} else {
setTime(calcMilli);
microSeconds = (int)(microElapsed % 1000); microSeconds = (int)(microElapsed % 1000);
} }
}
public int getMicroSeconds() { public int getMicroSeconds() {
Long temp_long = new Long((kerberosTime % 1000L) * 1000L); Long temp_long = new Long((kerberosTime % 1000L) * 1000L);
......
...@@ -375,7 +375,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC ...@@ -375,7 +375,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
} }
AuthorizationDataEntry[] auDataEntry = readAuth(); AuthorizationDataEntry[] auDataEntry = readAuth();
AuthorizationData auData = null; AuthorizationData auData = null;
if (auData != null) { if (auDataEntry != null) {
auData = new AuthorizationData(auDataEntry); auData = new AuthorizationData(auDataEntry);
} }
byte[] ticketData = readData(); byte[] ticketData = readData();
......
...@@ -209,10 +209,24 @@ public class Credentials { ...@@ -209,10 +209,24 @@ public class Credentials {
} }
public sun.security.krb5.Credentials setKrbCreds() { public sun.security.krb5.Credentials setKrbCreds() {
// Note: We will not pass authorizationData to s.s.k.Credentials. The
// field in that class will be passed to Krb5Context as the return
// value of ExtendedGSSContext.inquireSecContext(KRB5_GET_AUTHZ_DATA),
// which is documented as the authData in the service ticket. That
// is on the acceptor side.
//
// This class is for the initiator side. Also, authdata inside a ccache
// is most likely to be the one in Authenticator in PA-TGS-REQ encoded
// in TGS-REQ, therefore only stored with a service ticket. Currently
// in Java, we only reads TGTs.
return new sun.security.krb5.Credentials(ticket, return new sun.security.krb5.Credentials(ticket,
cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr); cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
} }
public KerberosTime getStartTime() {
return starttime;
}
public KerberosTime getAuthTime() { public KerberosTime getAuthTime() {
return authtime; return authtime;
} }
...@@ -221,6 +235,10 @@ public class Credentials { ...@@ -221,6 +235,10 @@ public class Credentials {
return endtime; return endtime;
} }
public KerberosTime getRenewTill() {
return renewTill;
}
public TicketFlags getTicketFlags() { public TicketFlags getTicketFlags() {
return flags; return flags;
} }
...@@ -228,4 +246,8 @@ public class Credentials { ...@@ -228,4 +246,8 @@ public class Credentials {
public int getEType() { public int getEType() {
return key.getEType(); return key.getEType();
} }
public int getTktEType() {
return ticket.encPart.getEType();
}
} }
...@@ -771,10 +771,15 @@ public abstract class SSLContextImpl extends SSLContextSpi { ...@@ -771,10 +771,15 @@ public abstract class SSLContextImpl extends SSLContextSpi {
final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
implements X509TrustManager { implements X509TrustManager {
// the delegated trust manager
private final X509TrustManager tm; private final X509TrustManager tm;
// Cache the trusted certificate to optimize the performance.
private final Collection<X509Certificate> trustedCerts = new HashSet<>();
AbstractTrustManagerWrapper(X509TrustManager tm) { AbstractTrustManagerWrapper(X509TrustManager tm) {
this.tm = tm; this.tm = tm;
Collections.addAll(trustedCerts, tm.getAcceptedIssuers());
} }
@Override @Override
...@@ -863,20 +868,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager ...@@ -863,20 +868,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(sslSocket, true); constraints = new SSLAlgorithmConstraints(sslSocket, true);
} }
AlgorithmChecker checker = new AlgorithmChecker(constraints); checkAlgorithmConstraints(chain, constraints);
try {
checker.init(false);
// a forward checker, need to check from trust to target
for (int i = chain.length - 1; i >= 0; i--) {
Certificate cert = chain[i];
// We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet());
}
} catch (CertPathValidatorException cpve) {
throw new CertificateException(
"Certificates does not conform to algorithm constraints");
}
} }
} }
...@@ -918,22 +910,35 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager ...@@ -918,22 +910,35 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(engine, true); constraints = new SSLAlgorithmConstraints(engine, true);
} }
AlgorithmChecker checker = new AlgorithmChecker(constraints); checkAlgorithmConstraints(chain, constraints);
}
}
private void checkAlgorithmConstraints(X509Certificate[] chain,
AlgorithmConstraints constraints) throws CertificateException {
try { try {
checker.init(false); // Does the certificate chain end with a trusted certificate?
int checkedLength = chain.length - 1;
if (trustedCerts.contains(chain[checkedLength])) {
checkedLength--;
}
// A forward checker, need to check from trust to target // A forward checker, need to check from trust to target
for (int i = chain.length - 1; i >= 0; i--) { if (checkedLength >= 0) {
AlgorithmChecker checker = new AlgorithmChecker(constraints);
checker.init(false);
for (int i = checkedLength; i >= 0; i--) {
Certificate cert = chain[i]; Certificate cert = chain[i];
// We don't care about the unresolved critical extensions. // We don't care about the unresolved critical extensions.
checker.check(cert, Collections.<String>emptySet()); checker.check(cert, Collections.<String>emptySet());
} }
}
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
throw new CertificateException( throw new CertificateException(
"Certificates does not conform to algorithm constraints"); "Certificates does not conform to algorithm constraints");
} }
} }
}
} }
// Dummy X509TrustManager implementation, rejects all peer certificates. // Dummy X509TrustManager implementation, rejects all peer certificates.
......
...@@ -1485,7 +1485,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl { ...@@ -1485,7 +1485,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
private void closeSocket(boolean selfInitiated) throws IOException { private void closeSocket(boolean selfInitiated) throws IOException {
if ((debug != null) && Debug.isOn("ssl")) { if ((debug != null) && Debug.isOn("ssl")) {
System.out.println(threadName() + ", called closeSocket(selfInitiated)"); System.out.println(threadName() +
", called closeSocket(" + selfInitiated + ")");
} }
if (self == this) { if (self == this) {
super.close(); super.close();
......
...@@ -33,18 +33,7 @@ import java.security.*; ...@@ -33,18 +33,7 @@ import java.security.*;
import java.util.Date; import java.util.Date;
import sun.security.pkcs10.PKCS10; import sun.security.pkcs10.PKCS10;
import sun.security.x509.AlgorithmId; import sun.security.x509.*;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateSubjectName;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import sun.security.x509.X509Key;
/** /**
...@@ -165,6 +154,13 @@ public final class CertAndKeyGen { ...@@ -165,6 +154,13 @@ public final class CertAndKeyGen {
publicKey = pair.getPublic(); publicKey = pair.getPublic();
privateKey = pair.getPrivate(); privateKey = pair.getPrivate();
// publicKey's format must be X.509 otherwise
// the whole CertGen part of this class is broken.
if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) {
throw new IllegalArgumentException("publicKey's is not X.509, but "
+ publicKey.getFormat());
}
} }
...@@ -186,6 +182,16 @@ public final class CertAndKeyGen { ...@@ -186,6 +182,16 @@ public final class CertAndKeyGen {
return (X509Key)publicKey; return (X509Key)publicKey;
} }
/**
* Always returns the public key of the generated key pair. Used
* by KeyTool only.
*
* The publicKey is not necessarily to be an instance of
* X509Key in some JCA/JCE providers, for example SunPKCS11.
*/
public PublicKey getPublicKeyAnyway() {
return publicKey;
}
/** /**
* Returns the private key of the generated key pair. * Returns the private key of the generated key pair.
...@@ -200,7 +206,6 @@ public final class CertAndKeyGen { ...@@ -200,7 +206,6 @@ public final class CertAndKeyGen {
return privateKey; return privateKey;
} }
/** /**
* Returns a self-signed X.509v3 certificate for the public key. * Returns a self-signed X.509v3 certificate for the public key.
* The certificate is immediately valid. No extensions. * The certificate is immediately valid. No extensions.
...@@ -224,6 +229,15 @@ public final class CertAndKeyGen { ...@@ -224,6 +229,15 @@ public final class CertAndKeyGen {
X500Name myname, Date firstDate, long validity) X500Name myname, Date firstDate, long validity)
throws CertificateException, InvalidKeyException, SignatureException, throws CertificateException, InvalidKeyException, SignatureException,
NoSuchAlgorithmException, NoSuchProviderException NoSuchAlgorithmException, NoSuchProviderException
{
return getSelfCertificate(myname, firstDate, validity, null);
}
// Like above, plus a CertificateExtensions argument, which can be null.
public X509Certificate getSelfCertificate (X500Name myname, Date firstDate,
long validity, CertificateExtensions ext)
throws CertificateException, InvalidKeyException, SignatureException,
NoSuchAlgorithmException, NoSuchProviderException
{ {
X509CertImpl cert; X509CertImpl cert;
Date lastDate; Date lastDate;
...@@ -248,6 +262,7 @@ public final class CertAndKeyGen { ...@@ -248,6 +262,7 @@ public final class CertAndKeyGen {
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
info.set(X509CertInfo.VALIDITY, interval); info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname)); info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
cert = new X509CertImpl(info); cert = new X509CertImpl(info);
cert.sign(privateKey, this.sigAlg); cert.sign(privateKey, this.sigAlg);
......
...@@ -1518,9 +1518,16 @@ public final class KeyTool { ...@@ -1518,9 +1518,16 @@ public final class KeyTool {
keypair.generate(keysize); keypair.generate(keysize);
PrivateKey privKey = keypair.getPrivateKey(); PrivateKey privKey = keypair.getPrivateKey();
CertificateExtensions ext = createV3Extensions(
null,
null,
v3ext,
keypair.getPublicKeyAnyway(),
null);
X509Certificate[] chain = new X509Certificate[1]; X509Certificate[] chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate( chain[0] = keypair.getSelfCertificate(
x500Name, getStartDate(startDate), validity*24L*60L*60L); x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
if (verbose) { if (verbose) {
MessageFormat form = new MessageFormat(rb.getString MessageFormat form = new MessageFormat(rb.getString
...@@ -1537,9 +1544,6 @@ public final class KeyTool { ...@@ -1537,9 +1544,6 @@ public final class KeyTool {
keyPass = promptForKeyPass(alias, null, storePass); keyPass = promptForKeyPass(alias, null, storePass);
} }
keyStore.setKeyEntry(alias, privKey, keyPass, chain); keyStore.setKeyEntry(alias, privKey, keyPass, chain);
// resign so that -ext are applied.
doSelfCert(alias, null, sigAlgName);
} }
/** /**
......
...@@ -59,13 +59,8 @@ typedef double mlib_d64; ...@@ -59,13 +59,8 @@ typedef double mlib_d64;
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__GNUC__) #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__GNUC__)
#if defined(__linux__) #include <stdint.h>
#include <stdint.h> /* for uintptr_t */ #include <stddef.h>
#include <malloc.h> /* for ptrdiff_t */
#else
#include <link.h> /* for uintptr_t */
#include <stddef.h> /* for ptrdiff_t */
#endif /* __linux__ */
#ifdef MLIB_OS64BIT #ifdef MLIB_OS64BIT
......
/* /*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
package java.io; package java.io;
import java.util.concurrent.atomic.AtomicInteger; import java.util.ArrayList;
import java.util.List;
/** /**
* Instances of the file descriptor class serve as an opaque handle * Instances of the file descriptor class serve as an opaque handle
...@@ -46,12 +47,9 @@ public final class FileDescriptor { ...@@ -46,12 +47,9 @@ public final class FileDescriptor {
private int fd; private int fd;
/** private Closeable parent;
* A counter for tracking the FIS/FOS/RAF instances that private List<Closeable> otherParents;
* use this FileDescriptor. The FIS/FOS.finalize() will not release private boolean closed;
* the FileDescriptor if it is still under user by a stream.
*/
private AtomicInteger useCount;
/** /**
* Constructs an (invalid) FileDescriptor * Constructs an (invalid) FileDescriptor
...@@ -59,12 +57,10 @@ public final class FileDescriptor { ...@@ -59,12 +57,10 @@ public final class FileDescriptor {
*/ */
public /**/ FileDescriptor() { public /**/ FileDescriptor() {
fd = -1; fd = -1;
useCount = new AtomicInteger();
} }
private /* */ FileDescriptor(int fd) { private /* */ FileDescriptor(int fd) {
this.fd = fd; this.fd = fd;
useCount = new AtomicInteger();
} }
/** /**
...@@ -164,13 +160,67 @@ public final class FileDescriptor { ...@@ -164,13 +160,67 @@ public final class FileDescriptor {
); );
} }
// package private methods used by FIS, FOS and RAF /*
* Package private methods to track referents.
* If multiple streams point to the same FileDescriptor, we cycle
* through the list of all referents and call close()
*/
int incrementAndGetUseCount() { /**
return useCount.incrementAndGet(); * Attach a Closeable to this FD for tracking.
* parent reference is added to otherParents when
* needed to make closeAll simpler.
*/
synchronized void attach(Closeable c) {
if (parent == null) {
// first caller gets to do this
parent = c;
} else if (otherParents == null) {
otherParents = new ArrayList<>();
otherParents.add(parent);
otherParents.add(c);
} else {
otherParents.add(c);
}
} }
int decrementAndGetUseCount() { /**
return useCount.decrementAndGet(); * Cycle through all Closeables sharing this FD and call
* close() on each one.
*
* The caller closeable gets to call close0().
*/
@SuppressWarnings("try")
synchronized void closeAll(Closeable releaser) throws IOException {
if (!closed) {
closed = true;
IOException ioe = null;
try (Closeable c = releaser) {
if (otherParents != null) {
for (Closeable referent : otherParents) {
try {
referent.close();
} catch(IOException x) {
if (ioe == null) {
ioe = x;
} else {
ioe.addSuppressed(x);
}
}
}
}
} catch(IOException ex) {
/*
* If releaser close() throws IOException
* add other exceptions as suppressed.
*/
if (ioe != null)
ex.addSuppressed(ioe);
ioe = ex;
} finally {
if (ioe != null)
throw ioe;
}
}
} }
} }
...@@ -43,8 +43,9 @@ ...@@ -43,8 +43,9 @@
#include "java_net_Inet4AddressImpl.h" #include "java_net_Inet4AddressImpl.h"
/* the initial size of our hostent buffers */ /* the initial size of our hostent buffers */
#define HENT_BUF_SIZE 1024 #ifndef NI_MAXHOST
#define BIG_HENT_BUF_SIZE 10240 /* a jumbo-sized one */ #define NI_MAXHOST 1025
#endif
/************************************************************************ /************************************************************************
* Inet4AddressImpl * Inet4AddressImpl
...@@ -57,60 +58,36 @@ ...@@ -57,60 +58,36 @@
*/ */
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[MAXHOSTNAMELEN+1]; char hostname[NI_MAXHOST+1];
hostname[0] = '\0'; hostname[0] = '\0';
if (JVM_GetHostName(hostname, sizeof(hostname))) { if (JVM_GetHostName(hostname, sizeof(hostname))) {
/* Something went wrong, maybe networking is not setup? */ /* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost"); strcpy(hostname, "localhost");
} else { } else {
#ifdef __linux__ struct addrinfo hints, *res;
/* On Linux gethostname() says "host.domain.sun.com". On int error;
* Solaris gethostname() says "host", so extra work is needed.
*/ hostname[NI_MAXHOST] = '\0';
#else memset(&hints, 0, sizeof(hints));
/* Solaris doesn't want to give us a fully qualified domain name. hints.ai_flags = AI_CANONNAME;
* We do a reverse lookup to try and get one. This works hints.ai_family = AF_INET;
* if DNS occurs before NIS in /etc/resolv.conf, but fails
* if NIS comes first (it still gets only a partial name). error = getaddrinfo(hostname, NULL, &hints, &res);
* We use thread-safe system calls.
*/ if (error == 0) {/* host is known to name service */
#endif /* __linux__ */ getnameinfo(res->ai_addr,
struct hostent res, res2, *hp; res->ai_addrlen,
// these buffers must be pointer-aligned so they are declared hostname,
// with pointer type NI_MAXHOST,
char *buf[HENT_BUF_SIZE/(sizeof (char *))]; NULL,
char *buf2[HENT_BUF_SIZE/(sizeof (char *))]; 0,
int h_error=0; NI_NAMEREQD);
// ensure null-terminated /* if getnameinfo fails hostname is still the value
hostname[MAXHOSTNAMELEN] = '\0'; from gethostname */
#ifdef __GLIBC__ freeaddrinfo(res);
gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
#else
hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
#endif
if (hp) {
#ifdef __GLIBC__
gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
&res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
#else
hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
&res2, (char*)buf2, sizeof(buf2), &h_error);
#endif
if (hp) {
/*
* If gethostbyaddr_r() found a fully qualified host name,
* returns that name. Otherwise, returns the hostname
* found by gethostname().
*/
char *p = hp->h_name;
if ((strlen(hp->h_name) > strlen(hostname))
&& (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
&& (*(p + strlen(hostname)) == '.'))
strcpy(hostname, hp->h_name);
}
} }
} }
return (*env)->NewStringUTF(env, hostname); return (*env)->NewStringUTF(env, hostname);
...@@ -140,14 +117,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -140,14 +117,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
jstring host) { jstring host) {
const char *hostname; const char *hostname;
jobjectArray ret = 0; jobjectArray ret = 0;
struct hostent res, *hp = 0; int retLen = 0;
// this buffer must be pointer-aligned so is declared int error = 0;
// with pointer type struct addrinfo hints, *res, *resNew = NULL;
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
/* temporary buffer, on the off chance we need to expand */
char *tmp = NULL;
int h_error=0;
if (!initialized) { if (!initialized) {
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress"); ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
...@@ -168,6 +140,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -168,6 +140,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
CHECK_NULL_RETURN(hostname, NULL); CHECK_NULL_RETURN(hostname, NULL);
/* Try once, with our static buffer. */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
#ifdef __solaris__ #ifdef __solaris__
/* /*
* Workaround for Solaris bug 4160367 - if a hostname contains a * Workaround for Solaris bug 4160367 - if a hostname contains a
...@@ -181,69 +158,93 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -181,69 +158,93 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
} }
#endif #endif
/* Try once, with our static buffer. */ error = getaddrinfo(hostname, NULL, &hints, &res);
#ifdef __GLIBC__
gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
#else
hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
#endif
/* With the re-entrant system calls, it's possible that the buffer if (error) {
* we pass to it is not large enough to hold an exceptionally /* report error */
* large DNS entry. This is signaled by errno->ERANGE. We try once ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
* more, with a very big size. JNU_ReleaseStringPlatformChars(env, host, hostname);
*/ return NULL;
if (hp == NULL && errno == ERANGE) { } else {
if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) { int i = 0;
#ifdef __GLIBC__ struct addrinfo *itr, *last = NULL, *iterator = res;
gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
&hp, &h_error); while (iterator != NULL) {
#else // remove the duplicate one
hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE, int skip = 0;
&h_error); itr = resNew;
#endif while (itr != NULL) {
struct sockaddr_in *addr1, *addr2;
addr1 = (struct sockaddr_in *)iterator->ai_addr;
addr2 = (struct sockaddr_in *)itr->ai_addr;
if (addr1->sin_addr.s_addr ==
addr2->sin_addr.s_addr) {
skip = 1;
break;
}
itr = itr->ai_next;
}
if (!skip) {
struct addrinfo *next
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
if (!next) {
JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
ret = NULL;
goto cleanupAndReturn;
} }
memcpy(next, iterator, sizeof(struct addrinfo));
next->ai_next = NULL;
if (resNew == NULL) {
resNew = next;
} else {
last->ai_next = next;
} }
if (hp != NULL) { last = next;
struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
int i = 0;
while (*addrp != (struct in_addr *) 0) {
i++; i++;
addrp++;
} }
iterator = iterator->ai_next;
}
retLen = i;
iterator = resNew;
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
if (IS_NULL(ret)) { if (IS_NULL(ret)) {
/* we may have memory to free at the end of this */ /* we may have memory to free at the end of this */
goto cleanupAndReturn; goto cleanupAndReturn;
} }
addrp = (struct in_addr **) hp->h_addr_list;
i = 0; i = 0;
while (*addrp) { while (iterator != NULL) {
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
ret = NULL; ret = NULL;
goto cleanupAndReturn; goto cleanupAndReturn;
} }
(*env)->SetIntField(env, iaObj, ni_iaaddressID, (*env)->SetIntField(env, iaObj, ni_iaaddressID,
ntohl((*addrp)->s_addr)); ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
(*env)->SetObjectField(env, iaObj, ni_iahostID, host); (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
(*env)->SetObjectArrayElement(env, ret, i, iaObj); (*env)->SetObjectArrayElement(env, ret, i++, iaObj);
addrp++; iterator = iterator->ai_next;
i++;
} }
} else {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
(char *)hostname);
ret = NULL;
} }
cleanupAndReturn: cleanupAndReturn:
JNU_ReleaseStringPlatformChars(env, host, hostname); {
if (tmp != NULL) { struct addrinfo *iterator, *tmp;
iterator = resNew;
while (iterator != NULL) {
tmp = iterator;
iterator = iterator->ai_next;
free(tmp); free(tmp);
} }
JNU_ReleaseStringPlatformChars(env, host, hostname);
}
freeaddrinfo(res);
return ret; return ret;
} }
...@@ -256,63 +257,38 @@ JNIEXPORT jstring JNICALL ...@@ -256,63 +257,38 @@ JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this, Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
jbyteArray addrArray) { jbyteArray addrArray) {
jstring ret = NULL; jstring ret = NULL;
jint addr;
struct hostent hent, *hp = 0;
// this buffer must be pointer-aligned so is declared
// with pointer type
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
int h_error = 0;
char *tmp = NULL;
/* char host[NI_MAXHOST+1];
* We are careful here to use the reentrant version of int error = 0;
* gethostbyname because at the Java level this routine is not int len = 0;
* protected by any synchronization.
*
* Still keeping the reentrant platform dependent calls temporarily
* We should probably conform to one interface later.
*
*/
jbyte caddr[4]; jbyte caddr[4];
struct sockaddr_in him4;
struct sockaddr *sa;
jint addr;
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
addr = ((caddr[0]<<24) & 0xff000000); addr = ((caddr[0]<<24) & 0xff000000);
addr |= ((caddr[1] <<16) & 0xff0000); addr |= ((caddr[1] <<16) & 0xff0000);
addr |= ((caddr[2] <<8) & 0xff00); addr |= ((caddr[2] <<8) & 0xff00);
addr |= (caddr[3] & 0xff); addr |= (caddr[3] & 0xff);
addr = htonl(addr); memset((void *) &him4, 0, sizeof(him4));
#ifdef __GLIBC__ him4.sin_addr.s_addr = (uint32_t) htonl(addr);
gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent, him4.sin_family = AF_INET;
(char*)buf, sizeof(buf), &hp, &h_error); sa = (struct sockaddr *) &him4;
#else len = sizeof(him4);
hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
(char*)buf, sizeof(buf), &h_error); error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
#endif NI_NAMEREQD);
/* With the re-entrant system calls, it's possible that the buffer
* we pass to it is not large enough to hold an exceptionally if (!error) {
* large DNS entry. This is signaled by errno->ERANGE. We try once ret = (*env)->NewStringUTF(env, host);
* more, with a very big size.
*/
if (hp == NULL && errno == ERANGE) {
if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
#ifdef __GLIBC__
gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
&hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
#else
hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
&hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
#endif
} else {
JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
}
} }
if (hp == NULL) {
if (ret == NULL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL); JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
} else {
ret = (*env)->NewStringUTF(env, hp->h_name);
}
if (tmp) {
free(tmp);
} }
return ret; return ret;
} }
......
...@@ -82,19 +82,18 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { ...@@ -82,19 +82,18 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
* We use thread-safe system calls. * We use thread-safe system calls.
*/ */
#ifdef AF_INET6 #ifdef AF_INET6
if (NET_addrtransAvailable()) {
struct addrinfo hints, *res; struct addrinfo hints, *res;
int error; int error;
bzero(&hints, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME; hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); error = getaddrinfo(hostname, NULL, &hints, &res);
if (error == 0) { if (error == 0) {
/* host is known to name service */ /* host is known to name service */
error = (*getnameinfo_ptr)(res->ai_addr, error = getnameinfo(res->ai_addr,
res->ai_addrlen, res->ai_addrlen,
hostname, hostname,
NI_MAXHOST, NI_MAXHOST,
...@@ -105,8 +104,7 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) { ...@@ -105,8 +104,7 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
/* if getnameinfo fails hostname is still the value /* if getnameinfo fails hostname is still the value
from gethostname */ from gethostname */
(*freeaddrinfo_ptr)(res); freeaddrinfo(res);
}
} }
#endif /* AF_INET6 */ #endif /* AF_INET6 */
#endif /* __linux__ */ #endif /* __linux__ */
...@@ -173,7 +171,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -173,7 +171,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
CHECK_NULL_RETURN(hostname, NULL); CHECK_NULL_RETURN(hostname, NULL);
#ifdef AF_INET6 #ifdef AF_INET6
if (NET_addrtransAvailable()) {
static jfieldID ia_preferIPv6AddressID; static jfieldID ia_preferIPv6AddressID;
if (ia_preferIPv6AddressID == NULL) { if (ia_preferIPv6AddressID == NULL) {
jclass c = (*env)->FindClass(env,"java/net/InetAddress"); jclass c = (*env)->FindClass(env,"java/net/InetAddress");
...@@ -191,7 +188,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -191,7 +188,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID); = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
/* Try once, with our static buffer. */ /* Try once, with our static buffer. */
bzero(&hints, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME; hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
...@@ -208,7 +205,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -208,7 +205,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
} }
#endif #endif
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res); error = getaddrinfo(hostname, NULL, &hints, &res);
if (error) { if (error) {
/* report error */ /* report error */
...@@ -355,9 +352,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ...@@ -355,9 +352,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
iterator = iterator->ai_next; iterator = iterator->ai_next;
} }
} }
}
cleanupAndReturn: cleanupAndReturn:
{ {
struct addrinfo *iterator, *tmp; struct addrinfo *iterator, *tmp;
iterator = resNew; iterator = resNew;
...@@ -369,8 +365,7 @@ cleanupAndReturn: ...@@ -369,8 +365,7 @@ cleanupAndReturn:
JNU_ReleaseStringPlatformChars(env, host, hostname); JNU_ReleaseStringPlatformChars(env, host, hostname);
} }
if (NET_addrtransAvailable()) freeaddrinfo(res);
(*freeaddrinfo_ptr)(res);
#endif /* AF_INET6 */ #endif /* AF_INET6 */
return ret; return ret;
...@@ -393,7 +388,6 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, ...@@ -393,7 +388,6 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
int len = 0; int len = 0;
jbyte caddr[16]; jbyte caddr[16];
if (NET_addrtransAvailable()) {
struct sockaddr_in him4; struct sockaddr_in him4;
struct sockaddr_in6 him6; struct sockaddr_in6 him6;
struct sockaddr *sa; struct sockaddr *sa;
...@@ -425,13 +419,12 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, ...@@ -425,13 +419,12 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
len = sizeof(him6) ; len = sizeof(him6) ;
} }
error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0, error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
NI_NAMEREQD); NI_NAMEREQD);
if (!error) { if (!error) {
ret = (*env)->NewStringUTF(env, host); ret = (*env)->NewStringUTF(env, host);
} }
}
#endif /* AF_INET6 */ #endif /* AF_INET6 */
if (ret == NULL) { if (ret == NULL) {
......
...@@ -377,37 +377,12 @@ jint IPv6_supported() ...@@ -377,37 +377,12 @@ jint IPv6_supported()
* we should also check if the APIs are available. * we should also check if the APIs are available.
*/ */
ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton"); ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
if (ipv6_fn == NULL ) {
close(fd); close(fd);
if (ipv6_fn == NULL ) {
return JNI_FALSE; return JNI_FALSE;
} } else {
/*
* We've got the library, let's get the pointers to some
* IPV6 specific functions. We have to do that because, at least
* on Solaris we may build on a system without IPV6 networking
* libraries, therefore we can't have a hard link to these
* functions.
*/
getaddrinfo_ptr = (getaddrinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
freeaddrinfo_ptr = (freeaddrinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
gai_strerror_ptr = (gai_strerror_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
getnameinfo_ptr = (getnameinfo_f)
JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
/* We need all 3 of them */
getaddrinfo_ptr = NULL;
}
close(fd);
return JNI_TRUE; return JNI_TRUE;
}
#endif /* AF_INET6 */ #endif /* AF_INET6 */
} }
...@@ -920,10 +895,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) { ...@@ -920,10 +895,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
return 1; return 1;
} }
jboolean NET_addrtransAvailable() {
return (jboolean)(getaddrinfo_ptr != NULL);
}
/* /*
* Map the Java level socket option to the platform specific * Map the Java level socket option to the platform specific
* level and option name. * level and option name.
......
...@@ -102,10 +102,6 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, ...@@ -102,10 +102,6 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
const char* hostname, const char* hostname,
int gai_error); int gai_error);
/* do we have address translation support */
extern jboolean NET_addrtransAvailable();
#define NET_WAIT_READ 0x01 #define NET_WAIT_READ 0x01
#define NET_WAIT_WRITE 0x02 #define NET_WAIT_WRITE 0x02
#define NET_WAIT_CONNECT 0x04 #define NET_WAIT_CONNECT 0x04
......
/* /*
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
package java.io; package java.io;
import java.util.concurrent.atomic.AtomicInteger; import java.util.ArrayList;
import java.util.List;
/** /**
* Instances of the file descriptor class serve as an opaque handle * Instances of the file descriptor class serve as an opaque handle
...@@ -45,13 +46,9 @@ public final class FileDescriptor { ...@@ -45,13 +46,9 @@ public final class FileDescriptor {
private long handle; private long handle;
/** private Closeable parent;
* A use counter for tracking the FIS/FOS/RAF instances that private List<Closeable> otherParents;
* use this FileDescriptor. The FIS/FOS.finalize() will not release private boolean closed;
* the FileDescriptor if it is still under use by any stream.
*/
private AtomicInteger useCount;
/** /**
* Constructs an (invalid) FileDescriptor * Constructs an (invalid) FileDescriptor
...@@ -60,7 +57,6 @@ public final class FileDescriptor { ...@@ -60,7 +57,6 @@ public final class FileDescriptor {
public /**/ FileDescriptor() { public /**/ FileDescriptor() {
fd = -1; fd = -1;
handle = -1; handle = -1;
useCount = new AtomicInteger();
} }
static { static {
...@@ -168,13 +164,67 @@ public final class FileDescriptor { ...@@ -168,13 +164,67 @@ public final class FileDescriptor {
return desc; return desc;
} }
// package private methods used by FIS, FOS and RAF. /*
* Package private methods to track referents.
* If multiple streams point to the same FileDescriptor, we cycle
* through the list of all referents and call close()
*/
int incrementAndGetUseCount() { /**
return useCount.incrementAndGet(); * Attach a Closeable to this FD for tracking.
* parent reference is added to otherParents when
* needed to make closeAll simpler.
*/
synchronized void attach(Closeable c) {
if (parent == null) {
// first caller gets to do this
parent = c;
} else if (otherParents == null) {
otherParents = new ArrayList<>();
otherParents.add(parent);
otherParents.add(c);
} else {
otherParents.add(c);
}
} }
int decrementAndGetUseCount() { /**
return useCount.decrementAndGet(); * Cycle through all Closeables sharing this FD and call
* close() on each one.
*
* The caller closeable gets to call close0().
*/
@SuppressWarnings("try")
synchronized void closeAll(Closeable releaser) throws IOException {
if (!closed) {
closed = true;
IOException ioe = null;
try (Closeable c = releaser) {
if (otherParents != null) {
for (Closeable referent : otherParents) {
try {
referent.close();
} catch(IOException x) {
if (ioe == null) {
ioe = x;
} else {
ioe.addSuppressed(x);
}
}
}
}
} catch(IOException ex) {
/*
* If releaser close() throws IOException
* add other exceptions as suppressed.
*/
if (ioe != null)
ex.addSuppressed(ioe);
ioe = ex;
} finally {
if (ioe != null)
throw ioe;
}
}
} }
} }
...@@ -314,7 +314,7 @@ class PlainSocketImpl extends AbstractPlainSocketImpl ...@@ -314,7 +314,7 @@ class PlainSocketImpl extends AbstractPlainSocketImpl
void socketSetOption(int cmd, boolean on, Object value) void socketSetOption(int cmd, boolean on, Object value)
throws SocketException { throws SocketException {
socketSetOption(cmd, on, value); impl.socketSetOption(cmd, on, value);
} }
int socketGetOption(int opt, Object iaContainerObj) throws SocketException { int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
......
...@@ -207,7 +207,7 @@ public class Klist { ...@@ -207,7 +207,7 @@ public class Klist {
} }
if (options[2] == 't') { if (options[2] == 't') {
System.out.println("\t Time stamp: " + System.out.println("\t Time stamp: " +
reformat(entries[i].getTimeStamp().toDate().toString())); format(entries[i].getTimeStamp()));
} }
} }
} }
...@@ -234,17 +234,19 @@ public class Klist { ...@@ -234,17 +234,19 @@ public class Klist {
System.out.println("\nDefault principal: " + System.out.println("\nDefault principal: " +
defaultPrincipal + ", " + defaultPrincipal + ", " +
creds.length + " entries found.\n"); creds.length + " entries found.\n");
String starttime = null;
String endtime = null;
String servicePrincipal = null;
String etype = null;
if (creds != null) { if (creds != null) {
for (int i = 0; i < creds.length; i++) { for (int i = 0; i < creds.length; i++) {
try { try {
starttime = String starttime;
reformat(creds[i].getAuthTime().toDate().toString()); String endtime;
endtime = String renewTill;
reformat(creds[i].getEndTime().toDate().toString()); String servicePrincipal;
if (creds[i].getStartTime() != null) {
starttime = format(creds[i].getStartTime());
} else {
starttime = format(creds[i].getAuthTime());
}
endtime = format(creds[i].getEndTime());
servicePrincipal = servicePrincipal =
creds[i].getServicePrincipal().toString(); creds[i].getServicePrincipal().toString();
System.out.println("[" + (i + 1) + "] " + System.out.println("[" + (i + 1) + "] " +
...@@ -252,9 +254,16 @@ public class Klist { ...@@ -252,9 +254,16 @@ public class Klist {
servicePrincipal); servicePrincipal);
System.out.println(" Valid starting: " + starttime); System.out.println(" Valid starting: " + starttime);
System.out.println(" Expires: " + endtime); System.out.println(" Expires: " + endtime);
if (creds[i].getRenewTill() != null) {
renewTill = format(creds[i].getRenewTill());
System.out.println(
" Renew until: " + renewTill);
}
if (options[0] == 'e') { if (options[0] == 'e') {
etype = EType.toString(creds[i].getEType()); String eskey = EType.toString(creds[i].getEType());
System.out.println(" Encryption type: " + etype); String etkt = EType.toString(creds[i].getTktEType());
System.out.println(" EType (skey, tkt): "
+ eskey + ", " + etkt);
} }
if (options[1] == 'f') { if (options[1] == 'f') {
System.out.println(" Flags: " + System.out.println(" Flags: " +
...@@ -312,13 +321,14 @@ public class Klist { ...@@ -312,13 +321,14 @@ public class Klist {
* and yyyy is the year. * and yyyy is the year.
* @param date the string form of Date object. * @param date the string form of Date object.
*/ */
String reformat(String date) { private String format(KerberosTime kt) {
String date = kt.toDate().toString();
return (date.substring(4, 7) + " " + date.substring(8, 10) + return (date.substring(4, 7) + " " + date.substring(8, 10) +
", " + date.substring(24) ", " + date.substring(24)
+ " " + date.substring(11, 16)); + " " + date.substring(11, 19));
} }
/** /**
* Printes out the help information. * Prints out the help information.
*/ */
void printHelp() { void printHelp() {
System.out.println("\nUsage: klist " + System.out.println("\nUsage: klist " +
......
...@@ -167,7 +167,7 @@ Greenwich Standard Time:88,89::GMT: ...@@ -167,7 +167,7 @@ Greenwich Standard Time:88,89::GMT:
Argentina Standard Time:900,900::America/Buenos_Aires: Argentina Standard Time:900,900::America/Buenos_Aires:
Azerbaijan Standard Time:901,901:AZ:Asia/Baku: Azerbaijan Standard Time:901,901:AZ:Asia/Baku:
Bangladesh Standard Time:902,902::Asia/Dhaka: Bangladesh Standard Time:902,902::Asia/Dhaka:
Central Brazilian Standard Time:903,903:BR:America/Manaus: Central Brazilian Standard Time:903,903:BR:America/Cuiaba:
Central Standard Time (Mexico):904,904::America/Mexico_City: Central Standard Time (Mexico):904,904::America/Mexico_City:
Georgian Standard Time:905,905:GE:Asia/Tbilisi: Georgian Standard Time:905,905:GE:Asia/Tbilisi:
Jordan Standard Time:906,906:JO:Asia/Amman: Jordan Standard Time:906,906:JO:Asia/Amman:
...@@ -189,5 +189,7 @@ UTC-11:921,921::GMT-1100: ...@@ -189,5 +189,7 @@ UTC-11:921,921::GMT-1100:
Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar: Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar:
Venezuela Standard Time:923,923::America/Caracas: Venezuela Standard Time:923,923::America/Caracas:
Magadan Standard Time:924,924::Asia/Magadan: Magadan Standard Time:924,924::Asia/Magadan:
Western Brazilian Standard Time:925,925:BR:America/Rio_Branco: Kaliningrad Standard Time:925,925:RU:Europe/Kaliningrad:
Armenian Standard Time:926,926:AM:Asia/Yerevan: Turkey Standard Time:926,926::Asia/Istanbul:
Western Brazilian Standard Time:927,927:BR:America/Rio_Branco:
Armenian Standard Time:928,928:AM:Asia/Yerevan:
...@@ -23,10 +23,9 @@ ...@@ -23,10 +23,9 @@
/* /*
* @test * @test
* @bug 6322678 7082769 * @bug 7105952 6322678 7082769
* @summary FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor * @summary Improve finalisation for FileInputStream/FileOutputStream/RandomAccessFile
* to be closed while still in use. * @run main/othervm Sharing
* @run main/othervm FileDescriptorSharing
*/ */
import java.io.*; import java.io.*;
...@@ -34,7 +33,7 @@ import java.nio.channels.FileChannel; ...@@ -34,7 +33,7 @@ import java.nio.channels.FileChannel;
import java.nio.channels.FileLock; import java.nio.channels.FileLock;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
public class FileDescriptorSharing { public class Sharing {
final static int numFiles = 10; final static int numFiles = 10;
volatile static boolean fail; volatile static boolean fail;
...@@ -44,11 +43,12 @@ public class FileDescriptorSharing { ...@@ -44,11 +43,12 @@ public class FileDescriptorSharing {
TestMultipleFD(); TestMultipleFD();
TestIsValid(); TestIsValid();
MultiThreadedFD(); MultiThreadedFD();
TestCloseAll();
} }
/** /**
* We shouldn't discard a file descriptor until all streams have * Finalizer shouldn't discard a file descriptor until all streams have
* finished with it * finished with it.
*/ */
private static void TestFinalizer() throws Exception { private static void TestFinalizer() throws Exception {
FileDescriptor fd = null; FileDescriptor fd = null;
...@@ -96,9 +96,6 @@ public class FileDescriptorSharing { ...@@ -96,9 +96,6 @@ public class FileDescriptorSharing {
System.out.print("."); System.out.print(".");
ret = fis3.read(); ret = fis3.read();
} }
if(!fd.valid()) {
throw new RuntimeException("TestFinalizer() : FileDescriptor should be valid");
}
} finally { } finally {
testFinalizerFile.delete(); testFinalizerFile.delete();
} }
...@@ -194,23 +191,19 @@ public class FileDescriptorSharing { ...@@ -194,23 +191,19 @@ public class FileDescriptorSharing {
} finally { } finally {
try { try {
if (fis != null) fis.close(); if (fis != null) fis.close();
if (fos != null) fos.close();
if (!fd.valid()) {
throw new RuntimeException("FileDescriptor should be valid");
}
if (raf != null) raf.close();
if (fd.valid()) { if (fd.valid()) {
throw new RuntimeException("close() called and FileDescriptor still valid"); throw new RuntimeException("[FIS close()] FileDescriptor shouldn't be valid");
} }
} finally { if (fos != null) fos.close();
if (raf != null) raf.close(); if (raf != null) raf.close();
} finally {
test1.delete(); test1.delete();
} }
} }
/* /*
* Close out in different order to ensure FD is not * Close out in different order to ensure FD is
* closed out too early * closed correctly.
*/ */
File test2 = new File("test2"); File test2 = new File("test2");
try { try {
...@@ -221,14 +214,11 @@ public class FileDescriptorSharing { ...@@ -221,14 +214,11 @@ public class FileDescriptorSharing {
} finally { } finally {
try { try {
if (raf != null) raf.close(); if (raf != null) raf.close();
if (fos != null) fos.close();
if (!fd.valid()) {
throw new RuntimeException("FileDescriptor should be valid");
}
if (fis != null) fis.close();
if (fd.valid()) { if (fd.valid()) {
throw new RuntimeException("close() called and FileDescriptor still valid"); throw new RuntimeException("[RAF close()] FileDescriptor shouldn't be valid");
} }
if (fos != null) fos.close();
if (fis != null) fis.close();
} finally { } finally {
test2.delete(); test2.delete();
} }
...@@ -244,14 +234,11 @@ public class FileDescriptorSharing { ...@@ -244,14 +234,11 @@ public class FileDescriptorSharing {
} finally { } finally {
try { try {
if (fos != null) fos.close(); if (fos != null) fos.close();
if (raf != null) raf.close();
if (!fd.valid()) {
throw new RuntimeException("FileDescriptor should be valid");
}
if (fis != null) fis.close();
if (fd.valid()) { if (fd.valid()) {
throw new RuntimeException("close() called and FileDescriptor still valid"); throw new RuntimeException("[FOS close()] FileDescriptor shouldn't be valid");
} }
if (raf != null) raf.close();
if (fis != null) fis.close();
} finally { } finally {
test3.delete(); test3.delete();
} }
...@@ -259,7 +246,7 @@ public class FileDescriptorSharing { ...@@ -259,7 +246,7 @@ public class FileDescriptorSharing {
} }
/** /**
* Test concurrent access to the same fd.useCount field * Test concurrent access to the same FileDescriptor
*/ */
private static void MultiThreadedFD() throws Exception { private static void MultiThreadedFD() throws Exception {
RandomAccessFile raf = null; RandomAccessFile raf = null;
...@@ -293,6 +280,68 @@ public class FileDescriptorSharing { ...@@ -293,6 +280,68 @@ public class FileDescriptorSharing {
} }
} }
/**
* Test closeAll handling in FileDescriptor
*/
private static void TestCloseAll() throws Exception {
File testFile = new File("test");
testFile.deleteOnExit();
RandomAccessFile raf = new RandomAccessFile(testFile, "rw");
FileInputStream fis = new FileInputStream(raf.getFD());
fis.close();
if (raf.getFD().valid()) {
throw new RuntimeException("FD should not be valid.");
}
// Test the suppressed exception handling - FileInputStream
raf = new RandomAccessFile(testFile, "rw");
fis = new FileInputStream(raf.getFD());
BadFileInputStream bfis1 = new BadFileInputStream(raf.getFD());
BadFileInputStream bfis2 = new BadFileInputStream(raf.getFD());
BadFileInputStream bfis3 = new BadFileInputStream(raf.getFD());
// extra test - set bfis3 to null
bfis3 = null;
try {
fis.close();
} catch (IOException ioe) {
ioe.printStackTrace();
if (ioe.getSuppressed().length != 2) {
throw new RuntimeException("[FIS]Incorrect number of suppressed " +
"exceptions received : " + ioe.getSuppressed().length);
}
}
if (raf.getFD().valid()) {
// we should still have closed the FD
// even with the exception.
throw new RuntimeException("[FIS]TestCloseAll : FD still valid.");
}
// Now test with FileOutputStream
raf = new RandomAccessFile(testFile, "rw");
FileOutputStream fos = new FileOutputStream(raf.getFD());
BadFileOutputStream bfos1 = new BadFileOutputStream(raf.getFD());
BadFileOutputStream bfos2 = new BadFileOutputStream(raf.getFD());
BadFileOutputStream bfos3 = new BadFileOutputStream(raf.getFD());
// extra test - set bfos3 to null
bfos3 = null;
try {
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
if (ioe.getSuppressed().length != 2) {
throw new RuntimeException("[FOS]Incorrect number of suppressed " +
"exceptions received : " + ioe.getSuppressed().length);
}
}
if (raf.getFD().valid()) {
// we should still have closed the FD
// even with the exception.
throw new RuntimeException("[FOS]TestCloseAll : FD still valid.");
}
}
/** /**
* A thread which will open and close a number of FileInputStreams and * A thread which will open and close a number of FileInputStreams and
* FileOutputStreams referencing the same native file descriptor. * FileOutputStreams referencing the same native file descriptor.
...@@ -325,12 +374,35 @@ public class FileDescriptorSharing { ...@@ -325,12 +374,35 @@ public class FileDescriptorSharing {
System.out.println("OpenClose encountered IO issue :" + ioe); System.out.println("OpenClose encountered IO issue :" + ioe);
fail = true; fail = true;
} finally { } finally {
if (!fd.valid()) { // fd should still be valid given RAF reference if (fd.valid()) { // fd should not be valid after first close() call
System.out.println("OpenClose: FileDescriptor should be valid"); System.out.println("OpenClose: FileDescriptor shouldn't be valid");
fail = true; fail = true;
} }
done.countDown(); done.countDown();
} }
} }
} }
private static class BadFileInputStream extends FileInputStream {
BadFileInputStream(FileDescriptor fd) {
super(fd);
}
public void close() throws IOException {
throw new IOException("Bad close operation");
}
}
private static class BadFileOutputStream extends FileOutputStream {
BadFileOutputStream(FileDescriptor fd) {
super(fd);
}
public void close() throws IOException {
throw new IOException("Bad close operation");
}
}
} }
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
*/ */
import java.io.*; import java.io.*;
import java.util.concurrent.*;
public class StreamsSurviveDestroy { public class StreamsSurviveDestroy {
...@@ -40,15 +41,17 @@ public class StreamsSurviveDestroy { ...@@ -40,15 +41,17 @@ public class StreamsSurviveDestroy {
boolean wantInterrupt; boolean wantInterrupt;
boolean acceptException; boolean acceptException;
Exception exc = null; Exception exc = null;
CountDownLatch latch;
Copier(String name, InputStream in, OutputStream out, Copier(String name, InputStream in, OutputStream out,
boolean ae, boolean wi) boolean ae, boolean wi, CountDownLatch l)
{ {
this.name = name; this.name = name;
this.in = in; this.in = in;
this.out = out; this.out = out;
this.acceptException = ae; this.acceptException = ae;
this.wantInterrupt = wi; this.wantInterrupt = wi;
this.latch = l;
setName(name); setName(name);
start(); start();
} }
...@@ -59,6 +62,7 @@ public class StreamsSurviveDestroy { ...@@ -59,6 +62,7 @@ public class StreamsSurviveDestroy {
public void run() { public void run() {
byte[] buf = new byte[4242]; byte[] buf = new byte[4242];
latch.countDown();
for (;;) { for (;;) {
try { try {
int n = in.read(buf); int n = in.read(buf);
...@@ -95,13 +99,17 @@ public class StreamsSurviveDestroy { ...@@ -95,13 +99,17 @@ public class StreamsSurviveDestroy {
} }
static void test() throws Exception { static void test() throws Exception {
CountDownLatch latch = new CountDownLatch(2);
System.err.println("test"); System.err.println("test");
Process p = Runtime.getRuntime().exec("/bin/cat"); Process p = Runtime.getRuntime().exec("/bin/cat");
Copier cp1 = new Copier("out", p.getInputStream(), System.err, Copier cp1 = new Copier("out", p.getInputStream(), System.err,
false, false); false, false, latch);
Copier cp2 = new Copier("err", p.getErrorStream(), System.err, Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
false, false); false, false, latch);
Thread.sleep(100); latch.await(); // Wait till both Copiers about to read
Thread.sleep(100);// Give both Copiers a chance to start read
p.destroy(); p.destroy();
System.err.println(" exit: " + p.waitFor()); System.err.println(" exit: " + p.waitFor());
cp1.join(); cp1.join();
...@@ -111,13 +119,17 @@ public class StreamsSurviveDestroy { ...@@ -111,13 +119,17 @@ public class StreamsSurviveDestroy {
} }
static void testCloseBeforeDestroy() throws Exception { static void testCloseBeforeDestroy() throws Exception {
CountDownLatch latch = new CountDownLatch(2);
System.err.println("testCloseBeforeDestroy"); System.err.println("testCloseBeforeDestroy");
Process p = Runtime.getRuntime().exec("/bin/cat"); Process p = Runtime.getRuntime().exec("/bin/cat");
Copier cp1 = new Copier("out", p.getInputStream(), System.err, Copier cp1 = new Copier("out", p.getInputStream(), System.err,
true, false); true, false, latch);
Copier cp2 = new Copier("err", p.getErrorStream(), System.err, Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
true, false); true, false, latch);
Thread.sleep(100); latch.await(); // Wait till both Copiers about to read
Thread.sleep(100);// Give both Copiers a chance to start read
p.getInputStream().close(); p.getInputStream().close();
p.getErrorStream().close(); p.getErrorStream().close();
p.destroy(); p.destroy();
...@@ -129,13 +141,17 @@ public class StreamsSurviveDestroy { ...@@ -129,13 +141,17 @@ public class StreamsSurviveDestroy {
} }
static void testCloseAfterDestroy() throws Exception { static void testCloseAfterDestroy() throws Exception {
CountDownLatch latch = new CountDownLatch(2);
System.err.println("testCloseAfterDestroy"); System.err.println("testCloseAfterDestroy");
Process p = Runtime.getRuntime().exec("/bin/cat"); Process p = Runtime.getRuntime().exec("/bin/cat");
Copier cp1 = new Copier("out", p.getInputStream(), System.err, Copier cp1 = new Copier("out", p.getInputStream(), System.err,
true, false); true, false,latch);
Copier cp2 = new Copier("err", p.getErrorStream(), System.err, Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
true, false); true, false, latch);
Thread.sleep(100);
latch.await(); // Wait till both Copiers about to read
Thread.sleep(100);// Give both Copiers a chance to start read
p.destroy(); p.destroy();
p.getInputStream().close(); p.getInputStream().close();
p.getErrorStream().close(); p.getErrorStream().close();
...@@ -147,13 +163,16 @@ public class StreamsSurviveDestroy { ...@@ -147,13 +163,16 @@ public class StreamsSurviveDestroy {
} }
static void testInterrupt() throws Exception { static void testInterrupt() throws Exception {
CountDownLatch latch = new CountDownLatch(2);
System.err.println("testInterrupt"); System.err.println("testInterrupt");
Process p = Runtime.getRuntime().exec("/bin/cat"); Process p = Runtime.getRuntime().exec("/bin/cat");
Copier cp1 = new Copier("out", p.getInputStream(), System.err, Copier cp1 = new Copier("out", p.getInputStream(), System.err,
false, true); false, true, latch);
Copier cp2 = new Copier("err", p.getErrorStream(), System.err, Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
false, true); false, true, latch);
Thread.sleep(100); latch.await(); // Wait till both Copiers about to read
Thread.sleep(100);// Give both Copiers a chance to start read
cp1.interrupt(); cp1.interrupt();
cp2.interrupt(); cp2.interrupt();
Thread.sleep(100); Thread.sleep(100);
...@@ -176,7 +195,5 @@ public class StreamsSurviveDestroy { ...@@ -176,7 +195,5 @@ public class StreamsSurviveDestroy {
testCloseBeforeDestroy(); testCloseBeforeDestroy();
testCloseAfterDestroy(); testCloseAfterDestroy();
testInterrupt(); testInterrupt();
} }
} }
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
/* /*
* @test * @test
* @bug 6576763 * @bug 6576763
* @ignore until hotspot 6776144 bug is resolved
* @summary (thread) Thread constructors throw undocumented NPE for null name * @summary (thread) Thread constructors throw undocumented NPE for null name
*/ */
...@@ -64,8 +63,8 @@ public class NullThreadName ...@@ -64,8 +63,8 @@ public class NullThreadName
try { Thread.sleep(2000); } try { Thread.sleep(2000); }
catch (InterruptedException unused) {} catch (InterruptedException unused) {}
/* do not wait forever */ /* do not wait forever - allow 120 seconds same as jtreg default timeout. */
if (count++ > 5) if (count++ > 60)
throw new AssertionError("GoodThread is still alive!"); throw new AssertionError("GoodThread is still alive!");
} }
......
...@@ -29,37 +29,58 @@ ...@@ -29,37 +29,58 @@
*/ */
public class Stop implements Runnable { public class Stop implements Runnable {
private static Thread first=null; private static boolean groupStopped = false ;
private static Thread second=null; private static final Object lock = new Object();
private static ThreadGroup group = new ThreadGroup("");
Stop() { private static final ThreadGroup group = new ThreadGroup("");
Thread thread = new Thread(group, this); private static final Thread first = new Thread(group, new Stop());
if (first == null) private static final Thread second = new Thread(group, new Stop());
first = thread;
else
second = thread;
thread.start();
}
public void run() { public void run() {
while (true) { while (true) {
// Give the other thread a chance to start
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// When the first thread runs, it will stop the group.
if (Thread.currentThread() == first) {
synchronized (lock) {
try { try {
Thread.sleep(1000); // Give other thread a chance to start
if (Thread.currentThread() == first)
group.stop(); group.stop();
} catch(InterruptedException e){ } finally {
// Signal the main thread it is time to check
// that the stopped thread group was successful
groupStopped = true;
lock.notifyAll();
}
}
} }
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
for (int i=0; i<2; i++) // Launch two threads as part of the same thread group
new Stop(); first.start();
Thread.sleep(3000); second.start();
// Wait for the thread group stop to be issued
synchronized(lock){
while (!groupStopped) {
lock.wait();
// Give the other thread a chance to stop
Thread.sleep(1000);
}
}
// Check that the second thread is terminated when the
// first thread terminates the thread group.
boolean failed = second.isAlive(); boolean failed = second.isAlive();
first.stop(); second.stop();
// Clean up any threads that may have not been terminated
first.stop();
second.stop();
if (failed) if (failed)
throw new RuntimeException("Failure."); throw new RuntimeException("Failure.");
} }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 7024172 * @bug 7024172 7067691
* @summary Test if proxy for PlatformLoggingMXBean is equivalent * @summary Test if proxy for PlatformLoggingMXBean is equivalent
* to proxy for LoggingMXBean * to proxy for LoggingMXBean
* *
...@@ -43,6 +43,13 @@ public class LoggingMXBeanTest ...@@ -43,6 +43,13 @@ public class LoggingMXBeanTest
static String LOGGER_NAME_2 = "com.sun.management.Logger.Logger2"; static String LOGGER_NAME_2 = "com.sun.management.Logger.Logger2";
static String UNKNOWN_LOGGER_NAME = "com.sun.management.Unknown"; static String UNKNOWN_LOGGER_NAME = "com.sun.management.Unknown";
// These instance variables prevent premature logger garbage collection
// See getLogger() weak reference warnings.
Logger logger1;
Logger logger2;
static LoggingMXBeanTest test;
public static void main(String[] argv) throws Exception { public static void main(String[] argv) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
LoggingMXBean proxy = LoggingMXBean proxy =
...@@ -51,7 +58,7 @@ public class LoggingMXBeanTest ...@@ -51,7 +58,7 @@ public class LoggingMXBeanTest
LoggingMXBean.class); LoggingMXBean.class);
// test LoggingMXBean proxy // test LoggingMXBean proxy
LoggingMXBeanTest p = new LoggingMXBeanTest(proxy); test = new LoggingMXBeanTest(proxy);
// check if the attributes implemented by PlatformLoggingMXBean // check if the attributes implemented by PlatformLoggingMXBean
// and LoggingMXBean return the same value // and LoggingMXBean return the same value
...@@ -64,9 +71,9 @@ public class LoggingMXBeanTest ...@@ -64,9 +71,9 @@ public class LoggingMXBeanTest
// same verification as in java/util/logging/LoggingMXBeanTest2 // same verification as in java/util/logging/LoggingMXBeanTest2
public LoggingMXBeanTest(LoggingMXBean mbean) throws Exception { public LoggingMXBeanTest(LoggingMXBean mbean) throws Exception {
Logger logger1 = Logger.getLogger( LOGGER_NAME_1 ); logger1 = Logger.getLogger( LOGGER_NAME_1 );
logger1.setLevel(Level.FINE); logger1.setLevel(Level.FINE);
Logger logger2 = Logger.getLogger( LOGGER_NAME_2 ); logger2 = Logger.getLogger( LOGGER_NAME_2 );
logger2.setLevel(null); logger2.setLevel(null);
/* /*
...@@ -207,6 +214,7 @@ public class LoggingMXBeanTest ...@@ -207,6 +214,7 @@ public class LoggingMXBeanTest
// verify logger names // verify logger names
List<String> loggers1 = mxbean1.getLoggerNames(); List<String> loggers1 = mxbean1.getLoggerNames();
List<String> loggers2 = mxbean2.getLoggerNames(); List<String> loggers2 = mxbean2.getLoggerNames();
if (loggers1.size() != loggers2.size()) if (loggers1.size() != loggers2.size())
throw new RuntimeException("LoggerNames: unmatched number of entries"); throw new RuntimeException("LoggerNames: unmatched number of entries");
List<String> loggers3 = new ArrayList<>(loggers1); List<String> loggers3 = new ArrayList<>(loggers1);
...@@ -219,7 +227,10 @@ public class LoggingMXBeanTest ...@@ -219,7 +227,10 @@ public class LoggingMXBeanTest
if (!mxbean1.getLoggerLevel(logger) if (!mxbean1.getLoggerLevel(logger)
.equals(mxbean2.getLoggerLevel(logger))) .equals(mxbean2.getLoggerLevel(logger)))
throw new RuntimeException( throw new RuntimeException(
"LoggerLevel: unmatched level for " + logger); "LoggerLevel: unmatched level for " + logger
+ ", " + mxbean1.getLoggerLevel(logger)
+ ", " + mxbean2.getLoggerLevel(logger));
if (!mxbean1.getParentLoggerName(logger) if (!mxbean1.getParentLoggerName(logger)
.equals(mxbean2.getParentLoggerName(logger))) .equals(mxbean2.getParentLoggerName(logger)))
throw new RuntimeException( throw new RuntimeException(
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6876135 7024172 * @bug 6876135 7024172 7067691
* *
* @summary Test PlatformLoggingMXBean * @summary Test PlatformLoggingMXBean
* This test performs similar testing as * This test performs similar testing as
...@@ -41,11 +41,15 @@ import java.util.List; ...@@ -41,11 +41,15 @@ import java.util.List;
public class PlatformLoggingMXBeanTest public class PlatformLoggingMXBeanTest
{ {
ObjectName objectName = null; ObjectName objectName = null;
static String LOGGER_NAME_1 = "com.sun.management.Logger1"; static String LOGGER_NAME_1 = "com.sun.management.Logger1";
static String LOGGER_NAME_2 = "com.sun.management.Logger2"; static String LOGGER_NAME_2 = "com.sun.management.Logger2";
// Use Logger instance variables to prevent premature garbage collection
// of weak references.
Logger logger1;
Logger logger2;
public PlatformLoggingMXBeanTest() throws Exception { public PlatformLoggingMXBeanTest() throws Exception {
} }
...@@ -135,8 +139,8 @@ public class PlatformLoggingMXBeanTest ...@@ -135,8 +139,8 @@ public class PlatformLoggingMXBeanTest
System.out.println( "*********** Phase 3 ***********" ); System.out.println( "*********** Phase 3 ***********" );
System.out.println( "*******************************" ); System.out.println( "*******************************" );
System.out.println( " Create and test new Loggers" ); System.out.println( " Create and test new Loggers" );
Logger logger1 = Logger.getLogger( LOGGER_NAME_1 ); logger1 = Logger.getLogger( LOGGER_NAME_1 );
Logger logger2 = Logger.getLogger( LOGGER_NAME_2 ); logger2 = Logger.getLogger( LOGGER_NAME_2 );
// check that Level object are returned properly // check that Level object are returned properly
try { try {
...@@ -187,6 +191,7 @@ public class PlatformLoggingMXBeanTest ...@@ -187,6 +191,7 @@ public class PlatformLoggingMXBeanTest
System.out.println( " Set and Check the Logger Level" ); System.out.println( " Set and Check the Logger Level" );
log1 = false; log1 = false;
log2 = false; log2 = false;
try { try {
// Set the level of logger1 to ALL // Set the level of logger1 to ALL
params = new Object[2]; params = new Object[2];
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class readTest {
public static void main(String args[]) throws Exception {
int port = 7491;
try {
testPkg.Server obj = new testPkg.Server();
testPkg.Hello stub = (testPkg.Hello) UnicastRemoteObject.exportObject(obj, 0);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.getRegistry(port);
registry.bind("Hello", stub);
System.err.println("Server ready");
// now, let's test client
testPkg.Client client = new testPkg.Client(port);
String testStubReturn = client.testStub();
if(!testStubReturn.equals(obj.hello)) {
throw new RuntimeException("Test Fails : unexpected string from stub call");
} else {
System.out.println("Test passed");
}
registry.unbind("Hello");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
#
# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @bug 7102369 7094468 7100592
# @summary remove java.rmi.server.codebase property parsing from registyimpl
# @run shell readTest.sh
OS=`uname -s`
case "$OS" in
SunOS | Linux )
PS=":"
FS="/"
FILEURL="file:"
;;
Windows* | CYGWIN* )
PS=";"
FS="\\"
FILEURL="file:/"
;;
* )
echo "Unrecognized system!"
exit 1;
;;
esac
cp -r ${TESTSRC}${FS}* .
${TESTJAVA}${FS}bin${FS}javac testPkg${FS}*java
${TESTJAVA}${FS}bin${FS}javac readTest.java
mkdir rmi_tmp
RMIREG_OUT=rmi.out
#start rmiregistry without any local classes on classpath
cd rmi_tmp
${TESTJAVA}${FS}bin${FS}rmiregistry 7491 > ..${FS}${RMIREG_OUT} 2>&1 &
RMIREG_PID=$!
# allow some time to start
sleep 3
cd ..
# trailing / after code base is important for rmi codebase property.
${TESTJAVA}${FS}bin${FS}java -Djava.rmi.server.codebase=${FILEURL}`pwd`/ readTest > OUT.TXT 2>&1 &
TEST_PID=$!
#bulk of testcase - let it run for a while
sleep 5
#we're done, kill processes first
kill -9 ${RMIREG_PID} ${TEST_PID}
sleep 3
echo "Test output : "
cat OUT.TXT
echo "=============="
echo "rmiregistry output : "
cat ${RMIREG_OUT}
echo "=============="
grep "Server ready" OUT.TXT
result1=$?
grep "Test passed" OUT.TXT
result2=$?
if [ $result1 -eq 0 -a $result2 -eq 0 ]
then
echo "Passed"
exitCode=0;
else
echo "Failed"
exitCode=1
fi
rm -rf OUT.TXT ${RMIREG_OUT} rmi_tmp
exit ${exitCode}
/* /*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,72 +21,28 @@ ...@@ -21,72 +21,28 @@
* questions. * questions.
*/ */
/** package testPkg;
*
* @test
* @bug 6322678
* @summary Test for making sure that fd is closed during
* finalization of a stream, when an associated
* file channel is not available
*/
import java.io.*; import java.rmi.registry.LocateRegistry;
import java.nio.*; import java.rmi.registry.Registry;
import java.nio.channels.*;
public class FileChannelFDTest { public class Client {
int port;
static byte data[] = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57,}; public Client(int p) {
static String inFileName = "fd-in-test.txt"; port = p;
static String outFileName = "fd-out-test.txt";
static File inFile;
static File outFile;
private static void writeToInFile() throws IOException {
FileOutputStream out = new FileOutputStream(inFile);
out.write(data);
out.close();
} }
public static void main(String[] args) public String testStub() throws Exception {
throws Exception { try {
Registry registry = LocateRegistry.getRegistry(port);
inFile= new File(System.getProperty("test.dir", "."), Hello stub = (Hello) registry.lookup("Hello");
inFileName); String response = stub.sayHello();
inFile.createNewFile(); return response;
inFile.deleteOnExit(); } catch (Exception e) {
writeToInFile(); System.err.println("Client exception: " + e.toString());
throw e;
outFile = new File(System.getProperty("test.dir", "."),
outFileName);
outFile.createNewFile();
outFile.deleteOnExit();
doFileChannel();
} }
private static void doFileChannel() throws Exception {
FileInputStream fis = new FileInputStream(inFile);
FileDescriptor fd = fis.getFD();
FileChannel fc = fis.getChannel();
System.out.println("Created fis:" + fis);
/**
* Encourage the GC
*/
fis = null;
fc = null;
System.gc();
Thread.sleep(500);
if (fd.valid()) {
throw new Exception("Finalizer either didn't run --" +
"try increasing the Thread's sleep time after System.gc();" +
"or the finalizer didn't close the file");
} }
System.out.println("File Closed successfully");
System.out.println();
} }
}
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package testPkg;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String sayHello() throws RemoteException;
}
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package testPkg;
public class Server implements Hello {
public String hello = "Hello, world!";
public Server() {}
public String sayHello() {
return hello;
}
}
...@@ -92,19 +92,22 @@ public class Args { ...@@ -92,19 +92,22 @@ public class Args {
new F(){void f(){ t.scheduleAtFixedRate(x, (Date)null, 42); }} new F(){void f(){ t.scheduleAtFixedRate(x, (Date)null, 42); }}
); );
final long start = System.currentTimeMillis();
final Date past = new Date(start - 10500);
final CountDownLatch y1 = new CountDownLatch(1); final CountDownLatch y1 = new CountDownLatch(1);
final CountDownLatch y2 = new CountDownLatch(1); final CountDownLatch y2 = new CountDownLatch(1);
final CountDownLatch y3 = new CountDownLatch(11); final CountDownLatch y3 = new CountDownLatch(11);
final long start = System.currentTimeMillis();
final Date past = new Date(start - 10500);
schedule( t, counter(y1), past); schedule( t, counter(y1), past);
schedule( t, counter(y2), past, 1000); schedule( t, counter(y2), past, 1000);
scheduleAtFixedRate(t, counter(y3), past, 1000); scheduleAtFixedRate(t, counter(y3), past, 1000);
y3.await(); y3.await();
y1.await(); y1.await();
y2.await(); y2.await();
System.out.printf("elapsed=%d%n", System.currentTimeMillis() - start);
check(System.currentTimeMillis() - start < 500); final long elapsed = System.currentTimeMillis() - start;
System.out.printf("elapsed=%d%n", elapsed);
check(elapsed < 500);
t.cancel(); t.cancel();
......
...@@ -31,21 +31,26 @@ ...@@ -31,21 +31,26 @@
import java.util.*; import java.util.*;
public class KillThread { public class KillThread {
static volatile Thread tdThread;
public static void main (String[] args) throws Exception { public static void main (String[] args) throws Exception {
Timer t = new Timer(); Timer t = new Timer();
// Start a mean event that kills the timer thread // Start a mean event that kills the timer thread
t.schedule(new TimerTask() { t.schedule(new TimerTask() {
public void run() { public void run() {
tdThread = Thread.currentThread();
throw new ThreadDeath(); throw new ThreadDeath();
} }
}, 0); }, 0);
// Wait for mean event to do the deed and thread to die. // Wait for mean event to do the deed and thread to die.
try { try {
do {
Thread.sleep(100); Thread.sleep(100);
} while(tdThread == null);
} catch(InterruptedException e) { } catch(InterruptedException e) {
} }
tdThread.join();
// Try to start another event // Try to start another event
try { try {
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7113275
* @summary compatibility issue with MD2 trust anchor and old X509TrustManager
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
* @run main/othervm MD2InTrustAnchor PKIX TLSv1.1
* @run main/othervm MD2InTrustAnchor SunX509 TLSv1.1
* @run main/othervm MD2InTrustAnchor PKIX TLSv1.2
* @run main/othervm MD2InTrustAnchor SunX509 TLSv1.2
*/
import java.net.*;
import java.util.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.KeyStore;
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.*;
import java.security.interfaces.*;
import sun.misc.BASE64Decoder;
public class MD2InTrustAnchor {
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static boolean separateServerThread = false;
/*
* Certificates and key used in the test.
*/
// It's a trust anchor signed with MD2 hash function.
static String trustedCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
"KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" +
"wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" +
"ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" +
"SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" +
"MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" +
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
"BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" +
"qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" +
"lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" +
"-----END CERTIFICATE-----";
// The certificate issued by above trust anchor, signed with MD5
static String targetCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
"BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" +
"fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" +
"G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" +
"NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" +
"MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" +
"2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
"CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" +
"sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" +
"YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" +
"yvudOlX4BkVR0l1K\n" +
"-----END CERTIFICATE-----";
// Private key in the format of PKCS#8.
static String targetPrivateKey =
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" +
"F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" +
"9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" +
"KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" +
"SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" +
"5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" +
"aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" +
"6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" +
"z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" +
"L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" +
"hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" +
"kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" +
"A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
"njWHoKY3axDQ8OU=\n";
static char passphrase[] = "passphrase".toCharArray();
/*
* Is the server ready to serve?
*/
volatile static boolean serverReady = false;
/*
* Turn on SSL debugging?
*/
static boolean debug = false;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doServerSide() throws Exception {
SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
targetPrivateKey);
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)sslssf.createServerSocket(serverPort);
sslServerSocket.setNeedClientAuth(true);
serverPort = sslServerSocket.getLocalPort();
/*
* Signal Client, we're ready for his connect.
*/
serverReady = true;
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslIS.read();
sslOS.write('A');
sslOS.flush();
sslSocket.close();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doClientSide() throws Exception {
/*
* Wait for server to get started.
*/
while (!serverReady) {
Thread.sleep(50);
}
SSLContext context = generateSSLContext(trustedCertStr, targetCertStr,
targetPrivateKey);
SSLSocketFactory sslsf = context.getSocketFactory();
SSLSocket sslSocket =
(SSLSocket)sslsf.createSocket("localhost", serverPort);
// enable the specified TLS protocol
sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslOS.write('B');
sslOS.flush();
sslIS.read();
sslSocket.close();
}
/*
* =============================================================
* The remainder is just support stuff
*/
private static String tmAlgorithm; // trust manager
private static String tlsProtocol; // trust manager
private static void parseArguments(String[] args) {
tmAlgorithm = args[0];
tlsProtocol = args[1];
}
private static SSLContext generateSSLContext(String trustedCertStr,
String keyCertStr, String keySpecStr) throws Exception {
// generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// create a key store
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
// import the trused cert
Certificate trusedCert = null;
ByteArrayInputStream is = null;
if (trustedCertStr != null) {
is = new ByteArrayInputStream(trustedCertStr.getBytes());
trusedCert = cf.generateCertificate(is);
is.close();
ks.setCertificateEntry("RSA Export Signer", trusedCert);
}
if (keyCertStr != null) {
// generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
new BASE64Decoder().decodeBuffer(keySpecStr));
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey priKey =
(RSAPrivateKey)kf.generatePrivate(priKeySpec);
// generate certificate chain
is = new ByteArrayInputStream(keyCertStr.getBytes());
Certificate keyCert = cf.generateCertificate(is);
is.close();
// It's not allowed to send MD2 signed certificate to peer,
// even it may be a trusted certificate. Then we will not
// place the trusted certficate in the chain.
Certificate[] chain = new Certificate[1];
chain[0] = keyCert;
// import the key entry.
ks.setKeyEntry("Whatever", priKey, passphrase, chain);
}
// create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
tmf.init(ks);
SSLContext ctx = SSLContext.getInstance(tlsProtocol);
if (keyCertStr != null && !keyCertStr.isEmpty()) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
ks = null;
} else {
ctx.init(null, tmf.getTrustManagers(), null);
}
return ctx;
}
// use any free port by default
volatile int serverPort = 0;
volatile Exception serverException = null;
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
if (debug)
System.setProperty("javax.net.debug", "all");
/*
* Get the customized arguments.
*/
parseArguments(args);
/*
* Start the tests.
*/
new MD2InTrustAnchor();
}
Thread clientThread = null;
Thread serverThread = null;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
MD2InTrustAnchor() throws Exception {
try {
if (separateServerThread) {
startServer(true);
startClient(false);
} else {
startClient(true);
startServer(false);
}
} catch (Exception e) {
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
serverThread.join();
} else {
clientThread.join();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception local;
Exception remote;
String whichRemote;
if (separateServerThread) {
remote = serverException;
local = clientException;
whichRemote = "server";
} else {
remote = clientException;
local = serverException;
whichRemote = "client";
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if ((local != null) && (remote != null)) {
System.out.println(whichRemote + " also threw:");
remote.printStackTrace();
System.out.println();
throw local;
}
if (remote != null) {
throw remote;
}
if (local != null) {
throw local;
}
}
void startServer(boolean newThread) throws Exception {
if (newThread) {
serverThread = new Thread() {
public void run() {
try {
doServerSide();
} catch (Exception e) {
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System.err.println("Server died...");
serverReady = true;
serverException = e;
}
}
};
serverThread.start();
} else {
try {
doServerSide();
} catch (Exception e) {
serverException = e;
} finally {
serverReady = true;
}
}
}
void startClient(boolean newThread) throws Exception {
if (newThread) {
clientThread = new Thread() {
public void run() {
try {
doClientSide();
} catch (Exception e) {
/*
* Our client thread just died.
*/
System.err.println("Client died...");
clientException = e;
}
}
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 7113275
* @summary compatibility issue with MD2 trust anchor and old X509TrustManager
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
* @run main/othervm TrustTrustedCert PKIX TLSv1.1
* @run main/othervm TrustTrustedCert SunX509 TLSv1.1
* @run main/othervm TrustTrustedCert PKIX TLSv1.2
* @run main/othervm TrustTrustedCert SunX509 TLSv1.2
*/
import java.net.*;
import java.util.*;
import java.io.*;
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.*;
import java.security.spec.*;
import java.security.interfaces.*;
import sun.misc.BASE64Decoder;
public class TrustTrustedCert {
/*
* =============================================================
* Set the various variables needed for the tests, then
* specify what tests to run on each side.
*/
/*
* Should we run the client or server in a separate thread?
* Both sides can throw exceptions, but do you have a preference
* as to which side should be the main thread.
*/
static boolean separateServerThread = false;
/*
* Certificates and key used in the test.
*/
// It's a trust anchor signed with MD2 hash function.
static String trustedCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
"KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" +
"wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" +
"ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" +
"SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" +
"MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" +
"EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
"Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" +
"BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" +
"qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" +
"lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" +
"-----END CERTIFICATE-----";
// The certificate issued by above trust anchor, signed with MD5
static String targetCertStr =
"-----BEGIN CERTIFICATE-----\n" +
"MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
"MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
"MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
"A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
"BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" +
"fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" +
"G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" +
"NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" +
"MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" +
"2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +
"CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" +
"sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" +
"YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" +
"yvudOlX4BkVR0l1K\n" +
"-----END CERTIFICATE-----";
// Private key in the format of PKCS#8.
static String targetPrivateKey =
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" +
"F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" +
"9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" +
"KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" +
"SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" +
"5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" +
"aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" +
"6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" +
"z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" +
"L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" +
"hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" +
"kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" +
"A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" +
"njWHoKY3axDQ8OU=\n";
static char passphrase[] = "passphrase".toCharArray();
/*
* Is the server ready to serve?
*/
volatile static boolean serverReady = false;
/*
* Turn on SSL debugging?
*/
static boolean debug = false;
/*
* Define the server side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doServerSide() throws Exception {
SSLContext context = generateSSLContext();
SSLServerSocketFactory sslssf = context.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)sslssf.createServerSocket(serverPort);
sslServerSocket.setNeedClientAuth(true);
serverPort = sslServerSocket.getLocalPort();
/*
* Signal Client, we're ready for his connect.
*/
serverReady = true;
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslIS.read();
sslOS.write('A');
sslOS.flush();
sslSocket.close();
}
/*
* Define the client side of the test.
*
* If the server prematurely exits, serverReady will be set to true
* to avoid infinite hangs.
*/
void doClientSide() throws Exception {
/*
* Wait for server to get started.
*/
while (!serverReady) {
Thread.sleep(50);
}
SSLContext context = generateSSLContext();
SSLSocketFactory sslsf = context.getSocketFactory();
SSLSocket sslSocket =
(SSLSocket)sslsf.createSocket("localhost", serverPort);
// enable the specified TLS protocol
sslSocket.setEnabledProtocols(new String[] {tlsProtocol});
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslOS.write('B');
sslOS.flush();
sslIS.read();
sslSocket.close();
}
/*
* =============================================================
* The remainder is just support stuff
*/
private static String tmAlgorithm; // trust manager
private static String tlsProtocol; // trust manager
private static void parseArguments(String[] args) {
tmAlgorithm = args[0];
tlsProtocol = args[1];
}
private static SSLContext generateSSLContext() throws Exception {
// generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// create a key store
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
// import the trused cert
X509Certificate trusedCert = null;
ByteArrayInputStream is =
new ByteArrayInputStream(trustedCertStr.getBytes());
trusedCert = (X509Certificate)cf.generateCertificate(is);
is.close();
ks.setCertificateEntry("Trusted RSA Signer", trusedCert);
// generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
new BASE64Decoder().decodeBuffer(targetPrivateKey));
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey priKey =
(RSAPrivateKey)kf.generatePrivate(priKeySpec);
// generate certificate chain
is = new ByteArrayInputStream(targetCertStr.getBytes());
X509Certificate keyCert = (X509Certificate)cf.generateCertificate(is);
is.close();
X509Certificate[] chain = new X509Certificate[2];
chain[0] = keyCert;
chain[1] = trusedCert;
// import the key entry and the chain
ks.setKeyEntry("TheKey", priKey, passphrase, chain);
// create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
tmf.init(ks);
// create the customized KM and TM
NoneExtendedX509TM myTM =
new NoneExtendedX509TM(tmf.getTrustManagers()[0]);
NoneExtendedX509KM myKM =
new NoneExtendedX509KM("TheKey", chain, priKey);
SSLContext ctx = SSLContext.getInstance(tlsProtocol);
// KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
// kmf.init(ks, passphrase);
// ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
ctx.init(new KeyManager[]{myKM}, new TrustManager[]{myTM}, null);
ks = null;
return ctx;
}
static class NoneExtendedX509TM implements X509TrustManager {
X509TrustManager tm;
NoneExtendedX509TM(TrustManager tm) {
this.tm = (X509TrustManager)tm;
}
public void checkClientTrusted(X509Certificate chain[], String authType)
throws CertificateException {
tm.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate chain[], String authType)
throws CertificateException {
tm.checkServerTrusted(chain, authType);
}
public X509Certificate[] getAcceptedIssuers() {
return tm.getAcceptedIssuers();
}
}
static class NoneExtendedX509KM implements X509KeyManager {
private String keyAlias;
private X509Certificate[] chain;
private PrivateKey privateKey;
NoneExtendedX509KM(String keyAlias, X509Certificate[] chain,
PrivateKey privateKey) {
this.keyAlias = keyAlias;
this.chain = chain;
this.privateKey = privateKey;
}
public String[] getClientAliases(String keyType, Principal[] issuers) {
return new String[] {keyAlias};
}
public String chooseClientAlias(String[] keyType, Principal[] issuers,
Socket socket) {
return keyAlias;
}
public String[] getServerAliases(String keyType, Principal[] issuers) {
return new String[] {keyAlias};
}
public String chooseServerAlias(String keyType, Principal[] issuers,
Socket socket) {
return keyAlias;
}
public X509Certificate[] getCertificateChain(String alias) {
return chain;
}
public PrivateKey getPrivateKey(String alias) {
return privateKey;
}
}
// use any free port by default
volatile int serverPort = 0;
volatile Exception serverException = null;
volatile Exception clientException = null;
public static void main(String[] args) throws Exception {
if (debug)
System.setProperty("javax.net.debug", "all");
/*
* Get the customized arguments.
*/
parseArguments(args);
/*
* Start the tests.
*/
new TrustTrustedCert();
}
Thread clientThread = null;
Thread serverThread = null;
/*
* Primary constructor, used to drive remainder of the test.
*
* Fork off the other side, then do your work.
*/
TrustTrustedCert() throws Exception {
try {
if (separateServerThread) {
startServer(true);
startClient(false);
} else {
startClient(true);
startServer(false);
}
} catch (Exception e) {
// swallow for now. Show later
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
serverThread.join();
} else {
clientThread.join();
}
/*
* When we get here, the test is pretty much over.
* Which side threw the error?
*/
Exception local;
Exception remote;
String whichRemote;
if (separateServerThread) {
remote = serverException;
local = clientException;
whichRemote = "server";
} else {
remote = clientException;
local = serverException;
whichRemote = "client";
}
/*
* If both failed, return the curthread's exception, but also
* print the remote side Exception
*/
if ((local != null) && (remote != null)) {
System.out.println(whichRemote + " also threw:");
remote.printStackTrace();
System.out.println();
throw local;
}
if (remote != null) {
throw remote;
}
if (local != null) {
throw local;
}
}
void startServer(boolean newThread) throws Exception {
if (newThread) {
serverThread = new Thread() {
public void run() {
try {
doServerSide();
} catch (Exception e) {
/*
* Our server thread just died.
*
* Release the client, if not active already...
*/
System.err.println("Server died...");
serverReady = true;
serverException = e;
}
}
};
serverThread.start();
} else {
try {
doServerSide();
} catch (Exception e) {
serverException = e;
} finally {
serverReady = true;
}
}
}
void startClient(boolean newThread) throws Exception {
if (newThread) {
clientThread = new Thread() {
public void run() {
try {
doClientSide();
} catch (Exception e) {
/*
* Our client thread just died.
*/
System.err.println("Client died...");
clientException = e;
}
}
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册