mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-06 19:59:17 +00:00
Merge
This commit is contained in:
commit
95e9cd174d
@ -71,7 +71,7 @@ include $(BUILDDIR)/common/internal/ImportComponents.gmk
|
||||
ifeq ($(ARCH_DATA_MODEL),64)
|
||||
MAX_VM_MEMORY = 1024
|
||||
else
|
||||
MAX_VM_MEMORY = 512
|
||||
MAX_VM_MEMORY = 612
|
||||
endif
|
||||
|
||||
# List of all possible directories for javadoc to look for sources
|
||||
|
||||
@ -124,7 +124,7 @@ class FileInputStream extends InputStream
|
||||
throw new NullPointerException();
|
||||
}
|
||||
fd = new FileDescriptor();
|
||||
fd.incrementAndGetUseCount();
|
||||
fd.attach(this);
|
||||
open(name);
|
||||
}
|
||||
|
||||
@ -164,10 +164,9 @@ class FileInputStream extends InputStream
|
||||
|
||||
/*
|
||||
* FileDescriptor is being shared by streams.
|
||||
* Ensure that it's GC'ed only when all the streams/channels are done
|
||||
* using it.
|
||||
* Register this stream with FileDescriptor tracker.
|
||||
*/
|
||||
fd.incrementAndGetUseCount();
|
||||
fd.attach(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,27 +293,14 @@ class FileInputStream extends InputStream
|
||||
closed = true;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement the FD use count associated with this stream
|
||||
*/
|
||||
int useCount = fd.decrementAndGetUseCount();
|
||||
|
||||
/*
|
||||
* If FileDescriptor is still in use by another stream, we
|
||||
* will not close it.
|
||||
*/
|
||||
if (useCount <= 0) {
|
||||
close0();
|
||||
}
|
||||
fd.closeAll(new Closeable() {
|
||||
public void close() throws IOException {
|
||||
close0();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -328,7 +314,9 @@ class FileInputStream extends InputStream
|
||||
* @see java.io.FileDescriptor
|
||||
*/
|
||||
public final FileDescriptor getFD() throws IOException {
|
||||
if (fd != null) return fd;
|
||||
if (fd != null) {
|
||||
return fd;
|
||||
}
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@ -352,13 +340,6 @@ class FileInputStream extends InputStream
|
||||
synchronized (this) {
|
||||
if (channel == null) {
|
||||
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;
|
||||
}
|
||||
@ -381,7 +362,12 @@ class FileInputStream extends InputStream
|
||||
*/
|
||||
protected void finalize() throws IOException {
|
||||
if ((fd != null) && (fd != FileDescriptor.in)) {
|
||||
close();
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,9 +197,9 @@ class FileOutputStream extends OutputStream
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
this.append = append;
|
||||
|
||||
fd.incrementAndGetUseCount();
|
||||
open(name, append);
|
||||
}
|
||||
|
||||
@ -237,12 +237,7 @@ class FileOutputStream extends OutputStream
|
||||
this.fd = fdObj;
|
||||
this.append = false;
|
||||
|
||||
/*
|
||||
* FileDescriptor is being shared by streams.
|
||||
* Ensure that it's GC'ed only when all the streams/channels are done
|
||||
* using it.
|
||||
*/
|
||||
fd.incrementAndGetUseCount();
|
||||
fd.attach(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,27 +326,14 @@ class FileOutputStream extends OutputStream
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement FD use count associated with this stream
|
||||
*/
|
||||
int useCount = fd.decrementAndGetUseCount();
|
||||
|
||||
/*
|
||||
* If FileDescriptor is still in use by another stream, we
|
||||
* will not close it.
|
||||
*/
|
||||
if (useCount <= 0) {
|
||||
close0();
|
||||
}
|
||||
fd.closeAll(new Closeable() {
|
||||
public void close() throws IOException {
|
||||
close0();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,7 +347,9 @@ class FileOutputStream extends OutputStream
|
||||
* @see java.io.FileDescriptor
|
||||
*/
|
||||
public final FileDescriptor getFD() throws IOException {
|
||||
if (fd != null) return fd;
|
||||
if (fd != null) {
|
||||
return fd;
|
||||
}
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@ -390,13 +374,6 @@ class FileOutputStream extends OutputStream
|
||||
synchronized (this) {
|
||||
if (channel == null) {
|
||||
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;
|
||||
}
|
||||
@ -415,7 +392,12 @@ class FileOutputStream extends OutputStream
|
||||
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
|
||||
flush();
|
||||
} else {
|
||||
close();
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
fd = new FileDescriptor();
|
||||
fd.incrementAndGetUseCount();
|
||||
fd.attach(this);
|
||||
open(name, imode);
|
||||
}
|
||||
|
||||
@ -242,7 +242,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
* @see java.io.FileDescriptor
|
||||
*/
|
||||
public final FileDescriptor getFD() throws IOException {
|
||||
if (fd != null) return fd;
|
||||
if (fd != null) {
|
||||
return fd;
|
||||
}
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@ -268,17 +270,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
synchronized (this) {
|
||||
if (channel == null) {
|
||||
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;
|
||||
}
|
||||
@ -577,28 +568,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
closed = true;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrement FD use count associated with this stream.
|
||||
* 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();
|
||||
}
|
||||
fd.closeAll(new Closeable() {
|
||||
public void close() throws IOException {
|
||||
close0();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@ -57,7 +57,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
|
||||
/**
|
||||
* 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
|
||||
@ -107,7 +107,7 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
|
||||
public void write(int c) throws IOException {
|
||||
synchronized (lock) {
|
||||
if (writeBuffer == null){
|
||||
writeBuffer = new char[writeBufferSize];
|
||||
writeBuffer = new char[WRITE_BUFFER_SIZE];
|
||||
}
|
||||
writeBuffer[0] = (char) c;
|
||||
write(writeBuffer, 0, 1);
|
||||
@ -180,9 +180,9 @@ public abstract class Writer implements Appendable, Closeable, Flushable {
|
||||
public void write(String str, int off, int len) throws IOException {
|
||||
synchronized (lock) {
|
||||
char cbuf[];
|
||||
if (len <= writeBufferSize) {
|
||||
if (len <= WRITE_BUFFER_SIZE) {
|
||||
if (writeBuffer == null) {
|
||||
writeBuffer = new char[writeBufferSize];
|
||||
writeBuffer = new char[WRITE_BUFFER_SIZE];
|
||||
}
|
||||
cbuf = writeBuffer;
|
||||
} else { // Don't permanently allocate very large buffers.
|
||||
|
||||
@ -71,7 +71,7 @@ public class AssertionError extends Error {
|
||||
* @see Throwable#getCause()
|
||||
*/
|
||||
public AssertionError(Object detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
if (detailMessage instanceof Throwable)
|
||||
initCause((Throwable) detailMessage);
|
||||
}
|
||||
@ -85,7 +85,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(boolean detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +97,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(char detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,7 +109,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(int detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,7 +121,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(long detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +133,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(float detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,7 +145,7 @@ public class AssertionError extends Error {
|
||||
* @param detailMessage value to be used in constructing detail message
|
||||
*/
|
||||
public AssertionError(double detailMessage) {
|
||||
this("" + detailMessage);
|
||||
this(String.valueOf(detailMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3008,7 +3008,7 @@ public final
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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> {
|
||||
* @see java.lang.Double#valueOf(java.lang.String)
|
||||
*/
|
||||
public Double(String s) throws NumberFormatException {
|
||||
// REMIND: this is inefficient
|
||||
this(valueOf(s).doubleValue());
|
||||
value = parseDouble(s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -529,8 +529,7 @@ public final class Float extends Number implements Comparable<Float> {
|
||||
* @see java.lang.Float#valueOf(java.lang.String)
|
||||
*/
|
||||
public Float(String s) throws NumberFormatException {
|
||||
// REMIND: this is inefficient
|
||||
this(valueOf(s).floatValue());
|
||||
value = parseFloat(s);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -28,6 +28,7 @@ package java.security;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import sun.security.jca.GetInstance;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.SecurityConstants;
|
||||
@ -60,8 +61,8 @@ import sun.security.util.SecurityConstants;
|
||||
* with a standard type. The default policy type is "JavaPolicy".
|
||||
*
|
||||
* <p> Once a Policy instance has been installed (either by default, or by
|
||||
* calling <code>setPolicy</code>),
|
||||
* the Java runtime invokes its <code>implies</code> when it needs to
|
||||
* calling <code>setPolicy</code>), the Java runtime invokes its
|
||||
* <code>implies</code> method when it needs to
|
||||
* determine whether executing code (encapsulated in a ProtectionDomain)
|
||||
* can perform SecurityManager-protected operations. How a Policy object
|
||||
* retrieves its policy data is up to the Policy implementation itself.
|
||||
@ -94,18 +95,33 @@ public abstract class Policy {
|
||||
public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
|
||||
new UnsupportedEmptyCollection();
|
||||
|
||||
/** the system-wide policy. */
|
||||
private static Policy policy; // package private for AccessControlContext
|
||||
// Information about the system-wide policy.
|
||||
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");
|
||||
|
||||
// Cache mapping ProtectionDomain.Key to PermissionCollection
|
||||
private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
|
||||
|
||||
/** package private for AccessControlContext */
|
||||
/** package private for AccessControlContext and ProtectionDomain */
|
||||
static boolean isSet()
|
||||
{
|
||||
return policy != null;
|
||||
PolicyInfo pi = policy.get();
|
||||
return pi.policy != null && pi.initialized == true;
|
||||
}
|
||||
|
||||
private static void checkPermission(String type) {
|
||||
@ -143,80 +159,92 @@ public abstract class Policy {
|
||||
|
||||
/**
|
||||
* Returns the installed Policy object, skipping the security check.
|
||||
* Used by SecureClassLoader and getPolicy.
|
||||
* Used by ProtectionDomain and getPolicy.
|
||||
*
|
||||
* @return the installed Policy.
|
||||
*
|
||||
*/
|
||||
static synchronized Policy getPolicyNoCheck()
|
||||
static Policy getPolicyNoCheck()
|
||||
{
|
||||
if (policy == null) {
|
||||
String policy_class = null;
|
||||
policy_class = AccessController.doPrivileged(
|
||||
new PrivilegedAction<String>() {
|
||||
public String run() {
|
||||
return Security.getProperty("policy.provider");
|
||||
}
|
||||
});
|
||||
if (policy_class == null) {
|
||||
policy_class = "sun.security.provider.PolicyFile";
|
||||
}
|
||||
|
||||
try {
|
||||
policy = (Policy)
|
||||
Class.forName(policy_class).newInstance();
|
||||
} catch (Exception e) {
|
||||
/*
|
||||
* The policy_class seems to be an extension
|
||||
* so we have to bootstrap loading it via a policy
|
||||
* provider that is on the bootclasspath
|
||||
* If it loads then shift gears to using the configured
|
||||
* provider.
|
||||
*/
|
||||
|
||||
// install the bootstrap provider to avoid recursion
|
||||
policy = new sun.security.provider.PolicyFile();
|
||||
|
||||
final String pc = policy_class;
|
||||
Policy p = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Policy>() {
|
||||
public Policy run() {
|
||||
try {
|
||||
ClassLoader cl =
|
||||
ClassLoader.getSystemClassLoader();
|
||||
// we want the extension loader
|
||||
ClassLoader extcl = null;
|
||||
while (cl != null) {
|
||||
extcl = cl;
|
||||
cl = cl.getParent();
|
||||
}
|
||||
return (extcl != null ? (Policy)Class.forName(
|
||||
pc, true, extcl).newInstance() : null);
|
||||
} catch (Exception e) {
|
||||
if (debug != null) {
|
||||
debug.println("policy provider " +
|
||||
pc +
|
||||
" not available");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
PolicyInfo pi = policy.get();
|
||||
// Use double-check idiom to avoid locking if system-wide policy is
|
||||
// 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>() {
|
||||
public String run() {
|
||||
return Security.getProperty("policy.provider");
|
||||
}
|
||||
});
|
||||
/*
|
||||
* if it loaded install it as the policy provider. Otherwise
|
||||
* continue to use the system default implementation
|
||||
*/
|
||||
if (p != null) {
|
||||
policy = p;
|
||||
} else {
|
||||
if (debug != null) {
|
||||
debug.println("using sun.security.provider.PolicyFile");
|
||||
if (policy_class == null) {
|
||||
policy_class = "sun.security.provider.PolicyFile";
|
||||
}
|
||||
|
||||
try {
|
||||
pinfo = new PolicyInfo(
|
||||
(Policy) Class.forName(policy_class).newInstance(),
|
||||
true);
|
||||
} catch (Exception e) {
|
||||
/*
|
||||
* The policy_class seems to be an extension
|
||||
* so we have to bootstrap loading it via a policy
|
||||
* provider that is on the bootclasspath.
|
||||
* If it loads then shift gears to using the configured
|
||||
* provider.
|
||||
*/
|
||||
|
||||
// install the bootstrap provider to avoid recursion
|
||||
Policy polFile = new sun.security.provider.PolicyFile();
|
||||
pinfo = new PolicyInfo(polFile, false);
|
||||
policy.set(pinfo);
|
||||
|
||||
final String pc = policy_class;
|
||||
Policy pol = AccessController.doPrivileged(
|
||||
new PrivilegedAction<Policy>() {
|
||||
public Policy run() {
|
||||
try {
|
||||
ClassLoader cl =
|
||||
ClassLoader.getSystemClassLoader();
|
||||
// we want the extension loader
|
||||
ClassLoader extcl = null;
|
||||
while (cl != null) {
|
||||
extcl = cl;
|
||||
cl = cl.getParent();
|
||||
}
|
||||
return (extcl != null ? (Policy)Class.forName(
|
||||
pc, true, extcl).newInstance() : null);
|
||||
} catch (Exception e) {
|
||||
if (debug != null) {
|
||||
debug.println("policy provider " +
|
||||
pc +
|
||||
" not available");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
* if it loaded install it as the policy provider. Otherwise
|
||||
* continue to use the system default implementation
|
||||
*/
|
||||
if (pol != null) {
|
||||
pinfo = new PolicyInfo(pol, true);
|
||||
} else {
|
||||
if (debug != null) {
|
||||
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 {
|
||||
initPolicy(p);
|
||||
}
|
||||
synchronized (Policy.class) {
|
||||
Policy.policy = p;
|
||||
policy.set(new PolicyInfo(p, p != null));
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,14 +320,14 @@ public abstract class Policy {
|
||||
PermissionCollection policyPerms = null;
|
||||
synchronized (p) {
|
||||
if (p.pdMapping == null) {
|
||||
p.pdMapping =
|
||||
new WeakHashMap<ProtectionDomain.Key, PermissionCollection>();
|
||||
p.pdMapping = new WeakHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
if (policyDomain.getCodeSource() != null) {
|
||||
if (Policy.isSet()) {
|
||||
policyPerms = policy.getPermissions(policyDomain);
|
||||
Policy pol = policy.get().policy;
|
||||
if (pol != null) {
|
||||
policyPerms = pol.getPermissions(policyDomain);
|
||||
}
|
||||
|
||||
if (policyPerms == null) { // assume it has all
|
||||
@ -434,7 +462,7 @@ public abstract class Policy {
|
||||
type,
|
||||
params);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
return handleException (nsae);
|
||||
return handleException(nsae);
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,7 +522,7 @@ public abstract class Policy {
|
||||
type,
|
||||
params);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
return handleException (nsae);
|
||||
return handleException(nsae);
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,7 +836,7 @@ public abstract class Policy {
|
||||
*
|
||||
* @param permission the Permission object to compare.
|
||||
*
|
||||
* @return true if "permission" is implied by the permissions in
|
||||
* @return true if "permission" is implied by the permissions in
|
||||
* the collection, false if not.
|
||||
*/
|
||||
@Override public boolean implies(Permission permission) {
|
||||
|
||||
@ -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
|
||||
* <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
|
||||
* (depending on the argument's
|
||||
|
||||
@ -991,7 +991,7 @@ public interface Statement extends Wrapper, AutoCloseable {
|
||||
/**
|
||||
* Requests that a <code>Statement</code> be pooled or not pooled. The value
|
||||
* 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.
|
||||
* <p>
|
||||
* The poolable value of a statement is applicable to both internal
|
||||
|
||||
@ -742,6 +742,8 @@ public class LinkedBlockingDeque<E>
|
||||
throw new NullPointerException();
|
||||
if (c == this)
|
||||
throw new IllegalArgumentException();
|
||||
if (maxElements <= 0)
|
||||
return 0;
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
try {
|
||||
|
||||
@ -332,7 +332,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
||||
// Note: convention in all put/take/etc is to preset local var
|
||||
// holding count negative to indicate failure unless set.
|
||||
int c = -1;
|
||||
Node<E> node = new Node(e);
|
||||
Node<E> node = new Node<E>(e);
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
final AtomicInteger count = this.count;
|
||||
putLock.lockInterruptibly();
|
||||
@ -412,7 +412,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
||||
if (count.get() == capacity)
|
||||
return false;
|
||||
int c = -1;
|
||||
Node<E> node = new Node(e);
|
||||
Node<E> node = new Node<E>(e);
|
||||
final ReentrantLock putLock = this.putLock;
|
||||
putLock.lock();
|
||||
try {
|
||||
@ -728,6 +728,8 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
|
||||
throw new NullPointerException();
|
||||
if (c == this)
|
||||
throw new IllegalArgumentException();
|
||||
if (maxElements <= 0)
|
||||
return 0;
|
||||
boolean signalNotFull = false;
|
||||
final ReentrantLock takeLock = this.takeLock;
|
||||
takeLock.lock();
|
||||
|
||||
@ -629,7 +629,7 @@ public class Attributes implements Map<Object,Object>, Cloneable {
|
||||
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.
|
||||
* @see <a href="../../../../technotes/guides/versioning/spec/versioning2.html#wp90779">
|
||||
* Java Product Versioning Specification</a>
|
||||
|
||||
@ -402,10 +402,10 @@ class ServerImpl implements TimeSource {
|
||||
} catch (IOException e) {
|
||||
logger.log (Level.FINER, "Dispatcher (4)", e);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.log (Level.FINER, "Dispatcher (7)", e);
|
||||
}
|
||||
}
|
||||
try {selector.close(); } catch (Exception e) {}
|
||||
}
|
||||
|
||||
private void handleException (SelectionKey key, Exception e) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,6 +29,7 @@ import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.rmi.*;
|
||||
@ -54,7 +55,6 @@ import sun.rmi.server.UnicastServerRef2;
|
||||
import sun.rmi.transport.LiveRef;
|
||||
import sun.rmi.transport.ObjectTable;
|
||||
import sun.rmi.transport.Target;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* A "registry" exists on every node that allows RMI connections to
|
||||
@ -335,19 +335,6 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
|
||||
URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp);
|
||||
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
|
||||
* be annotated with the value of the "java.rmi.server.codebase"
|
||||
@ -365,7 +352,7 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
|
||||
public RegistryImpl run() throws RemoteException {
|
||||
return new RegistryImpl(regPort);
|
||||
}
|
||||
}, getAccessControlContext(codebaseURLs));
|
||||
}, getAccessControlContext());
|
||||
} catch (PrivilegedActionException ex) {
|
||||
throw (RemoteException) ex.getException();
|
||||
}
|
||||
@ -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
|
||||
* 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
|
||||
PermissionCollection perms = AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<PermissionCollection>() {
|
||||
@ -420,17 +407,15 @@ public class RegistryImpl extends java.rmi.server.RemoteServer
|
||||
|
||||
perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
|
||||
|
||||
// add permissions required to load from codebase URL path
|
||||
LoaderHandler.addPermissionsForURLs(urls, perms, false);
|
||||
perms.add(new FilePermission("<<ALL FILES>>", "read"));
|
||||
|
||||
/*
|
||||
* Create an AccessControlContext that consists of a single
|
||||
* protection domain with only the permissions calculated above.
|
||||
*/
|
||||
ProtectionDomain pd = new ProtectionDomain(
|
||||
new CodeSource((urls.length > 0 ? urls[0] : null),
|
||||
(java.security.cert.Certificate[]) null),
|
||||
perms);
|
||||
new CodeSource(null,
|
||||
(java.security.cert.Certificate[]) null), perms);
|
||||
return new AccessControlContext(new ProtectionDomain[] { pd });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1031,7 +1031,7 @@ public final class LoaderHandler {
|
||||
* loader. A given permission is only added to the collection if
|
||||
* it is not already implied by the collection.
|
||||
*/
|
||||
public static void addPermissionsForURLs(URL[] urls,
|
||||
private static void addPermissionsForURLs(URL[] urls,
|
||||
PermissionCollection perms,
|
||||
boolean forLoader)
|
||||
{
|
||||
|
||||
@ -68,8 +68,8 @@ public class KerberosTime implements Cloneable {
|
||||
private int microSeconds; // the last three digits of the microsecond value
|
||||
|
||||
// The time when this class is loaded. Used in setNow()
|
||||
private static final long initMilli = System.currentTimeMillis();
|
||||
private static final long initMicro = System.nanoTime() / 1000;
|
||||
private static long initMilli = System.currentTimeMillis();
|
||||
private static long initMicro = System.nanoTime() / 1000;
|
||||
|
||||
private static long syncTime;
|
||||
private static boolean DEBUG = Krb5.DEBUG;
|
||||
@ -212,9 +212,22 @@ public class KerberosTime implements Cloneable {
|
||||
}
|
||||
|
||||
public void setNow() {
|
||||
long microElapsed = System.nanoTime() / 1000 - initMicro;
|
||||
setTime(initMilli + microElapsed/1000);
|
||||
microSeconds = (int)(microElapsed % 1000);
|
||||
long newMilli = System.currentTimeMillis();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMicroSeconds() {
|
||||
|
||||
@ -375,7 +375,7 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
|
||||
}
|
||||
AuthorizationDataEntry[] auDataEntry = readAuth();
|
||||
AuthorizationData auData = null;
|
||||
if (auData != null) {
|
||||
if (auDataEntry != null) {
|
||||
auData = new AuthorizationData(auDataEntry);
|
||||
}
|
||||
byte[] ticketData = readData();
|
||||
|
||||
@ -209,10 +209,24 @@ public class Credentials {
|
||||
}
|
||||
|
||||
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,
|
||||
cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
|
||||
}
|
||||
|
||||
public KerberosTime getStartTime() {
|
||||
return starttime;
|
||||
}
|
||||
|
||||
public KerberosTime getAuthTime() {
|
||||
return authtime;
|
||||
}
|
||||
@ -221,6 +235,10 @@ public class Credentials {
|
||||
return endtime;
|
||||
}
|
||||
|
||||
public KerberosTime getRenewTill() {
|
||||
return renewTill;
|
||||
}
|
||||
|
||||
public TicketFlags getTicketFlags() {
|
||||
return flags;
|
||||
}
|
||||
@ -228,4 +246,8 @@ public class Credentials {
|
||||
public int getEType() {
|
||||
return key.getEType();
|
||||
}
|
||||
|
||||
public int getTktEType() {
|
||||
return ticket.encPart.getEType();
|
||||
}
|
||||
}
|
||||
|
||||
@ -771,10 +771,15 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
|
||||
implements X509TrustManager {
|
||||
|
||||
// the delegated trust manager
|
||||
private final X509TrustManager tm;
|
||||
|
||||
// Cache the trusted certificate to optimize the performance.
|
||||
private final Collection<X509Certificate> trustedCerts = new HashSet<>();
|
||||
|
||||
AbstractTrustManagerWrapper(X509TrustManager tm) {
|
||||
this.tm = tm;
|
||||
Collections.addAll(trustedCerts, tm.getAcceptedIssuers());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -863,20 +868,7 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
|
||||
constraints = new SSLAlgorithmConstraints(sslSocket, true);
|
||||
}
|
||||
|
||||
AlgorithmChecker checker = new AlgorithmChecker(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");
|
||||
}
|
||||
checkAlgorithmConstraints(chain, constraints);
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,20 +910,33 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
|
||||
constraints = new SSLAlgorithmConstraints(engine, true);
|
||||
}
|
||||
|
||||
AlgorithmChecker checker = new AlgorithmChecker(constraints);
|
||||
try {
|
||||
checker.init(false);
|
||||
checkAlgorithmConstraints(chain, constraints);
|
||||
}
|
||||
}
|
||||
|
||||
// A forward checker, need to check from trust to target
|
||||
for (int i = chain.length - 1; i >= 0; i--) {
|
||||
private void checkAlgorithmConstraints(X509Certificate[] chain,
|
||||
AlgorithmConstraints constraints) throws CertificateException {
|
||||
|
||||
try {
|
||||
// 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
|
||||
if (checkedLength >= 0) {
|
||||
AlgorithmChecker checker = new AlgorithmChecker(constraints);
|
||||
checker.init(false);
|
||||
for (int i = checkedLength; 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");
|
||||
}
|
||||
} catch (CertPathValidatorException cpve) {
|
||||
throw new CertificateException(
|
||||
"Certificates does not conform to algorithm constraints");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1485,7 +1485,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
|
||||
private void closeSocket(boolean selfInitiated) throws IOException {
|
||||
if ((debug != null) && Debug.isOn("ssl")) {
|
||||
System.out.println(threadName() + ", called closeSocket(selfInitiated)");
|
||||
System.out.println(threadName() +
|
||||
", called closeSocket(" + selfInitiated + ")");
|
||||
}
|
||||
if (self == this) {
|
||||
super.close();
|
||||
|
||||
@ -33,18 +33,7 @@ import java.security.*;
|
||||
import java.util.Date;
|
||||
|
||||
import sun.security.pkcs10.PKCS10;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
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;
|
||||
import sun.security.x509.*;
|
||||
|
||||
|
||||
/**
|
||||
@ -165,6 +154,13 @@ public final class CertAndKeyGen {
|
||||
|
||||
publicKey = pair.getPublic();
|
||||
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 {
|
||||
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.
|
||||
@ -200,7 +206,6 @@ public final class CertAndKeyGen {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a self-signed X.509v3 certificate for the public key.
|
||||
* The certificate is immediately valid. No extensions.
|
||||
@ -224,6 +229,15 @@ public final class CertAndKeyGen {
|
||||
X500Name myname, Date firstDate, long validity)
|
||||
throws CertificateException, InvalidKeyException, SignatureException,
|
||||
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;
|
||||
Date lastDate;
|
||||
@ -248,6 +262,7 @@ public final class CertAndKeyGen {
|
||||
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
|
||||
info.set(X509CertInfo.VALIDITY, interval);
|
||||
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(myname));
|
||||
if (ext != null) info.set(X509CertInfo.EXTENSIONS, ext);
|
||||
|
||||
cert = new X509CertImpl(info);
|
||||
cert.sign(privateKey, this.sigAlg);
|
||||
|
||||
@ -1518,9 +1518,16 @@ public final class KeyTool {
|
||||
keypair.generate(keysize);
|
||||
PrivateKey privKey = keypair.getPrivateKey();
|
||||
|
||||
CertificateExtensions ext = createV3Extensions(
|
||||
null,
|
||||
null,
|
||||
v3ext,
|
||||
keypair.getPublicKeyAnyway(),
|
||||
null);
|
||||
|
||||
X509Certificate[] chain = new X509Certificate[1];
|
||||
chain[0] = keypair.getSelfCertificate(
|
||||
x500Name, getStartDate(startDate), validity*24L*60L*60L);
|
||||
x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
|
||||
|
||||
if (verbose) {
|
||||
MessageFormat form = new MessageFormat(rb.getString
|
||||
@ -1537,9 +1544,6 @@ public final class KeyTool {
|
||||
keyPass = promptForKeyPass(alias, null, storePass);
|
||||
}
|
||||
keyStore.setKeyEntry(alias, privKey, keyPass, chain);
|
||||
|
||||
// resign so that -ext are applied.
|
||||
doSelfCert(alias, null, sigAlgName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -59,13 +59,8 @@ typedef double mlib_d64;
|
||||
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__GNUC__)
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <stdint.h> /* for uintptr_t */
|
||||
#include <malloc.h> /* for ptrdiff_t */
|
||||
#else
|
||||
#include <link.h> /* for uintptr_t */
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#endif /* __linux__ */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef MLIB_OS64BIT
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,8 @@
|
||||
|
||||
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
|
||||
@ -46,12 +47,9 @@ public final class FileDescriptor {
|
||||
|
||||
private int fd;
|
||||
|
||||
/**
|
||||
* A counter for tracking the FIS/FOS/RAF instances that
|
||||
* use this FileDescriptor. The FIS/FOS.finalize() will not release
|
||||
* the FileDescriptor if it is still under user by a stream.
|
||||
*/
|
||||
private AtomicInteger useCount;
|
||||
private Closeable parent;
|
||||
private List<Closeable> otherParents;
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* Constructs an (invalid) FileDescriptor
|
||||
@ -59,12 +57,10 @@ public final class FileDescriptor {
|
||||
*/
|
||||
public /**/ FileDescriptor() {
|
||||
fd = -1;
|
||||
useCount = new AtomicInteger();
|
||||
}
|
||||
|
||||
private /* */ FileDescriptor(int fd) {
|
||||
this.fd = fd;
|
||||
useCount = new AtomicInteger();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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 @@
|
||||
#include "java_net_Inet4AddressImpl.h"
|
||||
|
||||
/* the initial size of our hostent buffers */
|
||||
#define HENT_BUF_SIZE 1024
|
||||
#define BIG_HENT_BUF_SIZE 10240 /* a jumbo-sized one */
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* Inet4AddressImpl
|
||||
@ -57,60 +58,36 @@
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
||||
char hostname[MAXHOSTNAMELEN+1];
|
||||
char hostname[NI_MAXHOST+1];
|
||||
|
||||
hostname[0] = '\0';
|
||||
if (JVM_GetHostName(hostname, sizeof(hostname))) {
|
||||
/* Something went wrong, maybe networking is not setup? */
|
||||
strcpy(hostname, "localhost");
|
||||
} else {
|
||||
#ifdef __linux__
|
||||
/* On Linux gethostname() says "host.domain.sun.com". On
|
||||
* Solaris gethostname() says "host", so extra work is needed.
|
||||
*/
|
||||
#else
|
||||
/* Solaris doesn't want to give us a fully qualified domain name.
|
||||
* We do a reverse lookup to try and get one. This works
|
||||
* if DNS occurs before NIS in /etc/resolv.conf, but fails
|
||||
* if NIS comes first (it still gets only a partial name).
|
||||
* We use thread-safe system calls.
|
||||
*/
|
||||
#endif /* __linux__ */
|
||||
struct hostent res, res2, *hp;
|
||||
// these buffers must be pointer-aligned so they are declared
|
||||
// with pointer type
|
||||
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
|
||||
char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
|
||||
int h_error=0;
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
|
||||
// ensure null-terminated
|
||||
hostname[MAXHOSTNAMELEN] = '\0';
|
||||
hostname[NI_MAXHOST] = '\0';
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
#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
|
||||
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);
|
||||
}
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
if (error == 0) {/* host is known to name service */
|
||||
getnameinfo(res->ai_addr,
|
||||
res->ai_addrlen,
|
||||
hostname,
|
||||
NI_MAXHOST,
|
||||
NULL,
|
||||
0,
|
||||
NI_NAMEREQD);
|
||||
|
||||
/* if getnameinfo fails hostname is still the value
|
||||
from gethostname */
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
return (*env)->NewStringUTF(env, hostname);
|
||||
@ -140,14 +117,9 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
jstring host) {
|
||||
const char *hostname;
|
||||
jobjectArray ret = 0;
|
||||
struct hostent res, *hp = 0;
|
||||
// this buffer must be pointer-aligned so is declared
|
||||
// with pointer type
|
||||
char *buf[HENT_BUF_SIZE/(sizeof (char *))];
|
||||
|
||||
/* temporary buffer, on the off chance we need to expand */
|
||||
char *tmp = NULL;
|
||||
int h_error=0;
|
||||
int retLen = 0;
|
||||
int error = 0;
|
||||
struct addrinfo hints, *res, *resNew = NULL;
|
||||
|
||||
if (!initialized) {
|
||||
ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
|
||||
@ -168,6 +140,11 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
|
||||
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__
|
||||
/*
|
||||
* Workaround for Solaris bug 4160367 - if a hostname contains a
|
||||
@ -181,69 +158,93 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try once, with our static buffer. */
|
||||
#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
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
/* With the re-entrant system calls, it's possible that the buffer
|
||||
* we pass to it is not large enough to hold an exceptionally
|
||||
* large DNS entry. This is signaled by errno->ERANGE. We try once
|
||||
* more, with a very big size.
|
||||
*/
|
||||
if (hp == NULL && errno == ERANGE) {
|
||||
if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
|
||||
#ifdef __GLIBC__
|
||||
gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
|
||||
&hp, &h_error);
|
||||
#else
|
||||
hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
|
||||
&h_error);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (hp != NULL) {
|
||||
struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
|
||||
if (error) {
|
||||
/* report error */
|
||||
ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
} else {
|
||||
int i = 0;
|
||||
struct addrinfo *itr, *last = NULL, *iterator = res;
|
||||
|
||||
while (*addrp != (struct in_addr *) 0) {
|
||||
i++;
|
||||
addrp++;
|
||||
while (iterator != NULL) {
|
||||
// remove the duplicate one
|
||||
int skip = 0;
|
||||
itr = resNew;
|
||||
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;
|
||||
}
|
||||
last = next;
|
||||
i++;
|
||||
}
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
|
||||
ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
|
||||
retLen = i;
|
||||
iterator = resNew;
|
||||
|
||||
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
|
||||
|
||||
if (IS_NULL(ret)) {
|
||||
/* we may have memory to free at the end of this */
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
addrp = (struct in_addr **) hp->h_addr_list;
|
||||
|
||||
i = 0;
|
||||
while (*addrp) {
|
||||
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
|
||||
if (IS_NULL(iaObj)) {
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
(*env)->SetIntField(env, iaObj, ni_iaaddressID,
|
||||
ntohl((*addrp)->s_addr));
|
||||
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
|
||||
(*env)->SetObjectArrayElement(env, ret, i, iaObj);
|
||||
addrp++;
|
||||
i++;
|
||||
while (iterator != NULL) {
|
||||
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
|
||||
if (IS_NULL(iaObj)) {
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
(*env)->SetIntField(env, iaObj, ni_iaaddressID,
|
||||
ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
||||
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
|
||||
(*env)->SetObjectArrayElement(env, ret, i++, iaObj);
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
} else {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
|
||||
(char *)hostname);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
cleanupAndReturn:
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
if (tmp != NULL) {
|
||||
free(tmp);
|
||||
cleanupAndReturn:
|
||||
{
|
||||
struct addrinfo *iterator, *tmp;
|
||||
iterator = resNew;
|
||||
while (iterator != NULL) {
|
||||
tmp = iterator;
|
||||
iterator = iterator->ai_next;
|
||||
free(tmp);
|
||||
}
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -256,63 +257,38 @@ JNIEXPORT jstring JNICALL
|
||||
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
|
||||
jbyteArray addrArray) {
|
||||
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;
|
||||
|
||||
/*
|
||||
* We are careful here to use the reentrant version of
|
||||
* gethostbyname because at the Java level this routine is not
|
||||
* protected by any synchronization.
|
||||
*
|
||||
* Still keeping the reentrant platform dependent calls temporarily
|
||||
* We should probably conform to one interface later.
|
||||
*
|
||||
*/
|
||||
char host[NI_MAXHOST+1];
|
||||
int error = 0;
|
||||
int len = 0;
|
||||
jbyte caddr[4];
|
||||
|
||||
struct sockaddr_in him4;
|
||||
struct sockaddr *sa;
|
||||
|
||||
jint addr;
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
|
||||
addr = ((caddr[0]<<24) & 0xff000000);
|
||||
addr |= ((caddr[1] <<16) & 0xff0000);
|
||||
addr |= ((caddr[2] <<8) & 0xff00);
|
||||
addr |= (caddr[3] & 0xff);
|
||||
addr = htonl(addr);
|
||||
#ifdef __GLIBC__
|
||||
gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
|
||||
(char*)buf, sizeof(buf), &hp, &h_error);
|
||||
#else
|
||||
hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
|
||||
(char*)buf, sizeof(buf), &h_error);
|
||||
#endif
|
||||
/* With the re-entrant system calls, it's possible that the buffer
|
||||
* we pass to it is not large enough to hold an exceptionally
|
||||
* large DNS entry. This is signaled by errno->ERANGE. We try once
|
||||
* 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");
|
||||
}
|
||||
memset((void *) &him4, 0, sizeof(him4));
|
||||
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
|
||||
him4.sin_family = AF_INET;
|
||||
sa = (struct sockaddr *) &him4;
|
||||
len = sizeof(him4);
|
||||
|
||||
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
|
||||
NI_NAMEREQD);
|
||||
|
||||
if (!error) {
|
||||
ret = (*env)->NewStringUTF(env, host);
|
||||
}
|
||||
if (hp == NULL) {
|
||||
|
||||
if (ret == NULL) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
|
||||
} else {
|
||||
ret = (*env)->NewStringUTF(env, hp->h_name);
|
||||
}
|
||||
if (tmp) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -82,31 +82,29 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
||||
* We use thread-safe system calls.
|
||||
*/
|
||||
#ifdef AF_INET6
|
||||
if (NET_addrtransAvailable()) {
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
|
||||
bzero(&hints, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
if (error == 0) {
|
||||
/* host is known to name service */
|
||||
error = (*getnameinfo_ptr)(res->ai_addr,
|
||||
res->ai_addrlen,
|
||||
hostname,
|
||||
NI_MAXHOST,
|
||||
NULL,
|
||||
0,
|
||||
NI_NAMEREQD);
|
||||
if (error == 0) {
|
||||
/* host is known to name service */
|
||||
error = getnameinfo(res->ai_addr,
|
||||
res->ai_addrlen,
|
||||
hostname,
|
||||
NI_MAXHOST,
|
||||
NULL,
|
||||
0,
|
||||
NI_NAMEREQD);
|
||||
|
||||
/* if getnameinfo fails hostname is still the value
|
||||
from gethostname */
|
||||
/* if getnameinfo fails hostname is still the value
|
||||
from gethostname */
|
||||
|
||||
(*freeaddrinfo_ptr)(res);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
#endif /* __linux__ */
|
||||
@ -173,193 +171,191 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
CHECK_NULL_RETURN(hostname, NULL);
|
||||
|
||||
#ifdef AF_INET6
|
||||
if (NET_addrtransAvailable()) {
|
||||
static jfieldID ia_preferIPv6AddressID;
|
||||
if (ia_preferIPv6AddressID == NULL) {
|
||||
jclass c = (*env)->FindClass(env,"java/net/InetAddress");
|
||||
if (c) {
|
||||
ia_preferIPv6AddressID =
|
||||
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
|
||||
}
|
||||
if (ia_preferIPv6AddressID == NULL) {
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
}
|
||||
static jfieldID ia_preferIPv6AddressID;
|
||||
if (ia_preferIPv6AddressID == NULL) {
|
||||
jclass c = (*env)->FindClass(env,"java/net/InetAddress");
|
||||
if (c) {
|
||||
ia_preferIPv6AddressID =
|
||||
(*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
|
||||
}
|
||||
/* get the address preference */
|
||||
preferIPv6Address
|
||||
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
|
||||
if (ia_preferIPv6AddressID == NULL) {
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* get the address preference */
|
||||
preferIPv6Address
|
||||
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
|
||||
|
||||
/* Try once, with our static buffer. */
|
||||
bzero(&hints, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
/* Try once, with our static buffer. */
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
#ifdef __solaris__
|
||||
/*
|
||||
* Workaround for Solaris bug 4160367 - if a hostname contains a
|
||||
* white space then 0.0.0.0 is returned
|
||||
*/
|
||||
if (isspace((unsigned char)hostname[0])) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
|
||||
hostname);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Workaround for Solaris bug 4160367 - if a hostname contains a
|
||||
* white space then 0.0.0.0 is returned
|
||||
*/
|
||||
if (isspace((unsigned char)hostname[0])) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
|
||||
hostname);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
if (error) {
|
||||
/* report error */
|
||||
ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
} else {
|
||||
int i = 0;
|
||||
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
|
||||
struct addrinfo *itr, *last = NULL, *iterator = res;
|
||||
while (iterator != NULL) {
|
||||
int skip = 0;
|
||||
itr = resNew;
|
||||
while (itr != NULL) {
|
||||
if (iterator->ai_family == itr->ai_family &&
|
||||
iterator->ai_addrlen == itr->ai_addrlen) {
|
||||
if (itr->ai_family == AF_INET) { /* AF_INET */
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
int t;
|
||||
struct sockaddr_in6 *addr1, *addr2;
|
||||
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
|
||||
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
|
||||
if (error) {
|
||||
/* report error */
|
||||
ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
} else {
|
||||
int i = 0;
|
||||
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
|
||||
struct addrinfo *itr, *last = NULL, *iterator = res;
|
||||
while (iterator != NULL) {
|
||||
int skip = 0;
|
||||
itr = resNew;
|
||||
while (itr != NULL) {
|
||||
if (iterator->ai_family == itr->ai_family &&
|
||||
iterator->ai_addrlen == itr->ai_addrlen) {
|
||||
if (itr->ai_family == AF_INET) { /* AF_INET */
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
int t;
|
||||
struct sockaddr_in6 *addr1, *addr2;
|
||||
addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
|
||||
addr2 = (struct sockaddr_in6 *)itr->ai_addr;
|
||||
|
||||
for (t = 0; t < 16; t++) {
|
||||
if (addr1->sin6_addr.s6_addr[t] !=
|
||||
addr2->sin6_addr.s6_addr[t]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (t < 16) {
|
||||
itr = itr->ai_next;
|
||||
continue;
|
||||
} else {
|
||||
skip = 1;
|
||||
for (t = 0; t < 16; t++) {
|
||||
if (addr1->sin6_addr.s6_addr[t] !=
|
||||
addr2->sin6_addr.s6_addr[t]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (iterator->ai_family != AF_INET &&
|
||||
iterator->ai_family != AF_INET6) {
|
||||
/* we can't handle other family types */
|
||||
skip = 1;
|
||||
break;
|
||||
if (t < 16) {
|
||||
itr = itr->ai_next;
|
||||
continue;
|
||||
} else {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
itr = itr->ai_next;
|
||||
} else if (iterator->ai_family != AF_INET &&
|
||||
iterator->ai_family != AF_INET6) {
|
||||
/* we can't handle other family types */
|
||||
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;
|
||||
}
|
||||
last = next;
|
||||
i++;
|
||||
if (iterator->ai_family == AF_INET) {
|
||||
inetCount ++;
|
||||
} else if (iterator->ai_family == AF_INET6) {
|
||||
inet6Count ++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
last = next;
|
||||
i++;
|
||||
if (iterator->ai_family == AF_INET) {
|
||||
inetCount ++;
|
||||
} else if (iterator->ai_family == AF_INET6) {
|
||||
inet6Count ++;
|
||||
}
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
retLen = i;
|
||||
iterator = resNew;
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
retLen = i;
|
||||
iterator = resNew;
|
||||
|
||||
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
|
||||
ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
|
||||
|
||||
if (IS_NULL(ret)) {
|
||||
/* we may have memory to free at the end of this */
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
if (IS_NULL(ret)) {
|
||||
/* we may have memory to free at the end of this */
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
|
||||
if (preferIPv6Address) {
|
||||
/* AF_INET addresses will be offset by inet6Count */
|
||||
inetIndex = inet6Count;
|
||||
inet6Index = 0;
|
||||
} else {
|
||||
/* AF_INET6 addresses will be offset by inetCount */
|
||||
inetIndex = 0;
|
||||
inet6Index = inetCount;
|
||||
}
|
||||
if (preferIPv6Address) {
|
||||
/* AF_INET addresses will be offset by inet6Count */
|
||||
inetIndex = inet6Count;
|
||||
inet6Index = 0;
|
||||
} else {
|
||||
/* AF_INET6 addresses will be offset by inetCount */
|
||||
inetIndex = 0;
|
||||
inet6Index = inetCount;
|
||||
}
|
||||
|
||||
while (iterator != NULL) {
|
||||
if (iterator->ai_family == AF_INET) {
|
||||
while (iterator != NULL) {
|
||||
if (iterator->ai_family == AF_INET) {
|
||||
jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
|
||||
if (IS_NULL(iaObj)) {
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
(*env)->SetIntField(env, iaObj, ni_iaaddressID,
|
||||
ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
||||
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
|
||||
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
|
||||
inetIndex++;
|
||||
} else if (iterator->ai_family == AF_INET6) {
|
||||
} else if (iterator->ai_family == AF_INET6) {
|
||||
jint scope = 0;
|
||||
jbyteArray ipaddress;
|
||||
|
||||
jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
|
||||
if (IS_NULL(iaObj)) {
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
ipaddress = (*env)->NewByteArray(env, 16);
|
||||
if (IS_NULL(ipaddress)) {
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
|
||||
(jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
|
||||
#ifdef __linux__
|
||||
if (!kernelIsV22()) {
|
||||
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
|
||||
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
|
||||
}
|
||||
#else
|
||||
scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
|
||||
#endif
|
||||
if (scope != 0) { /* zero is default value, no need to set */
|
||||
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
|
||||
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
|
||||
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
|
||||
(*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
|
||||
}
|
||||
(*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
|
||||
(*env)->SetObjectField(env, iaObj, ni_iahostID, host);
|
||||
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
|
||||
inet6Index++;
|
||||
}
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
cleanupAndReturn:
|
||||
cleanupAndReturn:
|
||||
{
|
||||
struct addrinfo *iterator, *tmp;
|
||||
struct addrinfo *iterator, *tmp;
|
||||
iterator = resNew;
|
||||
while (iterator != NULL) {
|
||||
tmp = iterator;
|
||||
@ -369,8 +365,7 @@ cleanupAndReturn:
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
}
|
||||
|
||||
if (NET_addrtransAvailable())
|
||||
(*freeaddrinfo_ptr)(res);
|
||||
freeaddrinfo(res);
|
||||
#endif /* AF_INET6 */
|
||||
|
||||
return ret;
|
||||
@ -393,44 +388,42 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
|
||||
int len = 0;
|
||||
jbyte caddr[16];
|
||||
|
||||
if (NET_addrtransAvailable()) {
|
||||
struct sockaddr_in him4;
|
||||
struct sockaddr_in6 him6;
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr_in him4;
|
||||
struct sockaddr_in6 him6;
|
||||
struct sockaddr *sa;
|
||||
|
||||
/*
|
||||
* For IPv4 addresses construct a sockaddr_in structure.
|
||||
*/
|
||||
if ((*env)->GetArrayLength(env, addrArray) == 4) {
|
||||
jint addr;
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
|
||||
addr = ((caddr[0]<<24) & 0xff000000);
|
||||
addr |= ((caddr[1] <<16) & 0xff0000);
|
||||
addr |= ((caddr[2] <<8) & 0xff00);
|
||||
addr |= (caddr[3] & 0xff);
|
||||
memset((void *) &him4, 0, sizeof(him4));
|
||||
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
|
||||
him4.sin_family = AF_INET;
|
||||
sa = (struct sockaddr *) &him4;
|
||||
len = sizeof(him4);
|
||||
} else {
|
||||
/*
|
||||
* For IPv4 addresses construct a sockaddr_in structure.
|
||||
* For IPv6 address construct a sockaddr_in6 structure.
|
||||
*/
|
||||
if ((*env)->GetArrayLength(env, addrArray) == 4) {
|
||||
jint addr;
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
|
||||
addr = ((caddr[0]<<24) & 0xff000000);
|
||||
addr |= ((caddr[1] <<16) & 0xff0000);
|
||||
addr |= ((caddr[2] <<8) & 0xff00);
|
||||
addr |= (caddr[3] & 0xff);
|
||||
memset((void *) &him4, 0, sizeof(him4));
|
||||
him4.sin_addr.s_addr = (uint32_t) htonl(addr);
|
||||
him4.sin_family = AF_INET;
|
||||
sa = (struct sockaddr *) &him4;
|
||||
len = sizeof(him4);
|
||||
} else {
|
||||
/*
|
||||
* For IPv6 address construct a sockaddr_in6 structure.
|
||||
*/
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
|
||||
memset((void *) &him6, 0, sizeof(him6));
|
||||
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
|
||||
him6.sin6_family = AF_INET6;
|
||||
sa = (struct sockaddr *) &him6 ;
|
||||
len = sizeof(him6) ;
|
||||
}
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
|
||||
memset((void *) &him6, 0, sizeof(him6));
|
||||
memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
|
||||
him6.sin6_family = AF_INET6;
|
||||
sa = (struct sockaddr *) &him6 ;
|
||||
len = sizeof(him6) ;
|
||||
}
|
||||
|
||||
error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
|
||||
NI_NAMEREQD);
|
||||
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
|
||||
NI_NAMEREQD);
|
||||
|
||||
if (!error) {
|
||||
ret = (*env)->NewStringUTF(env, host);
|
||||
}
|
||||
if (!error) {
|
||||
ret = (*env)->NewStringUTF(env, host);
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
|
||||
|
||||
@ -377,37 +377,12 @@ jint IPv6_supported()
|
||||
* we should also check if the APIs are available.
|
||||
*/
|
||||
ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
|
||||
if (ipv6_fn == NULL ) {
|
||||
close(fd);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
if (ipv6_fn == NULL ) {
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
}
|
||||
|
||||
@ -920,10 +895,6 @@ NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
jboolean NET_addrtransAvailable() {
|
||||
return (jboolean)(getaddrinfo_ptr != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the Java level socket option to the platform specific
|
||||
* level and option name.
|
||||
|
||||
@ -102,10 +102,6 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
|
||||
const char* hostname,
|
||||
int gai_error);
|
||||
|
||||
/* do we have address translation support */
|
||||
|
||||
extern jboolean NET_addrtransAvailable();
|
||||
|
||||
#define NET_WAIT_READ 0x01
|
||||
#define NET_WAIT_WRITE 0x02
|
||||
#define NET_WAIT_CONNECT 0x04
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,8 @@
|
||||
|
||||
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
|
||||
@ -45,13 +46,9 @@ public final class FileDescriptor {
|
||||
|
||||
private long handle;
|
||||
|
||||
/**
|
||||
* A use counter for tracking the FIS/FOS/RAF instances that
|
||||
* use this FileDescriptor. The FIS/FOS.finalize() will not release
|
||||
* the FileDescriptor if it is still under use by any stream.
|
||||
*/
|
||||
private AtomicInteger useCount;
|
||||
|
||||
private Closeable parent;
|
||||
private List<Closeable> otherParents;
|
||||
private boolean closed;
|
||||
|
||||
/**
|
||||
* Constructs an (invalid) FileDescriptor
|
||||
@ -60,7 +57,6 @@ public final class FileDescriptor {
|
||||
public /**/ FileDescriptor() {
|
||||
fd = -1;
|
||||
handle = -1;
|
||||
useCount = new AtomicInteger();
|
||||
}
|
||||
|
||||
static {
|
||||
@ -168,13 +164,67 @@ public final class FileDescriptor {
|
||||
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
|
||||
|
||||
void socketSetOption(int cmd, boolean on, Object value)
|
||||
throws SocketException {
|
||||
socketSetOption(cmd, on, value);
|
||||
impl.socketSetOption(cmd, on, value);
|
||||
}
|
||||
|
||||
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
|
||||
|
||||
@ -207,7 +207,7 @@ public class Klist {
|
||||
}
|
||||
if (options[2] == 't') {
|
||||
System.out.println("\t Time stamp: " +
|
||||
reformat(entries[i].getTimeStamp().toDate().toString()));
|
||||
format(entries[i].getTimeStamp()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,30 +234,39 @@ public class Klist {
|
||||
System.out.println("\nDefault principal: " +
|
||||
defaultPrincipal + ", " +
|
||||
creds.length + " entries found.\n");
|
||||
String starttime = null;
|
||||
String endtime = null;
|
||||
String servicePrincipal = null;
|
||||
String etype = null;
|
||||
if (creds != null) {
|
||||
for (int i = 0; i < creds.length; i++) {
|
||||
try {
|
||||
starttime =
|
||||
reformat(creds[i].getAuthTime().toDate().toString());
|
||||
endtime =
|
||||
reformat(creds[i].getEndTime().toDate().toString());
|
||||
String starttime;
|
||||
String endtime;
|
||||
String renewTill;
|
||||
String servicePrincipal;
|
||||
if (creds[i].getStartTime() != null) {
|
||||
starttime = format(creds[i].getStartTime());
|
||||
} else {
|
||||
starttime = format(creds[i].getAuthTime());
|
||||
}
|
||||
endtime = format(creds[i].getEndTime());
|
||||
servicePrincipal =
|
||||
creds[i].getServicePrincipal().toString();
|
||||
System.out.println("[" + (i + 1) + "] " +
|
||||
" Service Principal: " +
|
||||
servicePrincipal);
|
||||
System.out.println(" Valid starting: " + starttime);
|
||||
System.out.println(" Expires: " + endtime);
|
||||
System.out.println(" Valid starting: " + starttime);
|
||||
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') {
|
||||
etype = EType.toString(creds[i].getEType());
|
||||
System.out.println(" Encryption type: " + etype);
|
||||
String eskey = EType.toString(creds[i].getEType());
|
||||
String etkt = EType.toString(creds[i].getTktEType());
|
||||
System.out.println(" EType (skey, tkt): "
|
||||
+ eskey + ", " + etkt);
|
||||
}
|
||||
if (options[1] == 'f') {
|
||||
System.out.println(" Flags: " +
|
||||
System.out.println(" Flags: " +
|
||||
creds[i].getTicketFlags().toString());
|
||||
}
|
||||
if (options[2] == 'a') {
|
||||
@ -312,13 +321,14 @@ public class Klist {
|
||||
* and yyyy is the year.
|
||||
* @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) +
|
||||
", " + date.substring(24)
|
||||
+ " " + date.substring(11, 16));
|
||||
+ " " + date.substring(11, 19));
|
||||
}
|
||||
/**
|
||||
* Printes out the help information.
|
||||
* Prints out the help information.
|
||||
*/
|
||||
void printHelp() {
|
||||
System.out.println("\nUsage: klist " +
|
||||
|
||||
@ -167,7 +167,7 @@ Greenwich Standard Time:88,89::GMT:
|
||||
Argentina Standard Time:900,900::America/Buenos_Aires:
|
||||
Azerbaijan Standard Time:901,901:AZ:Asia/Baku:
|
||||
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:
|
||||
Georgian Standard Time:905,905:GE:Asia/Tbilisi:
|
||||
Jordan Standard Time:906,906:JO:Asia/Amman:
|
||||
@ -189,5 +189,7 @@ UTC-11:921,921::GMT-1100:
|
||||
Ulaanbaatar Standard Time:922,922::Asia/Ulaanbaatar:
|
||||
Venezuela Standard Time:923,923::America/Caracas:
|
||||
Magadan Standard Time:924,924::Asia/Magadan:
|
||||
Western Brazilian Standard Time:925,925:BR:America/Rio_Branco:
|
||||
Armenian Standard Time:926,926:AM:Asia/Yerevan:
|
||||
Kaliningrad Standard Time:925,925:RU:Europe/Kaliningrad:
|
||||
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:
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 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 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.nio.*;
|
||||
import java.nio.channels.*;
|
||||
|
||||
public class FileChannelFDTest {
|
||||
|
||||
static byte data[] = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57,};
|
||||
static String inFileName = "fd-in-test.txt";
|
||||
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)
|
||||
throws Exception {
|
||||
|
||||
inFile= new File(System.getProperty("test.dir", "."),
|
||||
inFileName);
|
||||
inFile.createNewFile();
|
||||
inFile.deleteOnExit();
|
||||
writeToInFile();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -23,10 +23,9 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6322678 7082769
|
||||
* @summary FileInputStream/FileOutputStream/RandomAccessFile allow file descriptor
|
||||
* to be closed while still in use.
|
||||
* @run main/othervm FileDescriptorSharing
|
||||
* @bug 7105952 6322678 7082769
|
||||
* @summary Improve finalisation for FileInputStream/FileOutputStream/RandomAccessFile
|
||||
* @run main/othervm Sharing
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
@ -34,7 +33,7 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class FileDescriptorSharing {
|
||||
public class Sharing {
|
||||
|
||||
final static int numFiles = 10;
|
||||
volatile static boolean fail;
|
||||
@ -44,11 +43,12 @@ public class FileDescriptorSharing {
|
||||
TestMultipleFD();
|
||||
TestIsValid();
|
||||
MultiThreadedFD();
|
||||
TestCloseAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* We shouldn't discard a file descriptor until all streams have
|
||||
* finished with it
|
||||
* Finalizer shouldn't discard a file descriptor until all streams have
|
||||
* finished with it.
|
||||
*/
|
||||
private static void TestFinalizer() throws Exception {
|
||||
FileDescriptor fd = null;
|
||||
@ -96,9 +96,6 @@ public class FileDescriptorSharing {
|
||||
System.out.print(".");
|
||||
ret = fis3.read();
|
||||
}
|
||||
if(!fd.valid()) {
|
||||
throw new RuntimeException("TestFinalizer() : FileDescriptor should be valid");
|
||||
}
|
||||
} finally {
|
||||
testFinalizerFile.delete();
|
||||
}
|
||||
@ -194,23 +191,19 @@ public class FileDescriptorSharing {
|
||||
} finally {
|
||||
try {
|
||||
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()) {
|
||||
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();
|
||||
} finally {
|
||||
test1.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close out in different order to ensure FD is not
|
||||
* closed out too early
|
||||
* Close out in different order to ensure FD is
|
||||
* closed correctly.
|
||||
*/
|
||||
File test2 = new File("test2");
|
||||
try {
|
||||
@ -221,14 +214,11 @@ public class FileDescriptorSharing {
|
||||
} finally {
|
||||
try {
|
||||
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()) {
|
||||
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 {
|
||||
test2.delete();
|
||||
}
|
||||
@ -244,14 +234,11 @@ public class FileDescriptorSharing {
|
||||
} finally {
|
||||
try {
|
||||
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()) {
|
||||
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 {
|
||||
test3.delete();
|
||||
}
|
||||
@ -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 {
|
||||
RandomAccessFile raf = null;
|
||||
@ -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
|
||||
* FileOutputStreams referencing the same native file descriptor.
|
||||
@ -325,12 +374,35 @@ public class FileDescriptorSharing {
|
||||
System.out.println("OpenClose encountered IO issue :" + ioe);
|
||||
fail = true;
|
||||
} finally {
|
||||
if (!fd.valid()) { // fd should still be valid given RAF reference
|
||||
System.out.println("OpenClose: FileDescriptor should be valid");
|
||||
if (fd.valid()) { // fd should not be valid after first close() call
|
||||
System.out.println("OpenClose: FileDescriptor shouldn't be valid");
|
||||
fail = true;
|
||||
}
|
||||
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 @@
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
public class StreamsSurviveDestroy {
|
||||
@ -40,15 +41,17 @@ public class StreamsSurviveDestroy {
|
||||
boolean wantInterrupt;
|
||||
boolean acceptException;
|
||||
Exception exc = null;
|
||||
CountDownLatch latch;
|
||||
|
||||
Copier(String name, InputStream in, OutputStream out,
|
||||
boolean ae, boolean wi)
|
||||
boolean ae, boolean wi, CountDownLatch l)
|
||||
{
|
||||
this.name = name;
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.acceptException = ae;
|
||||
this.wantInterrupt = wi;
|
||||
this.latch = l;
|
||||
setName(name);
|
||||
start();
|
||||
}
|
||||
@ -59,6 +62,7 @@ public class StreamsSurviveDestroy {
|
||||
|
||||
public void run() {
|
||||
byte[] buf = new byte[4242];
|
||||
latch.countDown();
|
||||
for (;;) {
|
||||
try {
|
||||
int n = in.read(buf);
|
||||
@ -95,13 +99,17 @@ public class StreamsSurviveDestroy {
|
||||
}
|
||||
|
||||
static void test() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
|
||||
System.err.println("test");
|
||||
Process p = Runtime.getRuntime().exec("/bin/cat");
|
||||
Copier cp1 = new Copier("out", p.getInputStream(), System.err,
|
||||
false, false);
|
||||
false, false, latch);
|
||||
Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
|
||||
false, false);
|
||||
Thread.sleep(100);
|
||||
false, false, latch);
|
||||
latch.await(); // Wait till both Copiers about to read
|
||||
Thread.sleep(100);// Give both Copiers a chance to start read
|
||||
|
||||
p.destroy();
|
||||
System.err.println(" exit: " + p.waitFor());
|
||||
cp1.join();
|
||||
@ -111,13 +119,17 @@ public class StreamsSurviveDestroy {
|
||||
}
|
||||
|
||||
static void testCloseBeforeDestroy() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
|
||||
System.err.println("testCloseBeforeDestroy");
|
||||
Process p = Runtime.getRuntime().exec("/bin/cat");
|
||||
Copier cp1 = new Copier("out", p.getInputStream(), System.err,
|
||||
true, false);
|
||||
true, false, latch);
|
||||
Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
|
||||
true, false);
|
||||
Thread.sleep(100);
|
||||
true, false, latch);
|
||||
latch.await(); // Wait till both Copiers about to read
|
||||
Thread.sleep(100);// Give both Copiers a chance to start read
|
||||
|
||||
p.getInputStream().close();
|
||||
p.getErrorStream().close();
|
||||
p.destroy();
|
||||
@ -129,13 +141,17 @@ public class StreamsSurviveDestroy {
|
||||
}
|
||||
|
||||
static void testCloseAfterDestroy() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
System.err.println("testCloseAfterDestroy");
|
||||
Process p = Runtime.getRuntime().exec("/bin/cat");
|
||||
Copier cp1 = new Copier("out", p.getInputStream(), System.err,
|
||||
true, false);
|
||||
true, false,latch);
|
||||
Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
|
||||
true, false);
|
||||
Thread.sleep(100);
|
||||
true, false, latch);
|
||||
|
||||
latch.await(); // Wait till both Copiers about to read
|
||||
Thread.sleep(100);// Give both Copiers a chance to start read
|
||||
|
||||
p.destroy();
|
||||
p.getInputStream().close();
|
||||
p.getErrorStream().close();
|
||||
@ -147,13 +163,16 @@ public class StreamsSurviveDestroy {
|
||||
}
|
||||
|
||||
static void testInterrupt() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
System.err.println("testInterrupt");
|
||||
Process p = Runtime.getRuntime().exec("/bin/cat");
|
||||
Copier cp1 = new Copier("out", p.getInputStream(), System.err,
|
||||
false, true);
|
||||
false, true, latch);
|
||||
Copier cp2 = new Copier("err", p.getErrorStream(), System.err,
|
||||
false, true);
|
||||
Thread.sleep(100);
|
||||
false, true, latch);
|
||||
latch.await(); // Wait till both Copiers about to read
|
||||
Thread.sleep(100);// Give both Copiers a chance to start read
|
||||
|
||||
cp1.interrupt();
|
||||
cp2.interrupt();
|
||||
Thread.sleep(100);
|
||||
@ -176,7 +195,5 @@ public class StreamsSurviveDestroy {
|
||||
testCloseBeforeDestroy();
|
||||
testCloseAfterDestroy();
|
||||
testInterrupt();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6576763
|
||||
* @ignore until hotspot 6776144 bug is resolved
|
||||
* @summary (thread) Thread constructors throw undocumented NPE for null name
|
||||
*/
|
||||
|
||||
@ -64,8 +63,8 @@ public class NullThreadName
|
||||
try { Thread.sleep(2000); }
|
||||
catch (InterruptedException unused) {}
|
||||
|
||||
/* do not wait forever */
|
||||
if (count++ > 5)
|
||||
/* do not wait forever - allow 120 seconds same as jtreg default timeout. */
|
||||
if (count++ > 60)
|
||||
throw new AssertionError("GoodThread is still alive!");
|
||||
}
|
||||
|
||||
|
||||
@ -29,37 +29,58 @@
|
||||
*/
|
||||
|
||||
public class Stop implements Runnable {
|
||||
private static Thread first=null;
|
||||
private static Thread second=null;
|
||||
private static ThreadGroup group = new ThreadGroup("");
|
||||
private static boolean groupStopped = false ;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
Stop() {
|
||||
Thread thread = new Thread(group, this);
|
||||
if (first == null)
|
||||
first = thread;
|
||||
else
|
||||
second = thread;
|
||||
|
||||
thread.start();
|
||||
}
|
||||
private static final ThreadGroup group = new ThreadGroup("");
|
||||
private static final Thread first = new Thread(group, new Stop());
|
||||
private static final Thread second = new Thread(group, new Stop());
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
// Give the other thread a chance to start
|
||||
try {
|
||||
Thread.sleep(1000); // Give other thread a chance to start
|
||||
if (Thread.currentThread() == first)
|
||||
group.stop();
|
||||
} catch(InterruptedException e){
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
// When the first thread runs, it will stop the group.
|
||||
if (Thread.currentThread() == first) {
|
||||
synchronized (lock) {
|
||||
try {
|
||||
group.stop();
|
||||
} 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 {
|
||||
for (int i=0; i<2; i++)
|
||||
new Stop();
|
||||
Thread.sleep(3000);
|
||||
// Launch two threads as part of the same thread group
|
||||
first.start();
|
||||
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();
|
||||
first.stop(); second.stop();
|
||||
|
||||
// Clean up any threads that may have not been terminated
|
||||
first.stop();
|
||||
second.stop();
|
||||
if (failed)
|
||||
throw new RuntimeException("Failure.");
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7024172
|
||||
* @bug 7024172 7067691
|
||||
* @summary Test if proxy for PlatformLoggingMXBean is equivalent
|
||||
* to proxy for LoggingMXBean
|
||||
*
|
||||
@ -43,6 +43,13 @@ public class LoggingMXBeanTest
|
||||
static String LOGGER_NAME_2 = "com.sun.management.Logger.Logger2";
|
||||
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 {
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
LoggingMXBean proxy =
|
||||
@ -51,7 +58,7 @@ public class LoggingMXBeanTest
|
||||
LoggingMXBean.class);
|
||||
|
||||
// test LoggingMXBean proxy
|
||||
LoggingMXBeanTest p = new LoggingMXBeanTest(proxy);
|
||||
test = new LoggingMXBeanTest(proxy);
|
||||
|
||||
// check if the attributes implemented by PlatformLoggingMXBean
|
||||
// and LoggingMXBean return the same value
|
||||
@ -64,9 +71,9 @@ public class LoggingMXBeanTest
|
||||
// same verification as in java/util/logging/LoggingMXBeanTest2
|
||||
public LoggingMXBeanTest(LoggingMXBean mbean) throws Exception {
|
||||
|
||||
Logger logger1 = Logger.getLogger( LOGGER_NAME_1 );
|
||||
logger1 = Logger.getLogger( LOGGER_NAME_1 );
|
||||
logger1.setLevel(Level.FINE);
|
||||
Logger logger2 = Logger.getLogger( LOGGER_NAME_2 );
|
||||
logger2 = Logger.getLogger( LOGGER_NAME_2 );
|
||||
logger2.setLevel(null);
|
||||
|
||||
/*
|
||||
@ -207,6 +214,7 @@ public class LoggingMXBeanTest
|
||||
// verify logger names
|
||||
List<String> loggers1 = mxbean1.getLoggerNames();
|
||||
List<String> loggers2 = mxbean2.getLoggerNames();
|
||||
|
||||
if (loggers1.size() != loggers2.size())
|
||||
throw new RuntimeException("LoggerNames: unmatched number of entries");
|
||||
List<String> loggers3 = new ArrayList<>(loggers1);
|
||||
@ -219,7 +227,10 @@ public class LoggingMXBeanTest
|
||||
if (!mxbean1.getLoggerLevel(logger)
|
||||
.equals(mxbean2.getLoggerLevel(logger)))
|
||||
throw new RuntimeException(
|
||||
"LoggerLevel: unmatched level for " + logger);
|
||||
"LoggerLevel: unmatched level for " + logger
|
||||
+ ", " + mxbean1.getLoggerLevel(logger)
|
||||
+ ", " + mxbean2.getLoggerLevel(logger));
|
||||
|
||||
if (!mxbean1.getParentLoggerName(logger)
|
||||
.equals(mxbean2.getParentLoggerName(logger)))
|
||||
throw new RuntimeException(
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6876135 7024172
|
||||
* @bug 6876135 7024172 7067691
|
||||
*
|
||||
* @summary Test PlatformLoggingMXBean
|
||||
* This test performs similar testing as
|
||||
@ -41,11 +41,15 @@ import java.util.List;
|
||||
|
||||
public class PlatformLoggingMXBeanTest
|
||||
{
|
||||
|
||||
ObjectName objectName = null;
|
||||
static String LOGGER_NAME_1 = "com.sun.management.Logger1";
|
||||
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 {
|
||||
}
|
||||
|
||||
@ -135,8 +139,8 @@ public class PlatformLoggingMXBeanTest
|
||||
System.out.println( "*********** Phase 3 ***********" );
|
||||
System.out.println( "*******************************" );
|
||||
System.out.println( " Create and test new Loggers" );
|
||||
Logger logger1 = Logger.getLogger( LOGGER_NAME_1 );
|
||||
Logger logger2 = Logger.getLogger( LOGGER_NAME_2 );
|
||||
logger1 = Logger.getLogger( LOGGER_NAME_1 );
|
||||
logger2 = Logger.getLogger( LOGGER_NAME_2 );
|
||||
|
||||
// check that Level object are returned properly
|
||||
try {
|
||||
@ -187,6 +191,7 @@ public class PlatformLoggingMXBeanTest
|
||||
System.out.println( " Set and Check the Logger Level" );
|
||||
log1 = false;
|
||||
log2 = false;
|
||||
|
||||
try {
|
||||
// Set the level of logger1 to ALL
|
||||
params = new Object[2];
|
||||
|
||||
58
jdk/test/java/rmi/registry/readTest/readTest.java
Normal file
58
jdk/test/java/rmi/registry/readTest/readTest.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
95
jdk/test/java/rmi/registry/readTest/readTest.sh
Normal file
95
jdk/test/java/rmi/registry/readTest/readTest.sh
Normal file
@ -0,0 +1,95 @@
|
||||
#
|
||||
# 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}
|
||||
|
||||
|
||||
48
jdk/test/java/rmi/registry/readTest/testPkg/Client.java
Normal file
48
jdk/test/java/rmi/registry/readTest/testPkg/Client.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
|
||||
public class Client {
|
||||
int port;
|
||||
|
||||
public Client(int p) {
|
||||
port = p;
|
||||
}
|
||||
|
||||
public String testStub() throws Exception {
|
||||
try {
|
||||
Registry registry = LocateRegistry.getRegistry(port);
|
||||
Hello stub = (Hello) registry.lookup("Hello");
|
||||
String response = stub.sayHello();
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Client exception: " + e.toString());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
jdk/test/java/rmi/registry/readTest/testPkg/Hello.java
Normal file
31
jdk/test/java/rmi/registry/readTest/testPkg/Hello.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
36
jdk/test/java/rmi/registry/readTest/testPkg/Server.java
Normal file
36
jdk/test/java/rmi/registry/readTest/testPkg/Server.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 {
|
||||
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 y2 = new CountDownLatch(1);
|
||||
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(y2), past, 1000);
|
||||
scheduleAtFixedRate(t, counter(y3), past, 1000);
|
||||
y3.await();
|
||||
y1.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();
|
||||
|
||||
|
||||
@ -31,21 +31,26 @@
|
||||
import java.util.*;
|
||||
|
||||
public class KillThread {
|
||||
static volatile Thread tdThread;
|
||||
public static void main (String[] args) throws Exception {
|
||||
Timer t = new Timer();
|
||||
|
||||
// Start a mean event that kills the timer thread
|
||||
t.schedule(new TimerTask() {
|
||||
public void run() {
|
||||
tdThread = Thread.currentThread();
|
||||
throw new ThreadDeath();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
// Wait for mean event to do the deed and thread to die.
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
do {
|
||||
Thread.sleep(100);
|
||||
} while(tdThread == null);
|
||||
} catch(InterruptedException e) {
|
||||
}
|
||||
tdThread.join();
|
||||
|
||||
// Try to start another event
|
||||
try {
|
||||
|
||||
@ -0,0 +1,423 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user