diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk
index e8a2223f67a..2ad599cbe23 100644
--- a/jdk/make/java/java/FILES_java.gmk
+++ b/jdk/make/java/java/FILES_java.gmk
@@ -454,6 +454,8 @@ JAVA_JAVA_java = \
sun/misc/JavaLangAccess.java \
sun/misc/JavaIOAccess.java \
sun/misc/JavaIOFileDescriptorAccess.java \
- sun/misc/JavaNioAccess.java
+ sun/misc/JavaNioAccess.java \
+ sun/misc/Perf.java \
+ sun/misc/PerfCounter.java
FILES_java = $(JAVA_JAVA_java)
diff --git a/jdk/make/sun/security/Makefile b/jdk/make/sun/security/Makefile
index 2b7cc6b2ab3..92371cc60cb 100644
--- a/jdk/make/sun/security/Makefile
+++ b/jdk/make/sun/security/Makefile
@@ -60,8 +60,15 @@ ifeq ($(PLATFORM), windows)
endif
endif
-SUBDIRS = ec other action util tools jgss krb5 smartcardio $(PKCS11) \
- $(JGSS_WRAPPER) $(MSCAPI)
+# Build in-tree elliptic curve crypto provider only when
+# DISABLE_INTREE_EC is not set
+INTREE_EC = ec
+ifdef DISABLE_INTREE_EC
+ INTREE_EC =
+endif
+
+SUBDIRS = $(INTREE_EC) other action util tools jgss krb5 smartcardio \
+ $(PKCS11) $(JGSS_WRAPPER) $(MSCAPI)
all build clean clobber::
$(SUBDIRS-loop)
diff --git a/jdk/src/share/bin/java.h b/jdk/src/share/bin/java.h
index fe039cdcc88..cebdb5fc81a 100644
--- a/jdk/src/share/bin/java.h
+++ b/jdk/src/share/bin/java.h
@@ -187,9 +187,6 @@ void InitLauncher(jboolean javaw);
*
*/
typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
- const char *name,
- jboolean init,
- jobject loader,
- jboolean throwError));
+ const char *name));
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
#endif /* _JAVA_H_ */
diff --git a/jdk/src/share/bin/parse_manifest.c b/jdk/src/share/bin/parse_manifest.c
index 6dcca091a4b..a59540213c2 100644
--- a/jdk/src/share/bin/parse_manifest.c
+++ b/jdk/src/share/bin/parse_manifest.c
@@ -59,7 +59,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
char *out;
z_stream zs;
- if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+ if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
return (NULL);
if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
return (NULL);
diff --git a/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java b/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
index 002d20785ff..1ebeb565ddb 100644
--- a/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
+++ b/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java
@@ -133,7 +133,7 @@ public class JdbcRowSetResourceBundle implements Serializable {
* This method returns an enumerated handle of the keys
* which correspond to values translated to various locales.
*
- * @returns an enumerated keys which have messages tranlated to
+ * @return an enumeration of keys which have messages tranlated to
* corresponding locales.
*/
public Enumeration getKeys() {
@@ -146,7 +146,7 @@ public class JdbcRowSetResourceBundle implements Serializable {
* returns the corresponding value reading it
* from the Resource Bundle loaded earlier.
*
- * @returns value in locale specific language
+ * @return value in locale specific language
* according to the key passed.
*/
public Object handleGetObject(String key) {
diff --git a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java
index 7908848b297..d301c605cdb 100644
--- a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java
+++ b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java
@@ -3737,7 +3737,6 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet {
* Returns a result set containing the original value of the current
* row only.
*
- * @return the original result set of the row
* @throws SQLException if there is no current row
* @see #setOriginalRow
*/
diff --git a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java
index 8db17537187..f25cec7e62e 100644
--- a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java
+++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java
@@ -46,6 +46,17 @@ import javax.sql.rowset.spi.*;
*/
public class WebRowSetXmlReader implements XmlReader, Serializable {
+
+ private JdbcRowSetResourceBundle resBundle;
+
+ public WebRowSetXmlReader(){
+ try {
+ resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+ } catch(IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
/**
* Parses the given WebRowSet object, getting its input from
* the given java.io.Reader object. The parser will send
@@ -69,17 +80,6 @@ public class WebRowSetXmlReader implements XmlReader, Serializable {
* reader for the given rowset
* @see XmlReaderContentHandler
*/
-
- private JdbcRowSetResourceBundle resBundle;
-
- public WebRowSetXmlReader(){
- try {
- resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
- } catch(IOException ioe) {
- throw new RuntimeException(ioe);
- }
- }
-
public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException {
try {
// Crimson Parser(as in J2SE 1.4.1 is NOT able to handle
diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java
index ddf57631790..46414ad8491 100644
--- a/jdk/src/share/classes/java/lang/Class.java
+++ b/jdk/src/share/classes/java/lang/Class.java
@@ -565,8 +565,9 @@ public final
* represented by this object.
*/
public String getName() {
+ String name = this.name;
if (name == null)
- name = getName0();
+ this.name = name = getName0();
return name;
}
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
index d25100958a0..9fec9b570a0 100644
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
@@ -380,16 +380,28 @@ public abstract class ClassLoader {
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
+ long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
- c = findBootstrapClass0(name);
+ c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
+ // ClassNotFoundException thrown if class not found
+ // from the non-null parent class loader
+ }
+
+ if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
+ long t1 = System.nanoTime();
c = findClass(name);
+
+ // this is the defining class loader; record the stats
+ sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+ sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+ sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
@@ -1008,22 +1020,29 @@ public abstract class ClassLoader {
if (system == null) {
if (!checkName(name))
throw new ClassNotFoundException(name);
- return findBootstrapClass(name);
+ Class cls = findBootstrapClass(name);
+ if (cls == null) {
+ throw new ClassNotFoundException(name);
+ }
+ return cls;
}
return system.loadClass(name);
}
- private Class findBootstrapClass0(String name)
- throws ClassNotFoundException
+ /**
+ * Returns a class loaded by the bootstrap class loader;
+ * or return null if not found.
+ */
+ private Class findBootstrapClassOrNull(String name)
{
check();
- if (!checkName(name))
- throw new ClassNotFoundException(name);
+ if (!checkName(name)) return null;
+
return findBootstrapClass(name);
}
- private native Class findBootstrapClass(String name)
- throws ClassNotFoundException;
+ // return null if not found
+ private native Class findBootstrapClass(String name);
// Check to make sure the class loader has been initialized.
private void check() {
diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java
index 22be20b7ecd..c4f775db71a 100644
--- a/jdk/src/share/classes/java/net/URLClassLoader.java
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java
@@ -340,6 +340,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
* used.
*/
private Class defineClass(String name, Resource res) throws IOException {
+ long t0 = System.nanoTime();
int i = name.lastIndexOf('.');
URL url = res.getCodeSourceURL();
if (i != -1) {
@@ -370,12 +371,14 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
// Use (direct) ByteBuffer:
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, bb, cs);
} else {
byte[] b = res.getBytes();
// must read certificates AFTER reading bytes.
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
+ sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
return defineClass(name, b, 0, b.length, cs);
}
}
diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html
index e6b6330ba42..384abd8d93f 100644
--- a/jdk/src/share/classes/java/net/doc-files/net-properties.html
+++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html
@@ -71,12 +71,12 @@ of proxies.
HTTP
The following proxy settings are used by the HTTP protocol handler.
-
http.proxyHost (default: <none>)
+
http.proxyHost (default: <none>)
The hostname, or address, of the proxy server
http.proxyPort (default: 80)
The port number of the proxy server.
-
http.nonProxyHosts (default: <none>)
+
http.nonProxyHosts (default: localhost|127.*|[::1])
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts,
@@ -86,7 +86,8 @@ of proxies.
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.
-
+
The default value excludes all common variations of the loopback address.
+
HTTPS This is HTTP over SSL, a secure version of HTTP
mainly used when confidentiality (like on payment sites) is needed.
The following proxy settings are used by the HTTPS protocol handler.
@@ -107,7 +108,7 @@ of proxies.
ftp.proxyPort (default: 80)
The port number of the proxy server.
-
ftp.nonProxyHosts (default: <none>)
+
ftp.nonProxyHosts (default: localhost|127.*|[::1])
Indicates the hosts that should be accessed without going
through the proxy. Typically this defines internal hosts.
The value of this property is a list of hosts, separated by
@@ -117,6 +118,7 @@ of proxies.
will indicate that every hosts in the foo.com domain and the
localhost should be accessed directly even if a proxy server is
specified.
+
The default value excludes all common variations of the loopback address.
SOCKS This is another type of proxy. It allows for lower
level type of tunneling since it works at the TCP level. In effect,
diff --git a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
index 71cb86eb88a..1452bd66b2a 100644
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java
@@ -41,8 +41,12 @@ class FileTreeWalker {
private final boolean detectCycles;
private final LinkOption[] linkOptions;
private final FileVisitor super Path> visitor;
+ private final int maxDepth;
- FileTreeWalker(Set options, FileVisitor super Path> visitor) {
+ FileTreeWalker(Set options,
+ FileVisitor super Path> visitor,
+ int maxDepth)
+ {
boolean fl = false;
boolean dc = false;
for (FileVisitOption option: options) {
@@ -58,18 +62,15 @@ class FileTreeWalker {
this.linkOptions = (fl) ? new LinkOption[0] :
new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
this.visitor = visitor;
+ this.maxDepth = maxDepth;
}
/**
* Walk file tree starting at the given file
*/
- void walk(Path start, int maxDepth) {
- // don't use attributes of starting file as they may be stale
- if (start instanceof BasicFileAttributesHolder) {
- ((BasicFileAttributesHolder)start).invalidate();
- }
+ void walk(Path start) {
FileVisitResult result = walk(start,
- maxDepth,
+ 0,
new ArrayList());
if (result == null) {
throw new NullPointerException("Visitor returned 'null'");
@@ -89,12 +90,15 @@ class FileTreeWalker {
List ancestors)
{
// depth check
- if (depth-- < 0)
+ if (depth > maxDepth)
return FileVisitResult.CONTINUE;
// if attributes are cached then use them if possible
BasicFileAttributes attrs = null;
- if (file instanceof BasicFileAttributesHolder) {
+ if ((depth > 0) &&
+ (file instanceof BasicFileAttributesHolder) &&
+ (System.getSecurityManager() == null))
+ {
BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
if (!followLinks || !cached.isSymbolicLink())
attrs = cached;
@@ -120,6 +124,10 @@ class FileTreeWalker {
}
}
} catch (SecurityException x) {
+ // If access to starting file is denied then SecurityException
+ // is thrown, otherwise the file is ignored.
+ if (depth == 0)
+ throw x;
return FileVisitResult.CONTINUE;
}
}
@@ -196,7 +204,7 @@ class FileTreeWalker {
try {
for (Path entry: stream) {
inAction = true;
- result = walk(entry, depth, ancestors);
+ result = walk(entry, depth+1, ancestors);
inAction = false;
// returning null will cause NPE to be thrown
diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java
index bf596409e5a..ca5bc5698e1 100644
--- a/jdk/src/share/classes/java/nio/file/Files.java
+++ b/jdk/src/share/classes/java/nio/file/Files.java
@@ -223,7 +223,7 @@ public final class Files {
{
if (maxDepth < 0)
throw new IllegalArgumentException("'maxDepth' is negative");
- new FileTreeWalker(options, visitor).walk(start, maxDepth);
+ new FileTreeWalker(options, visitor, maxDepth).walk(start);
}
/**
diff --git a/jdk/src/share/classes/java/util/logging/ErrorManager.java b/jdk/src/share/classes/java/util/logging/ErrorManager.java
index 39c215151fc..8a6d935dea3 100644
--- a/jdk/src/share/classes/java/util/logging/ErrorManager.java
+++ b/jdk/src/share/classes/java/util/logging/ErrorManager.java
@@ -28,7 +28,7 @@ package java.util.logging;
/**
* ErrorManager objects can be attached to Handlers to process
- * any error that occur on a Handler during Logging.
+ * any error that occurs on a Handler during Logging.
*
* When processing logging output, if a Handler encounters problems
* then rather than throwing an Exception back to the issuer of
@@ -72,7 +72,7 @@ public class ErrorManager {
/**
* The error method is called when a Handler failure occurs.
*
- * This method may be overriden in subclasses. The default
+ * This method may be overridden in subclasses. The default
* behavior in this base class is that the first call is
* reported to System.err, and subsequent calls are ignored.
*
diff --git a/jdk/src/share/classes/java/util/logging/FileHandler.java b/jdk/src/share/classes/java/util/logging/FileHandler.java
index a4f18bd2130..23031a010c8 100644
--- a/jdk/src/share/classes/java/util/logging/FileHandler.java
+++ b/jdk/src/share/classes/java/util/logging/FileHandler.java
@@ -39,7 +39,7 @@ import java.security.*;
* For a rotating set of files, as each file reaches a given size
* limit, it is closed, rotated out, and a new file opened.
* Successively older files are named by adding "0", "1", "2",
- * etc into the base filename.
+ * etc. into the base filename.
*
* By default buffering is enabled in the IO libraries but each log
* record is flushed out when it is complete.
@@ -391,7 +391,7 @@ public class FileHandler extends StreamHandler {
// Generate a lock file name from the "unique" int.
lockFileName = generate(pattern, 0, unique).toString() + ".lck";
// Now try to lock that filename.
- // Because some systems (e.g. Solaris) can only do file locks
+ // Because some systems (e.g., Solaris) can only do file locks
// between processes (and not within a process), we first check
// if we ourself already have the file locked.
synchronized(locks) {
diff --git a/jdk/src/share/classes/java/util/logging/Formatter.java b/jdk/src/share/classes/java/util/logging/Formatter.java
index 7e7030ba6b0..7cf5c1764a1 100644
--- a/jdk/src/share/classes/java/util/logging/Formatter.java
+++ b/jdk/src/share/classes/java/util/logging/Formatter.java
@@ -52,7 +52,7 @@ public abstract class Formatter {
* Format the given log record and return the formatted string.
*
* The resulting formatted String will normally include a
- * localized and formated version of the LogRecord's message field.
+ * localized and formatted version of the LogRecord's message field.
* It is recommended to use the {@link Formatter#formatMessage}
* convenience method to localize and format the message field.
*
@@ -66,7 +66,7 @@ public abstract class Formatter {
* Return the header string for a set of formatted records.
*
* This base class returns an empty string, but this may be
- * overriden by subclasses.
+ * overridden by subclasses.
*
* @param h The target handler (can be null)
* @return header string
@@ -79,7 +79,7 @@ public abstract class Formatter {
* Return the tail string for a set of formatted records.
*
* This base class returns an empty string, but this may be
- * overriden by subclasses.
+ * overridden by subclasses.
*
* @param h The target handler (can be null)
* @return tail string
diff --git a/jdk/src/share/classes/java/util/logging/Handler.java b/jdk/src/share/classes/java/util/logging/Handler.java
index 2643c734714..7c1c6268b00 100644
--- a/jdk/src/share/classes/java/util/logging/Handler.java
+++ b/jdk/src/share/classes/java/util/logging/Handler.java
@@ -274,7 +274,7 @@ public abstract class Handler {
* Level and whether it satisfies any Filter. It also
* may make other Handler specific checks that might prevent a
* handler from logging the LogRecord. It will return false if
- * the LogRecord is Null.
+ * the LogRecord is null.
*
* @param record a LogRecord
* @return true if the LogRecord would be logged.
diff --git a/jdk/src/share/classes/java/util/logging/Level.java b/jdk/src/share/classes/java/util/logging/Level.java
index 910a50d1ebb..173201f80ee 100644
--- a/jdk/src/share/classes/java/util/logging/Level.java
+++ b/jdk/src/share/classes/java/util/logging/Level.java
@@ -110,7 +110,7 @@ public class Level implements java.io.Serializable {
* Typically INFO messages will be written to the console
* or its equivalent. So the INFO level should only be
* used for reasonably significant messages that will
- * make sense to end users and system admins.
+ * make sense to end users and system administrators.
* This level is initialized to 800.
*/
public static final Level INFO = new Level("INFO", 800, defaultBundle);
@@ -245,6 +245,8 @@ public class Level implements java.io.Serializable {
}
/**
+ * Returns a string representation of this Level.
+ *
* @return the non-localized name of the Level, for example "INFO".
*/
public final String toString() {
@@ -299,14 +301,14 @@ public class Level implements java.io.Serializable {
* @throws IllegalArgumentException if the value is not valid.
* Valid values are integers between Integer.MIN_VALUE
* and Integer.MAX_VALUE, and all known level names.
- * Known names are the levels defined by this class (i.e. FINE,
+ * Known names are the levels defined by this class (e.g., FINE,
* FINER, FINEST), or created by this class with
* appropriate package access, or new levels defined or created
* by subclasses.
*
* @return The parsed value. Passing an integer that corresponds to a known name
- * (eg 700) will return the associated name (eg CONFIG).
- * Passing an integer that does not (eg 1) will return a new level name
+ * (e.g., 700) will return the associated name (e.g., CONFIG).
+ * Passing an integer that does not (e.g., 1) will return a new level name
* initialized to that value.
*/
public static synchronized Level parse(String name) throws IllegalArgumentException {
diff --git a/jdk/src/share/classes/java/util/logging/LogRecord.java b/jdk/src/share/classes/java/util/logging/LogRecord.java
index 2610316a5e3..6e659ba4ea7 100644
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java
@@ -188,7 +188,7 @@ public class LogRecord implements java.io.Serializable {
}
/**
- * Get the source Logger name's
+ * Get the source Logger's name.
*
* @return source logger name (may be null)
*/
@@ -197,7 +197,7 @@ public class LogRecord implements java.io.Serializable {
}
/**
- * Set the source Logger name.
+ * Set the source Logger's name.
*
* @param name the source logger name (may be null)
*/
diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java
index 5ae2b427133..cd9f4d90568 100644
--- a/jdk/src/share/classes/java/util/logging/Logger.java
+++ b/jdk/src/share/classes/java/util/logging/Logger.java
@@ -66,7 +66,7 @@ import java.lang.ref.WeakReference;
* effective level from its parent.
*
* On each logging call the Logger initially performs a cheap
- * check of the request level (e.g. SEVERE or FINE) against the
+ * check of the request level (e.g., SEVERE or FINE) against the
* effective log level of the logger. If the request level is
* lower than the log level, the logging call returns immediately.
*
@@ -230,7 +230,7 @@ public class Logger {
* Protected method to construct a logger for a named subsystem.
*
* The logger will be initially configured with a null Level
- * and with useParentHandlers true.
+ * and with useParentHandlers set to true.
*
* @param name A name for the logger. This should
* be a dot-separated name and should normally
@@ -240,7 +240,7 @@ public class Logger {
* @param resourceBundleName name of ResourceBundle to be used for localizing
* messages for this logger. May be null if none
* of the messages require localization.
- * @throws MissingResourceException if the ResourceBundleName is non-null and
+ * @throws MissingResourceException if the resourceBundleName is non-null and
* no corresponding resource can be found.
*/
protected Logger(String name, String resourceBundleName) {
@@ -285,7 +285,7 @@ public class Logger {
*
* If a new logger is created its log level will be configured
* based on the LogManager configuration and it will configured
- * to also send logging output to its parent's handlers. It will
+ * to also send logging output to its parent's Handlers. It will
* be registered in the LogManager global namespace.
*
* @param name A name for the logger. This should
@@ -308,7 +308,7 @@ public class Logger {
*
* If a new logger is created its log level will be configured
* based on the LogManager and it will configured to also send logging
- * output to its parent loggers Handlers. It will be registered in
+ * output to its parent's Handlers. It will be registered in
* the LogManager global namespace.
*
* If the named Logger already exists and does not yet have a
@@ -326,7 +326,8 @@ public class Logger {
* messages for this logger. May be null if none of
* the messages require localization.
* @return a suitable Logger
- * @throws MissingResourceException if the named ResourceBundle cannot be found.
+ * @throws MissingResourceException if the resourceBundleName is non-null and
+ * no corresponding resource can be found.
* @throws IllegalArgumentException if the Logger already exists and uses
* a different resource bundle name.
* @throws NullPointerException if the name is null.
@@ -395,7 +396,8 @@ public class Logger {
* messages for this logger.
* May be null if none of the messages require localization.
* @return a newly created private Logger
- * @throws MissingResourceException if the named ResourceBundle cannot be found.
+ * @throws MissingResourceException if the resourceBundleName is non-null and
+ * no corresponding resource can be found.
*/
public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
LogManager manager = LogManager.getLogManager();
@@ -514,7 +516,7 @@ public class Logger {
* level then the given message is forwarded to all the
* registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param msg The string message (or a key in the message catalog)
*/
public void log(Level level, String msg) {
@@ -532,7 +534,7 @@ public class Logger {
* level then a corresponding LogRecord is created and forwarded
* to all the registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param msg The string message (or a key in the message catalog)
* @param param1 parameter to the message
*/
@@ -553,7 +555,7 @@ public class Logger {
* level then a corresponding LogRecord is created and forwarded
* to all the registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param msg The string message (or a key in the message catalog)
* @param params array of parameters to the message
*/
@@ -578,7 +580,7 @@ public class Logger {
* processed specially by output Formatters and is not treated
* as a formatting parameter to the LogRecord message property.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param msg The string message (or a key in the message catalog)
* @param thrown Throwable associated with log message.
*/
@@ -603,7 +605,7 @@ public class Logger {
* level then the given message is forwarded to all the
* registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param msg The string message (or a key in the message catalog)
@@ -626,7 +628,7 @@ public class Logger {
* level then a corresponding LogRecord is created and forwarded
* to all the registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param msg The string message (or a key in the message catalog)
@@ -653,7 +655,7 @@ public class Logger {
* level then a corresponding LogRecord is created and forwarded
* to all the registered output Handler objects.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param msg The string message (or a key in the message catalog)
@@ -684,7 +686,7 @@ public class Logger {
* processed specially by output Formatters and is not treated
* as a formatting parameter to the LogRecord message property.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param msg The string message (or a key in the message catalog)
@@ -731,7 +733,7 @@ public class Logger {
* resource bundle name is null, or an empty String or invalid
* then the msg string is not localized.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param bundleName name of resource bundle to localize msg,
@@ -762,7 +764,7 @@ public class Logger {
* resource bundle name is null, or an empty String or invalid
* then the msg string is not localized.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param bundleName name of resource bundle to localize msg,
@@ -795,7 +797,7 @@ public class Logger {
* resource bundle name is null, or an empty String or invalid
* then the msg string is not localized.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param bundleName name of resource bundle to localize msg,
@@ -832,7 +834,7 @@ public class Logger {
* processed specially by output Formatters and is not treated
* as a formatting parameter to the LogRecord message property.
*
- * @param level One of the message level identifiers, e.g. SEVERE
+ * @param level One of the message level identifiers, e.g., SEVERE
* @param sourceClass name of class that issued the logging request
* @param sourceMethod name of method that issued the logging request
* @param bundleName name of resource bundle to localize msg,
@@ -1214,7 +1216,7 @@ public class Logger {
/**
* Specify whether or not this logger should send its output
- * to it's parent Logger. This means that any LogRecords will
+ * to its parent Logger. This means that any LogRecords will
* also be written to the parent's Handlers, and potentially
* to its parent, recursively up the namespace.
*
diff --git a/jdk/src/share/classes/java/util/logging/LoggingMXBean.java b/jdk/src/share/classes/java/util/logging/LoggingMXBean.java
index cb67d7b4fb0..a3abe3c69b1 100644
--- a/jdk/src/share/classes/java/util/logging/LoggingMXBean.java
+++ b/jdk/src/share/classes/java/util/logging/LoggingMXBean.java
@@ -105,8 +105,8 @@ public interface LoggingMXBean extends PlatformManagedObject {
*
* @param loggerName The name of the Logger to be set.
* Must be non-null.
- * @param levelName The name of the level to set the specified logger to,
- * or null if to set the level to inherit
+ * @param levelName The name of the level to set on the specified logger,
+ * or null if setting the level to inherit
* from its nearest ancestor.
*
* @throws IllegalArgumentException if the specified logger
diff --git a/jdk/src/share/classes/java/util/logging/MemoryHandler.java b/jdk/src/share/classes/java/util/logging/MemoryHandler.java
index d812e3bf64f..aa632223667 100644
--- a/jdk/src/share/classes/java/util/logging/MemoryHandler.java
+++ b/jdk/src/share/classes/java/util/logging/MemoryHandler.java
@@ -136,7 +136,7 @@ public class MemoryHandler extends Handler {
* @param size the number of log records to buffer (must be greater than zero)
* @param pushLevel message level to push on
*
- * @throws IllegalArgumentException is size is <= 0
+ * @throws IllegalArgumentException if size is <= 0
*/
public MemoryHandler(Handler target, int size, Level pushLevel) {
if (target == null || pushLevel == null) {
@@ -258,7 +258,7 @@ public class MemoryHandler extends Handler {
* This method checks if the LogRecord has an appropriate level and
* whether it satisfies any Filter. However it does not
* check whether the LogRecord would result in a "push" of the
- * buffer contents. It will return false if the LogRecord is Null.
+ * buffer contents. It will return false if the LogRecord is null.
*
* @param record a LogRecord
* @return true if the LogRecord would be logged.
diff --git a/jdk/src/share/classes/java/util/logging/StreamHandler.java b/jdk/src/share/classes/java/util/logging/StreamHandler.java
index 766142a1a58..ce47fe90427 100644
--- a/jdk/src/share/classes/java/util/logging/StreamHandler.java
+++ b/jdk/src/share/classes/java/util/logging/StreamHandler.java
@@ -220,7 +220,7 @@ public class StreamHandler extends Handler {
*
* This method checks if the LogRecord has an appropriate level and
* whether it satisfies any Filter. It will also return false if
- * no output stream has been assigned yet or the LogRecord is Null.
+ * no output stream has been assigned yet or the LogRecord is null.
*
* @param record a LogRecord
* @return true if the LogRecord would be logged.
diff --git a/jdk/src/share/classes/java/util/zip/ZipEntry.java b/jdk/src/share/classes/java/util/zip/ZipEntry.java
index cba69b0c1a2..0e2ddaec3fb 100644
--- a/jdk/src/share/classes/java/util/zip/ZipEntry.java
+++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java
@@ -253,14 +253,10 @@ class ZipEntry implements ZipConstants, Cloneable {
* the first 0xFFFF bytes are output to the ZIP file entry.
*
* @param comment the comment string
- * @exception IllegalArgumentException if the length of the specified
- * comment string is greater than 0xFFFF bytes
+ *
* @see #getComment()
*/
public void setComment(String comment) {
- if (comment != null && comment.length() > 0xffff) {
- throw new IllegalArgumentException("invalid entry comment length");
- }
this.comment = comment;
}
diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java
index 76c270c1b10..583d7dcfe1a 100644
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java
+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java
@@ -195,7 +195,10 @@ class ZipFile implements ZipConstants, Closeable {
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
+ long t0 = System.nanoTime();
jzfile = open(name, mode, file.lastModified());
+ sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
+ sun.misc.PerfCounter.getZipFileCount().increment();
this.name = name;
this.total = getTotal(jzfile);
}
diff --git a/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java b/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java
index 2d13d835c1b..f3e79555ba1 100644
--- a/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java
+++ b/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java
@@ -168,8 +168,8 @@ import javax.sql.rowset.serial.*;
* The majority of methods for setting placeholder parameters take two parameters,
* with the first parameter
* indicating which placeholder parameter is to be set, and the second parameter
- * giving the value to be set. Methods such as getInt,
- * getString, getBoolean, and getLong fall into
+ * giving the value to be set. Methods such as setInt,
+ * setString, setBoolean, and setLong fall into
* this category. After these methods have been called, a call to the method
* getParams will return an array with the values that have been set. Each
* element in the array is an Object instance representing the
@@ -3259,9 +3259,9 @@ public static final int ASCII_STREAM_PARAM = 2;
* @param x the parameter value
* @exception SQLException if a database access error occurs or
* this method is called on a closed CallableStatement
- * @see #getBoolean
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
+ * @see #getParams
* @since 1.4
*/
public void setBoolean(String parameterName, boolean x) throws SQLException{
@@ -3281,7 +3281,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getByte
+ * @see #getParams
* @since 1.4
*/
public void setByte(String parameterName, byte x) throws SQLException{
@@ -3301,7 +3301,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getShort
+ * @see #getParams
* @since 1.4
*/
public void setShort(String parameterName, short x) throws SQLException{
@@ -3320,7 +3320,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getInt
+ * @see #getParams
* @since 1.4
*/
public void setInt(String parameterName, int x) throws SQLException{
@@ -3339,7 +3339,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getLong
+ * @see #getParams
* @since 1.4
*/
public void setLong(String parameterName, long x) throws SQLException{
@@ -3358,7 +3358,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getFloat
+ * @see #getParams
* @since 1.4
*/
public void setFloat(String parameterName, float x) throws SQLException{
@@ -3377,7 +3377,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getDouble
+ * @see #getParams
* @since 1.4
*/
public void setDouble(String parameterName, double x) throws SQLException{
@@ -3398,7 +3398,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getBigDecimal
+ * @see #getParams
* @since 1.4
*/
public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
@@ -3421,7 +3421,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getString
+ * @see #getParams
* @since 1.4
*/
public void setString(String parameterName, String x) throws SQLException{
@@ -3443,7 +3443,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getBytes
+ * @see #getParams
* @since 1.4
*/
public void setBytes(String parameterName, byte x[]) throws SQLException{
@@ -3464,7 +3464,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getTimestamp
+ * @see #getParams
* @since 1.4
*/
public void setTimestamp(String parameterName, java.sql.Timestamp x)
@@ -3712,7 +3712,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* or STRUCT data type and the JDBC driver does not support
* this data type
* @see Types
- * @see #getObject
+ * @see #getParams
* @since 1.4
*/
public void setObject(String parameterName, Object x, int targetSqlType, int scale)
@@ -3740,7 +3740,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* REF, ROWID, SQLXML
* or STRUCT data type and the JDBC driver does not support
* this data type
- * @see #getObject
+ * @see #getParams
* @since 1.4
*/
public void setObject(String parameterName, Object x, int targetSqlType)
@@ -3782,7 +3782,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* Object parameter is ambiguous
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getObject
+ * @see #getParams
* @since 1.4
*/
public void setObject(String parameterName, Object x) throws SQLException{
@@ -4064,7 +4064,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getDate
+ * @see #getParams
* @since 1.4
*/
public void setDate(String parameterName, java.sql.Date x)
@@ -4091,7 +4091,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getDate
+ * @see #getParams
* @since 1.4
*/
public void setDate(String parameterName, java.sql.Date x, Calendar cal)
@@ -4111,7 +4111,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getTime
+ * @see #getParams
* @since 1.4
*/
public void setTime(String parameterName, java.sql.Time x)
@@ -4138,7 +4138,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getTime
+ * @see #getParams
* @since 1.4
*/
public void setTime(String parameterName, java.sql.Time x, Calendar cal)
@@ -4165,7 +4165,7 @@ public static final int ASCII_STREAM_PARAM = 2;
* this method is called on a closed CallableStatement
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
* this method
- * @see #getTimestamp
+ * @see #getParams
* @since 1.4
*/
public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
diff --git a/jdk/src/share/classes/sun/misc/PerfCounter.java b/jdk/src/share/classes/sun/misc/PerfCounter.java
new file mode 100644
index 00000000000..8c47234407a
--- /dev/null
+++ b/jdk/src/share/classes/sun/misc/PerfCounter.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.LongBuffer;
+import java.security.AccessController;
+
+/**
+ * Performance counter support for internal JRE classes.
+ * This class defines a fixed list of counters for the platform
+ * to use as an interim solution until RFE# 6209222 is implemented.
+ * The perf counters will be created in the jvmstat perf buffer
+ * that the HotSpot VM creates. The default size is 32K and thus
+ * the number of counters is bounded. You can alter the size
+ * with -XX:PerfDataMemorySize= option. If there is
+ * insufficient memory in the jvmstat perf buffer, the C heap memory
+ * will be used and thus the application will continue to run if
+ * the counters added exceeds the buffer size but the counters
+ * will be missing.
+ *
+ * See HotSpot jvmstat implementation for certain circumstances
+ * that the jvmstat perf buffer is not supported.
+ *
+ */
+public class PerfCounter {
+ private static final Perf perf =
+ AccessController.doPrivileged(new Perf.GetPerfAction());
+
+ // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp
+ private final static int V_Constant = 1;
+ private final static int V_Monotonic = 2;
+ private final static int V_Variable = 3;
+ private final static int U_None = 1;
+
+ private final String name;
+ private final LongBuffer lb;
+
+ private PerfCounter(String name, int type) {
+ this.name = name;
+ ByteBuffer bb = perf.createLong(name, U_None, type, 0L);
+ bb.order(ByteOrder.nativeOrder());
+ this.lb = bb.asLongBuffer();
+ }
+
+ static PerfCounter newPerfCounter(String name) {
+ return new PerfCounter(name, V_Variable);
+ }
+
+ static PerfCounter newConstantPerfCounter(String name) {
+ PerfCounter c = new PerfCounter(name, V_Constant);
+ return c;
+ }
+
+ /**
+ * Returns the current value of the perf counter.
+ */
+ public synchronized long get() {
+ return lb.get(0);
+ }
+
+ /**
+ * Sets the value of the perf counter to the given newValue.
+ */
+ public synchronized void set(long newValue) {
+ lb.put(0, newValue);
+ }
+
+ /**
+ * Adds the given value to the perf counter.
+ */
+ public synchronized void add(long value) {
+ long res = get() + value;
+ lb.put(0, res);
+ }
+
+ /**
+ * Increments the perf counter with 1.
+ */
+ public void increment() {
+ add(1);
+ }
+
+ /**
+ * Adds the given interval to the perf counter.
+ */
+ public void addTime(long interval) {
+ add(interval);
+ }
+
+ /**
+ * Adds the elapsed time from the given start time (ns) to the perf counter.
+ */
+ public void addElapsedTimeFrom(long startTime) {
+ add(System.nanoTime() - startTime);
+ }
+
+ @Override
+ public String toString() {
+ return name + " = " + get();
+ }
+
+ static class CoreCounters {
+ static final PerfCounter pdt = newPerfCounter("sun.classloader.parentDelegationTime");
+ static final PerfCounter lc = newPerfCounter("sun.classloader.findClasses");
+ static final PerfCounter lct = newPerfCounter("sun.classloader.findClassTime");
+ static final PerfCounter rcbt = newPerfCounter("sun.urlClassLoader.readClassBytesTime");
+ static final PerfCounter zfc = newPerfCounter("sun.zip.zipFiles");
+ static final PerfCounter zfot = newPerfCounter("sun.zip.zipFile.openTime");
+ }
+
+ static class WindowsClientCounters {
+ static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
+ }
+
+ /**
+ * Number of findClass calls
+ */
+ public static PerfCounter getFindClasses() {
+ return CoreCounters.lc;
+ }
+
+ /**
+ * Time (ns) spent in finding classes that includes
+ * lookup and read class bytes and defineClass
+ */
+ public static PerfCounter getFindClassTime() {
+ return CoreCounters.lct;
+ }
+
+ /**
+ * Time (ns) spent in finding classes
+ */
+ public static PerfCounter getReadClassBytesTime() {
+ return CoreCounters.rcbt;
+ }
+
+ /**
+ * Time (ns) spent in the parent delegation to
+ * the parent of the defining class loader
+ */
+ public static PerfCounter getParentDelegationTime() {
+ return CoreCounters.pdt;
+ }
+
+ /**
+ * Number of zip files opened.
+ */
+ public static PerfCounter getZipFileCount() {
+ return CoreCounters.zfc;
+ }
+
+ /**
+ * Time (ns) spent in opening the zip files that
+ * includes building the entries hash table
+ */
+ public static PerfCounter getZipFileOpenTime() {
+ return CoreCounters.zfot;
+ }
+
+ /**
+ * D3D graphic pipeline available
+ */
+ public static PerfCounter getD3DAvailable() {
+ return WindowsClientCounters.d3dAvailable;
+ }
+}
diff --git a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java
index 714dc4ce5c3..af34ada8ccf 100644
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,9 @@
package sun.net.spi;
-import sun.net.www.http.*;
import sun.net.NetProperties;
import java.net.*;
import java.util.*;
-import java.util.regex.*;
import java.io.*;
import sun.misc.RegexpPool;
import java.security.AccessController;
@@ -102,17 +100,22 @@ public class DefaultProxySelector extends ProxySelector {
*/
static class NonProxyInfo {
+ // Default value for nonProxyHosts, this provides backward compatibility
+ // by excluding localhost and its litteral notations.
+ static final String defStringVal = "localhost|127.*|[::1]";
+
String hostsSource;
RegexpPool hostsPool;
- String property;
+ final String property;
+ final String defaultVal;
+ static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
+ static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
- static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
- static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
-
- NonProxyInfo(String p, String s, RegexpPool pool) {
+ NonProxyInfo(String p, String s, RegexpPool pool, String d) {
property = p;
hostsSource = s;
hostsPool = pool;
+ defaultVal = d;
}
}
@@ -130,7 +133,6 @@ public class DefaultProxySelector extends ProxySelector {
}
String protocol = uri.getScheme();
String host = uri.getHost();
- int port = uri.getPort();
if (host == null) {
// This is a hack to ensure backward compatibility in two
@@ -149,11 +151,6 @@ public class DefaultProxySelector extends ProxySelector {
}
i = auth.lastIndexOf(':');
if (i >= 0) {
- try {
- port = Integer.parseInt(auth.substring(i+1));
- } catch (NumberFormatException e) {
- port = -1;
- }
auth = auth.substring(0,i);
}
host = auth;
@@ -165,13 +162,6 @@ public class DefaultProxySelector extends ProxySelector {
}
List proxyl = new ArrayList(1);
- // special case localhost and loopback addresses to
- // not go through proxy
- if (isLoopback(host)) {
- proxyl.add(Proxy.NO_PROXY);
- return proxyl;
- }
-
NonProxyInfo pinfo = null;
if ("http".equalsIgnoreCase(protocol)) {
@@ -244,9 +234,14 @@ public class DefaultProxySelector extends ProxySelector {
nphosts = NetProperties.get(nprop.property);
synchronized (nprop) {
if (nphosts == null) {
- nprop.hostsSource = null;
- nprop.hostsPool = null;
- } else {
+ if (nprop.defaultVal != null) {
+ nphosts = nprop.defaultVal;
+ } else {
+ nprop.hostsSource = null;
+ nprop.hostsPool = null;
+ }
+ }
+ if (nphosts != null) {
if (!nphosts.equals(nprop.hostsSource)) {
RegexpPool pool = new RegexpPool();
StringTokenizer st = new StringTokenizer(nphosts, "|", false);
@@ -334,107 +329,6 @@ public class DefaultProxySelector extends ProxySelector {
}
}
- private boolean isLoopback(String host) {
- if (host == null || host.length() == 0)
- return false;
-
- if (host.equalsIgnoreCase("localhost"))
- return true;
-
- /* The string could represent a numerical IP address.
- * For IPv4 addresses, check whether it starts with 127.
- * For IPv6 addresses, check whether it is ::1 or its equivalent.
- * Don't check IPv4-mapped or IPv4-compatible addresses
- */
-
- if (host.startsWith("127.")) {
- // possible IPv4 loopback address
- int p = 4;
- int q;
- int n = host.length();
- // Per RFC2732: At most three digits per byte
- // Further constraint: Each element fits in a byte
- if ((q = scanByte(host, p, n)) <= p) return false; p = q;
- if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q;
- if ((q = scanByte(host, p, n)) <= p) return false; p = q;
- if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q;
- if ((q = scanByte(host, p, n)) <= p) return false;
- return q == n && number > 0;
- }
-
- if (host.endsWith(":1")) {
- final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
- return p6.matcher(host).matches();
- }
- return false;
- }
-
- // Character-class masks, in reverse order from RFC2396 because
- // initializers for static fields cannot make forward references.
-
- // Compute a low-order mask for the characters
- // between first and last, inclusive
- private static long lowMask(char first, char last) {
- long m = 0;
- int f = Math.max(Math.min(first, 63), 0);
- int l = Math.max(Math.min(last, 63), 0);
- for (int i = f; i <= l; i++)
- m |= 1L << i;
- return m;
- }
- // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
- // "8" | "9"
- private static final long L_DIGIT = lowMask('0', '9');
- private static final long H_DIGIT = 0L;
-
- // Scan a string of decimal digits whose value fits in a byte
- //
- private int number;
- private int scanByte(String input, int start, int n)
- {
- int p = start;
- int q = scan(input, p, n, L_DIGIT, H_DIGIT);
- if (q <= p) return q;
- number = Integer.parseInt(input.substring(p, q));
- if (number > 255) return p;
- return q;
- }
-
- // Scan a specific char: If the char at the given start position is
- // equal to c, return the index of the next char; otherwise, return the
- // start position.
- //
- private int scan(String input, int start, int end, char c) {
- if ((start < end) && (input.charAt(start) == c))
- return start + 1;
- return start;
- }
-
- // Scan chars that match the given mask pair
- //
- private int scan(String input, int start, int n, long lowMask, long highMask)
- {
- int p = start;
- while (p < n) {
- char c = input.charAt(p);
- if (match(c, lowMask, highMask)) {
- p++;
- continue;
- }
- break;
- }
- return p;
- }
-
- // Tell whether the given character is permitted by the given mask pair
- private boolean match(char c, long lowMask, long highMask) {
- if (c < 64)
- return ((1L << c) & lowMask) != 0;
- if (c < 128)
- return ((1L << (c - 64)) & highMask) != 0;
- return false;
- }
-
private native static boolean init();
private native Proxy getSystemProxy(String protocol, String host);
}
diff --git a/jdk/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java b/jdk/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java
new file mode 100644
index 00000000000..3310c93e4fe
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.action;
+
+import java.security.Security;
+
+/**
+ * A convenience class for retrieving the boolean value of a security property
+ * as a privileged action.
+ *
+ *
An instance of this class can be used as the argument of
+ * AccessController.doPrivileged.
+ *
+ *
The following code retrieves the boolean value of the security
+ * property named "prop" as a privileged action:
+ *
+ *
+ * boolean b = java.security.AccessController.doPrivileged
+ * (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
+ *
+ *
+ */
+public class GetBooleanSecurityPropertyAction
+ implements java.security.PrivilegedAction {
+ private String theProp;
+
+ /**
+ * Constructor that takes the name of the security property whose boolean
+ * value needs to be determined.
+ *
+ * @param theProp the name of the security property
+ */
+ public GetBooleanSecurityPropertyAction(String theProp) {
+ this.theProp = theProp;
+ }
+
+ /**
+ * Determines the boolean value of the security property whose name was
+ * specified in the constructor.
+ *
+ * @return the Boolean value of the security property.
+ */
+ public Boolean run() {
+ boolean b = false;
+ try {
+ String value = Security.getProperty(theProp);
+ b = (value != null) && value.equalsIgnoreCase("true");
+ } catch (NullPointerException e) {}
+ return b;
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java
index 8e13fb8b777..5892b1b328d 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,14 @@
package sun.security.provider.certpath;
import java.io.IOException;
+import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.cert.*;
import java.util.*;
import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanAction;
import sun.security.util.Debug;
import sun.security.x509.GeneralNames;
import sun.security.x509.GeneralNameInterface;
@@ -64,9 +66,8 @@ public abstract class Builder {
* Authority Information Access extension shall be enabled. Currently
* disabled by default for compatibility reasons.
*/
- final static boolean USE_AIA =
- DistributionPointFetcher.getBooleanProperty
- ("com.sun.security.enableAIAcaIssuers", false);
+ final static boolean USE_AIA = AccessController.doPrivileged
+ (new GetBooleanAction("com.sun.security.enableAIAcaIssuers"));
/**
* Initialize the builder with the input parameters.
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertId.java b/jdk/src/share/classes/sun/security/provider/certpath/CertId.java
index 1ee63949964..20e9aa2a789 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertId.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertId.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,11 @@
package sun.security.provider.certpath;
-import java.io.*;
+import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
@@ -54,21 +56,28 @@ import sun.security.util.*;
public class CertId {
private static final boolean debug = false;
- private AlgorithmId hashAlgId;
- private byte[] issuerNameHash;
- private byte[] issuerKeyHash;
- private SerialNumber certSerialNumber;
+ private static final AlgorithmId SHA1_ALGID
+ = new AlgorithmId(AlgorithmId.SHA_oid);
+ private final AlgorithmId hashAlgId;
+ private final byte[] issuerNameHash;
+ private final byte[] issuerKeyHash;
+ private final SerialNumber certSerialNumber;
private int myhash = -1; // hashcode for this CertId
/**
* Creates a CertId. The hash algorithm used is SHA-1.
*/
- public CertId(X509CertImpl issuerCert, SerialNumber serialNumber)
- throws Exception {
+ public CertId(X509Certificate issuerCert, SerialNumber serialNumber)
+ throws IOException {
// compute issuerNameHash
- MessageDigest md = MessageDigest.getInstance("SHA1");
- hashAlgId = AlgorithmId.get("SHA1");
+ MessageDigest md = null;
+ try {
+ md = MessageDigest.getInstance("SHA1");
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new IOException("Unable to create CertId", nsae);
+ }
+ hashAlgId = SHA1_ALGID;
md.update(issuerCert.getSubjectX500Principal().getEncoded());
issuerNameHash = md.digest();
@@ -90,6 +99,7 @@ public class CertId {
encoder.encode(issuerNameHash));
System.out.println("issuerKeyHash is " +
encoder.encode(issuerKeyHash));
+ System.out.println("SerialNumber is " + serialNumber.getNumber());
}
}
@@ -97,7 +107,6 @@ public class CertId {
* Creates a CertId from its ASN.1 DER encoding.
*/
public CertId(DerInputStream derIn) throws IOException {
-
hashAlgId = AlgorithmId.parse(derIn.getDerValue());
issuerNameHash = derIn.getOctetString();
issuerKeyHash = derIn.getOctetString();
@@ -157,7 +166,7 @@ public class CertId {
*
* @return the hashcode value.
*/
- public int hashCode() {
+ @Override public int hashCode() {
if (myhash == -1) {
myhash = hashAlgId.hashCode();
for (int i = 0; i < issuerNameHash.length; i++) {
@@ -180,8 +189,7 @@ public class CertId {
* @param other the object to test for equality with this object.
* @return true if the objects are considered equal, false otherwise.
*/
- public boolean equals(Object other) {
-
+ @Override public boolean equals(Object other) {
if (this == other) {
return true;
}
@@ -203,7 +211,7 @@ public class CertId {
/**
* Create a string representation of the CertId.
*/
- public String toString() {
+ @Override public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("CertId \n");
sb.append("Algorithm: " + hashAlgId.toString() +"\n");
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java
index b462dd5ba08..18845113edb 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java
@@ -80,6 +80,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
{ false, false, false, false, false, false, true };
private static final boolean[] ALL_REASONS =
{true, true, true, true, true, true, true, true, true};
+ private boolean mOnlyEECert = false;
// Maximum clock skew in milliseconds (15 minutes) allowed when checking
// validity of CRLs
@@ -114,6 +115,12 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
Collection certs) throws CertPathValidatorException
{
+ this(anchor, params, certs, false);
+ }
+
+ CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
+ Collection certs, boolean onlyEECert)
+ throws CertPathValidatorException {
mAnchor = anchor;
mParams = params;
mStores = new ArrayList(params.getCertStores());
@@ -133,6 +140,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
}
Date testDate = params.getDate();
mCurrentTime = (testDate != null ? testDate : new Date());
+ mOnlyEECert = onlyEECert;
init(false);
}
@@ -264,6 +272,13 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
" ---checking " + msg + "...");
}
+ if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
+ if (debug != null) {
+ debug.println("Skipping revocation check, not end entity cert");
+ }
+ return;
+ }
+
// reject circular dependencies - RFC 3280 is not explicit on how
// to handle this, so we feel it is safest to reject them until
// the issue is resolved in the PKIX WG.
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
index 39ee1f1dad6..dea521a4a19 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
@@ -32,7 +32,7 @@ import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
-import sun.security.action.GetPropertyAction;
+import sun.security.action.GetBooleanAction;
import sun.security.util.Debug;
import sun.security.util.DerOutputStream;
import sun.security.x509.*;
@@ -62,28 +62,8 @@ class DistributionPointFetcher {
* extension shall be enabled. Currently disabled by default for
* compatibility and legal reasons.
*/
- private final static boolean USE_CRLDP =
- getBooleanProperty("com.sun.security.enableCRLDP", false);
-
- /**
- * Return the value of the boolean System property propName.
- */
- public static boolean getBooleanProperty(String propName,
- boolean defaultValue) {
- // if set, require value of either true or false
- String b = AccessController.doPrivileged(
- new GetPropertyAction(propName));
- if (b == null) {
- return defaultValue;
- } else if (b.equalsIgnoreCase("false")) {
- return false;
- } else if (b.equalsIgnoreCase("true")) {
- return true;
- } else {
- throw new RuntimeException("Value of " + propName
- + " must either be 'true' or 'false'");
- }
- }
+ private final static boolean USE_CRLDP = AccessController.doPrivileged
+ (new GetBooleanAction("com.sun.security.enableCRLDP"));
// singleton instance
private static final DistributionPointFetcher INSTANCE =
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
index 393a7663c91..41fe50d66b7 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
@@ -82,6 +82,7 @@ class ForwardBuilder extends Builder {
TrustAnchor trustAnchor;
private Comparator comparator;
private boolean searchAllCertStores = true;
+ private boolean onlyEECert = false;
/**
* Initialize the builder with the input parameters.
@@ -89,7 +90,8 @@ class ForwardBuilder extends Builder {
* @param params the parameter set used to build a certification path
*/
ForwardBuilder(PKIXBuilderParameters buildParams,
- X500Principal targetSubjectDN, boolean searchAllCertStores)
+ X500Principal targetSubjectDN, boolean searchAllCertStores,
+ boolean onlyEECert)
{
super(buildParams, targetSubjectDN);
@@ -108,6 +110,7 @@ class ForwardBuilder extends Builder {
}
comparator = new PKIXCertComparator(trustedSubjectDNs);
this.searchAllCertStores = searchAllCertStores;
+ this.onlyEECert = onlyEECert;
}
/**
@@ -875,8 +878,8 @@ class ForwardBuilder extends Builder {
/* Check revocation if it is enabled */
if (buildParams.isRevocationEnabled()) {
try {
- CrlRevocationChecker crlChecker =
- new CrlRevocationChecker(anchor, buildParams);
+ CrlRevocationChecker crlChecker = new CrlRevocationChecker
+ (anchor, buildParams, null, onlyEECert);
crlChecker.check(cert, anchor.getCAPublicKey(), true);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
new file mode 100644
index 00000000000..2665de6d680
--- /dev/null
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package sun.security.provider.certpath;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.HttpURLConnection;
+import java.security.cert.CertificateException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CRLReason;
+import java.security.cert.Extension;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static sun.security.provider.certpath.OCSPResponse.*;
+import sun.security.util.Debug;
+import sun.security.x509.AccessDescription;
+import sun.security.x509.AuthorityInfoAccessExtension;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNameInterface;
+import sun.security.x509.URIName;
+import sun.security.x509.X509CertImpl;
+
+/**
+ * This is a class that checks the revocation status of a certificate(s) using
+ * OCSP. It is not a PKIXCertPathChecker and therefore can be used outside of
+ * the CertPathValidator framework. It is useful when you want to
+ * just check the revocation status of a certificate, and you don't want to
+ * incur the overhead of validating all of the certificates in the
+ * associated certificate chain.
+ *
+ * @author Sean Mullan
+ */
+public final class OCSP {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+
+ private OCSP() {}
+
+ /**
+ * Obtains the revocation status of a certificate using OCSP using the most
+ * common defaults. The OCSP responder URI is retrieved from the
+ * certificate's AIA extension. The OCSP responder certificate is assumed
+ * to be the issuer's certificate (or issued by the issuer CA).
+ *
+ * @param cert the certificate to be checked
+ * @param issuerCert the issuer certificate
+ * @return the RevocationStatus
+ * @throws IOException if there is an exception connecting to or
+ * communicating with the OCSP responder
+ * @throws CertPathValidatorException if an exception occurs while
+ * encoding the OCSP Request or validating the OCSP Response
+ */
+ public static RevocationStatus check(X509Certificate cert,
+ X509Certificate issuerCert)
+ throws IOException, CertPathValidatorException {
+ CertId certId = null;
+ URI responderURI = null;
+ try {
+ X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+ responderURI = getResponderURI(certImpl);
+ if (responderURI == null) {
+ throw new CertPathValidatorException
+ ("No OCSP Responder URI in certificate");
+ }
+ certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException
+ ("Exception while encoding OCSPRequest", ce);
+ } catch (IOException ioe) {
+ throw new CertPathValidatorException
+ ("Exception while encoding OCSPRequest", ioe);
+ }
+ OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+ responderURI, issuerCert, null);
+ return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+ }
+
+ /**
+ * Obtains the revocation status of a certificate using OCSP.
+ *
+ * @param cert the certificate to be checked
+ * @param issuerCert the issuer certificate
+ * @param responderURI the URI of the OCSP responder
+ * @param responderCert the OCSP responder's certificate
+ * @param date the time the validity of the OCSP responder's certificate
+ * should be checked against. If null, the current time is used.
+ * @return the RevocationStatus
+ * @throws IOException if there is an exception connecting to or
+ * communicating with the OCSP responder
+ * @throws CertPathValidatorException if an exception occurs while
+ * encoding the OCSP Request or validating the OCSP Response
+ */
+ public static RevocationStatus check(X509Certificate cert,
+ X509Certificate issuerCert, URI responderURI, X509Certificate
+ responderCert, Date date)
+ throws IOException, CertPathValidatorException {
+ CertId certId = null;
+ try {
+ X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+ certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException
+ ("Exception while encoding OCSPRequest", ce);
+ } catch (IOException ioe) {
+ throw new CertPathValidatorException
+ ("Exception while encoding OCSPRequest", ioe);
+ }
+ OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+ responderURI, responderCert, date);
+ return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+ }
+
+ /**
+ * Checks the revocation status of a list of certificates using OCSP.
+ *
+ * @param certs the CertIds to be checked
+ * @param responderURI the URI of the OCSP responder
+ * @param responderCert the OCSP responder's certificate
+ * @param date the time the validity of the OCSP responder's certificate
+ * should be checked against. If null, the current time is used.
+ * @return the OCSPResponse
+ * @throws IOException if there is an exception connecting to or
+ * communicating with the OCSP responder
+ * @throws CertPathValidatorException if an exception occurs while
+ * encoding the OCSP Request or validating the OCSP Response
+ */
+ static OCSPResponse check(List certIds, URI responderURI,
+ X509Certificate responderCert, Date date)
+ throws IOException, CertPathValidatorException {
+
+ byte[] bytes = null;
+ try {
+ OCSPRequest request = new OCSPRequest(certIds);
+ bytes = request.encodeBytes();
+ } catch (IOException ioe) {
+ throw new CertPathValidatorException
+ ("Exception while encoding OCSPRequest", ioe);
+ }
+
+ InputStream in = null;
+ OutputStream out = null;
+ byte[] response = null;
+ try {
+ URL url = responderURI.toURL();
+ if (debug != null) {
+ debug.println("connecting to OCSP service at: " + url);
+ }
+ HttpURLConnection con = (HttpURLConnection)url.openConnection();
+ con.setDoOutput(true);
+ con.setDoInput(true);
+ con.setRequestMethod("POST");
+ con.setRequestProperty
+ ("Content-type", "application/ocsp-request");
+ con.setRequestProperty
+ ("Content-length", String.valueOf(bytes.length));
+ out = con.getOutputStream();
+ out.write(bytes);
+ out.flush();
+ // Check the response
+ if (debug != null &&
+ con.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ debug.println("Received HTTP error: " + con.getResponseCode()
+ + " - " + con.getResponseMessage());
+ }
+ in = con.getInputStream();
+ int contentLength = con.getContentLength();
+ if (contentLength == -1) {
+ contentLength = Integer.MAX_VALUE;
+ }
+ response = new byte[contentLength > 2048 ? 2048 : contentLength];
+ int total = 0;
+ while (total < contentLength) {
+ int count = in.read(response, total, response.length - total);
+ if (count < 0)
+ break;
+
+ total += count;
+ if (total >= response.length && total < contentLength) {
+ response = Arrays.copyOf(response, total * 2);
+ }
+ }
+ response = Arrays.copyOf(response, total);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ throw ioe;
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioe) {
+ throw ioe;
+ }
+ }
+ }
+
+ OCSPResponse ocspResponse = null;
+ try {
+ ocspResponse = new OCSPResponse(response, date, responderCert);
+ } catch (IOException ioe) {
+ // response decoding exception
+ throw new CertPathValidatorException(ioe);
+ }
+ if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) {
+ throw new CertPathValidatorException
+ ("OCSP response error: " + ocspResponse.getResponseStatus());
+ }
+
+ // Check that the response includes a response for all of the
+ // certs that were supplied in the request
+ for (CertId certId : certIds) {
+ SingleResponse sr = ocspResponse.getSingleResponse(certId);
+ if (sr == null) {
+ if (debug != null) {
+ debug.println("No response found for CertId: " + certId);
+ }
+ throw new CertPathValidatorException(
+ "OCSP response does not include a response for a " +
+ "certificate supplied in the OCSP request");
+ }
+ if (debug != null) {
+ debug.println("Status of certificate (with serial number " +
+ certId.getSerialNumber() + ") is: " + sr.getCertStatus());
+ }
+ }
+ return ocspResponse;
+ }
+
+ /**
+ * Returns the URI of the OCSP Responder as specified in the
+ * certificate's Authority Information Access extension, or null if
+ * not specified.
+ *
+ * @param cert the certificate
+ * @return the URI of the OCSP Responder, or null if not specified
+ */
+ public static URI getResponderURI(X509Certificate cert) {
+ try {
+ return getResponderURI(X509CertImpl.toImpl(cert));
+ } catch (CertificateException ce) {
+ // treat this case as if the cert had no extension
+ return null;
+ }
+ }
+
+ static URI getResponderURI(X509CertImpl certImpl) {
+
+ // Examine the certificate's AuthorityInfoAccess extension
+ AuthorityInfoAccessExtension aia =
+ certImpl.getAuthorityInfoAccessExtension();
+ if (aia == null) {
+ return null;
+ }
+
+ List descriptions = aia.getAccessDescriptions();
+ for (AccessDescription description : descriptions) {
+ if (description.getAccessMethod().equals(
+ AccessDescription.Ad_OCSP_Id)) {
+
+ GeneralName generalName = description.getAccessLocation();
+ if (generalName.getType() == GeneralNameInterface.NAME_URI) {
+ URIName uri = (URIName) generalName.getName();
+ return uri.getURI();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The Revocation Status of a certificate.
+ */
+ public static interface RevocationStatus {
+ public enum CertStatus { GOOD, REVOKED, UNKNOWN };
+
+ /**
+ * Returns the revocation status.
+ */
+ CertStatus getCertStatus();
+ /**
+ * Returns the time when the certificate was revoked, or null
+ * if it has not been revoked.
+ */
+ Date getRevocationTime();
+ /**
+ * Returns the reason the certificate was revoked, or null if it
+ * has not been revoked.
+ */
+ CRLReason getRevocationReason();
+
+ /**
+ * Returns a Map of additional extensions.
+ */
+ Map getSingleExtensions();
+ }
+}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java
index 04e0649d8ff..6f72c7ec185 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java
@@ -25,19 +25,20 @@
package sun.security.provider.certpath;
-import java.io.*;
+import java.io.IOException;
import java.math.BigInteger;
import java.util.*;
import java.security.AccessController;
-import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.Security;
import java.security.cert.*;
import java.security.cert.CertPathValidatorException.BasicReason;
-import java.net.*;
+import java.net.URI;
+import java.net.URISyntaxException;
import javax.security.auth.x500.X500Principal;
-import sun.security.util.*;
+import static sun.security.provider.certpath.OCSP.*;
+import sun.security.util.Debug;
import sun.security.x509.*;
/**
@@ -50,27 +51,18 @@ import sun.security.x509.*;
*/
class OCSPChecker extends PKIXCertPathChecker {
- public static final String OCSP_ENABLE_PROP = "ocsp.enable";
- public static final String OCSP_URL_PROP = "ocsp.responderURL";
- public static final String OCSP_CERT_SUBJECT_PROP =
+ static final String OCSP_ENABLE_PROP = "ocsp.enable";
+ static final String OCSP_URL_PROP = "ocsp.responderURL";
+ static final String OCSP_CERT_SUBJECT_PROP =
"ocsp.responderCertSubjectName";
- public static final String OCSP_CERT_ISSUER_PROP =
- "ocsp.responderCertIssuerName";
- public static final String OCSP_CERT_NUMBER_PROP =
+ static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
+ static final String OCSP_CERT_NUMBER_PROP =
"ocsp.responderCertSerialNumber";
private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
private static final Debug DEBUG = Debug.getInstance("certpath");
private static final boolean dump = false;
- // Supported extensions
- private static final int OCSP_NONCE_DATA[] =
- { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2 };
- private static final ObjectIdentifier OCSP_NONCE_OID;
- static {
- OCSP_NONCE_OID = ObjectIdentifier.newInternal(OCSP_NONCE_DATA);
- }
-
private int remainingCerts;
private X509Certificate[] certs;
@@ -79,19 +71,26 @@ class OCSPChecker extends PKIXCertPathChecker {
private PKIXParameters pkixParams;
+ private boolean onlyEECert = false;
+
/**
* Default Constructor
*
* @param certPath the X509 certification path
* @param pkixParams the input PKIX parameter set
- * @exception CertPathValidatorException Exception thrown if cert path
- * does not validate.
+ * @throws CertPathValidatorException if OCSPChecker can not be created
*/
OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
throws CertPathValidatorException {
+ this(certPath, pkixParams, false);
+ }
+
+ OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
+ throws CertPathValidatorException {
this.cp = certPath;
this.pkixParams = pkixParams;
+ this.onlyEECert = onlyEECert;
List extends Certificate> tmp = cp.getCertificates();
certs = tmp.toArray(new X509Certificate[tmp.size()]);
init(false);
@@ -101,6 +100,7 @@ class OCSPChecker extends PKIXCertPathChecker {
* Initializes the internal state of the checker from parameters
* specified in the constructor
*/
+ @Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
remainingCerts = certs.length + 1;
@@ -110,11 +110,11 @@ class OCSPChecker extends PKIXCertPathChecker {
}
}
- public boolean isForwardCheckingSupported() {
+ @Override public boolean isForwardCheckingSupported() {
return false;
}
- public Set getSupportedExtensions() {
+ @Override public Set getSupportedExtensions() {
return Collections.emptySet();
}
@@ -127,300 +127,233 @@ class OCSPChecker extends PKIXCertPathChecker {
* @exception CertPathValidatorException Exception is thrown if the
* certificate has been revoked.
*/
+ @Override
public void check(Certificate cert, Collection unresolvedCritExts)
throws CertPathValidatorException {
- InputStream in = null;
- OutputStream out = null;
-
// Decrement the certificate counter
remainingCerts--;
+ X509CertImpl currCertImpl = null;
try {
- X509Certificate responderCert = null;
- boolean seekResponderCert = false;
- X500Principal responderSubjectName = null;
- X500Principal responderIssuerName = null;
- BigInteger responderSerialNumber = null;
+ currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
+ } catch (CertificateException ce) {
+ throw new CertPathValidatorException(ce);
+ }
- boolean seekIssuerCert = true;
- X509CertImpl issuerCertImpl = null;
- X509CertImpl currCertImpl =
- X509CertImpl.toImpl((X509Certificate)cert);
+ if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
+ if (DEBUG != null) {
+ DEBUG.println("Skipping revocation check, not end entity cert");
+ }
+ return;
+ }
- /*
- * OCSP security property values, in the following order:
- * 1. ocsp.responderURL
- * 2. ocsp.responderCertSubjectName
- * 3. ocsp.responderCertIssuerName
- * 4. ocsp.responderCertSerialNumber
- */
- String[] properties = getOCSPProperties();
+ /*
+ * OCSP security property values, in the following order:
+ * 1. ocsp.responderURL
+ * 2. ocsp.responderCertSubjectName
+ * 3. ocsp.responderCertIssuerName
+ * 4. ocsp.responderCertSerialNumber
+ */
+ // should cache these properties to avoid calling every time?
+ String[] properties = getOCSPProperties();
- // Check whether OCSP is feasible before seeking cert information
- URL url = getOCSPServerURL(currCertImpl, properties);
+ // Check whether OCSP is feasible before seeking cert information
+ URI uri = getOCSPServerURI(currCertImpl, properties[0]);
- // When responder's subject name is set then the issuer/serial
- // properties are ignored
- if (properties[1] != null) {
- responderSubjectName = new X500Principal(properties[1]);
+ // When responder's subject name is set then the issuer/serial
+ // properties are ignored
+ X500Principal responderSubjectName = null;
+ X500Principal responderIssuerName = null;
+ BigInteger responderSerialNumber = null;
+ if (properties[1] != null) {
+ responderSubjectName = new X500Principal(properties[1]);
+ } else if (properties[2] != null && properties[3] != null) {
+ responderIssuerName = new X500Principal(properties[2]);
+ // remove colon or space separators
+ String value = stripOutSeparators(properties[3]);
+ responderSerialNumber = new BigInteger(value, 16);
+ } else if (properties[2] != null || properties[3] != null) {
+ throw new CertPathValidatorException(
+ "Must specify both ocsp.responderCertIssuerName and " +
+ "ocsp.responderCertSerialNumber properties");
+ }
- } else if (properties[2] != null && properties[3] != null) {
- responderIssuerName = new X500Principal(properties[2]);
- // remove colon or space separators
- String value = stripOutSeparators(properties[3]);
- responderSerialNumber = new BigInteger(value, 16);
+ // If the OCSP responder cert properties are set then the
+ // identified cert must be located in the trust anchors or
+ // in the cert stores.
+ boolean seekResponderCert = false;
+ if (responderSubjectName != null || responderIssuerName != null) {
+ seekResponderCert = true;
+ }
- } else if (properties[2] != null || properties[3] != null) {
+ // Set the issuer certificate to the next cert in the chain
+ // (unless we're processing the final cert).
+ X509Certificate issuerCert = null;
+ boolean seekIssuerCert = true;
+ X509Certificate responderCert = null;
+ if (remainingCerts < certs.length) {
+ issuerCert = certs[remainingCerts];
+ seekIssuerCert = false; // done
+
+ // By default, the OCSP responder's cert is the same as the
+ // issuer of the cert being validated.
+ if (!seekResponderCert) {
+ responderCert = issuerCert;
+ if (DEBUG != null) {
+ DEBUG.println("Responder's certificate is the same " +
+ "as the issuer of the certificate being validated");
+ }
+ }
+ }
+
+ // Check anchor certs for:
+ // - the issuer cert (of the cert being validated)
+ // - the OCSP responder's cert
+ if (seekIssuerCert || seekResponderCert) {
+
+ if (DEBUG != null && seekResponderCert) {
+ DEBUG.println("Searching trust anchors for responder's " +
+ "certificate");
+ }
+
+ // Extract the anchor certs
+ Iterator anchors
+ = pkixParams.getTrustAnchors().iterator();
+ if (!anchors.hasNext()) {
throw new CertPathValidatorException(
- "Must specify both ocsp.responderCertIssuerName and " +
- "ocsp.responderCertSerialNumber properties");
+ "Must specify at least one trust anchor");
}
- // If the OCSP responder cert properties are set then the
- // identified cert must be located in the trust anchors or
- // in the cert stores.
- if (responderSubjectName != null || responderIssuerName != null) {
- seekResponderCert = true;
- }
+ X500Principal certIssuerName =
+ currCertImpl.getIssuerX500Principal();
+ while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
- // Set the issuer certificate to the next cert in the chain
- // (unless we're processing the final cert).
- if (remainingCerts < certs.length) {
- issuerCertImpl = X509CertImpl.toImpl(certs[remainingCerts]);
- seekIssuerCert = false; // done
+ TrustAnchor anchor = anchors.next();
+ X509Certificate anchorCert = anchor.getTrustedCert();
+ X500Principal anchorSubjectName =
+ anchorCert.getSubjectX500Principal();
- // By default, the OCSP responder's cert is the same as the
- // issuer of the cert being validated.
- if (! seekResponderCert) {
- responderCert = certs[remainingCerts];
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is the same " +
- "as the issuer of the certificate being validated");
+ if (dump) {
+ System.out.println("Issuer DN is " + certIssuerName);
+ System.out.println("Subject DN is " + anchorSubjectName);
+ }
+
+ // Check if anchor cert is the issuer cert
+ if (seekIssuerCert &&
+ certIssuerName.equals(anchorSubjectName)) {
+
+ issuerCert = anchorCert;
+ seekIssuerCert = false; // done
+
+ // By default, the OCSP responder's cert is the same as
+ // the issuer of the cert being validated.
+ if (!seekResponderCert && responderCert == null) {
+ responderCert = anchorCert;
+ if (DEBUG != null) {
+ DEBUG.println("Responder's certificate is the" +
+ " same as the issuer of the certificate " +
+ "being validated");
+ }
+ }
+ }
+
+ // Check if anchor cert is the responder cert
+ if (seekResponderCert) {
+ // Satisfy the responder subject name property only, or
+ // satisfy the responder issuer name and serial number
+ // properties only
+ if ((responderSubjectName != null &&
+ responderSubjectName.equals(anchorSubjectName)) ||
+ (responderIssuerName != null &&
+ responderSerialNumber != null &&
+ responderIssuerName.equals(
+ anchorCert.getIssuerX500Principal()) &&
+ responderSerialNumber.equals(
+ anchorCert.getSerialNumber()))) {
+
+ responderCert = anchorCert;
+ seekResponderCert = false; // done
}
}
}
+ if (issuerCert == null) {
+ throw new CertPathValidatorException(
+ "No trusted certificate for " + currCertImpl.getIssuerDN());
+ }
- // Check anchor certs for:
- // - the issuer cert (of the cert being validated)
- // - the OCSP responder's cert
- if (seekIssuerCert || seekResponderCert) {
-
- if (DEBUG != null && seekResponderCert) {
- DEBUG.println("Searching trust anchors for responder's " +
+ // Check cert stores if responder cert has not yet been found
+ if (seekResponderCert) {
+ if (DEBUG != null) {
+ DEBUG.println("Searching cert stores for responder's " +
"certificate");
}
-
- // Extract the anchor certs
- Iterator anchors = pkixParams.getTrustAnchors().iterator();
- if (! anchors.hasNext()) {
- throw new CertPathValidatorException(
- "Must specify at least one trust anchor");
+ X509CertSelector filter = null;
+ if (responderSubjectName != null) {
+ filter = new X509CertSelector();
+ filter.setSubject(responderSubjectName);
+ } else if (responderIssuerName != null &&
+ responderSerialNumber != null) {
+ filter = new X509CertSelector();
+ filter.setIssuer(responderIssuerName);
+ filter.setSerialNumber(responderSerialNumber);
}
-
- X500Principal certIssuerName =
- currCertImpl.getIssuerX500Principal();
- while (anchors.hasNext() &&
- (seekIssuerCert || seekResponderCert)) {
-
- TrustAnchor anchor = (TrustAnchor)anchors.next();
- X509Certificate anchorCert = anchor.getTrustedCert();
- X500Principal anchorSubjectName =
- anchorCert.getSubjectX500Principal();
-
- if (dump) {
- System.out.println("Issuer DN is " + certIssuerName);
- System.out.println("Subject DN is " +
- anchorSubjectName);
- }
-
- // Check if anchor cert is the issuer cert
- if (seekIssuerCert &&
- certIssuerName.equals(anchorSubjectName)) {
-
- issuerCertImpl = X509CertImpl.toImpl(anchorCert);
- seekIssuerCert = false; // done
-
- // By default, the OCSP responder's cert is the same as
- // the issuer of the cert being validated.
- if (! seekResponderCert && responderCert == null) {
- responderCert = anchorCert;
+ if (filter != null) {
+ List certStores = pkixParams.getCertStores();
+ for (CertStore certStore : certStores) {
+ Iterator i = null;
+ try {
+ i = certStore.getCertificates(filter).iterator();
+ } catch (CertStoreException cse) {
+ // ignore and try next certStore
if (DEBUG != null) {
- DEBUG.println("Responder's certificate is the" +
- " same as the issuer of the certificate " +
- "being validated");
+ DEBUG.println("CertStore exception:" + cse);
}
+ continue;
}
- }
-
- // Check if anchor cert is the responder cert
- if (seekResponderCert) {
- // Satisfy the responder subject name property only, or
- // satisfy the responder issuer name and serial number
- // properties only
- if ((responderSubjectName != null &&
- responderSubjectName.equals(anchorSubjectName)) ||
- (responderIssuerName != null &&
- responderSerialNumber != null &&
- responderIssuerName.equals(
- anchorCert.getIssuerX500Principal()) &&
- responderSerialNumber.equals(
- anchorCert.getSerialNumber()))) {
-
- responderCert = anchorCert;
+ if (i.hasNext()) {
+ responderCert = (X509Certificate) i.next();
seekResponderCert = false; // done
- }
- }
- }
- if (issuerCertImpl == null) {
- throw new CertPathValidatorException(
- "No trusted certificate for " +
- currCertImpl.getIssuerDN());
- }
-
- // Check cert stores if responder cert has not yet been found
- if (seekResponderCert) {
- if (DEBUG != null) {
- DEBUG.println("Searching cert stores for responder's " +
- "certificate");
- }
- X509CertSelector filter = null;
- if (responderSubjectName != null) {
- filter = new X509CertSelector();
- filter.setSubject(responderSubjectName.getName());
- } else if (responderIssuerName != null &&
- responderSerialNumber != null) {
- filter = new X509CertSelector();
- filter.setIssuer(responderIssuerName.getName());
- filter.setSerialNumber(responderSerialNumber);
- }
- if (filter != null) {
- List certStores = pkixParams.getCertStores();
- for (CertStore certStore : certStores) {
- Iterator i =
- certStore.getCertificates(filter).iterator();
- if (i.hasNext()) {
- responderCert = (X509Certificate) i.next();
- seekResponderCert = false; // done
- break;
- }
+ break;
}
}
}
}
+ }
- // Could not find the certificate identified in the OCSP properties
- if (seekResponderCert) {
- throw new CertPathValidatorException(
- "Cannot find the responder's certificate " +
- "(set using the OCSP security properties).");
- }
+ // Could not find the certificate identified in the OCSP properties
+ if (seekResponderCert) {
+ throw new CertPathValidatorException(
+ "Cannot find the responder's certificate " +
+ "(set using the OCSP security properties).");
+ }
- // Construct an OCSP Request
- OCSPRequest ocspRequest =
- new OCSPRequest(currCertImpl, issuerCertImpl);
+ CertId certId = null;
+ OCSPResponse response = null;
+ try {
+ certId = new CertId
+ (issuerCert, currCertImpl.getSerialNumberObject());
+ response = OCSP.check(Collections.singletonList(certId), uri,
+ responderCert, pkixParams.getDate());
+ } catch (IOException ioe) {
+ // should allow this to pass if network failures are acceptable
+ throw new CertPathValidatorException
+ ("Unable to send OCSP request", ioe);
+ }
- // Use the URL to the OCSP service that was created earlier
- HttpURLConnection con = (HttpURLConnection)url.openConnection();
- if (DEBUG != null) {
- DEBUG.println("connecting to OCSP service at: " + url);
- }
-
- // Indicate that both input and output will be performed,
- // that the method is POST, and that the content length is
- // the length of the byte array
-
- con.setDoOutput(true);
- con.setDoInput(true);
- con.setRequestMethod("POST");
- con.setRequestProperty("Content-type", "application/ocsp-request");
- byte[] bytes = ocspRequest.encodeBytes();
- CertId certId = ocspRequest.getCertId();
-
- con.setRequestProperty("Content-length",
- String.valueOf(bytes.length));
- out = con.getOutputStream();
- out.write(bytes);
- out.flush();
-
- // Check the response
- if (DEBUG != null &&
- con.getResponseCode() != HttpURLConnection.HTTP_OK) {
- DEBUG.println("Received HTTP error: " + con.getResponseCode() +
- " - " + con.getResponseMessage());
- }
- in = con.getInputStream();
-
- byte[] response = null;
- int total = 0;
- int contentLength = con.getContentLength();
- if (contentLength != -1) {
- response = new byte[contentLength];
- } else {
- response = new byte[2048];
- contentLength = Integer.MAX_VALUE;
- }
-
- while (total < contentLength) {
- int count = in.read(response, total, response.length - total);
- if (count < 0)
- break;
-
- total += count;
- if (total >= response.length && total < contentLength) {
- response = Arrays.copyOf(response, total * 2);
- }
- }
- response = Arrays.copyOf(response, total);
-
- OCSPResponse ocspResponse = new OCSPResponse(response, pkixParams,
- responderCert);
- // Check that response applies to the cert that was supplied
- if (! certId.equals(ocspResponse.getCertId())) {
- throw new CertPathValidatorException(
- "Certificate in the OCSP response does not match the " +
- "certificate supplied in the OCSP request.");
- }
- SerialNumber serialNumber = currCertImpl.getSerialNumberObject();
- int certOCSPStatus = ocspResponse.getCertStatus(serialNumber);
-
- if (DEBUG != null) {
- DEBUG.println("Status of certificate (with serial number " +
- serialNumber.getNumber() + ") is: " +
- OCSPResponse.certStatusToText(certOCSPStatus));
- }
-
- if (certOCSPStatus == OCSPResponse.CERT_STATUS_REVOKED) {
- Throwable t = new CertificateRevokedException(
- ocspResponse.getRevocationTime(),
- ocspResponse.getRevocationReason(),
- responderCert.getSubjectX500Principal(),
- ocspResponse.getSingleExtensions());
- throw new CertPathValidatorException(t.getMessage(), t,
- null, -1, BasicReason.REVOKED);
-
- } else if (certOCSPStatus == OCSPResponse.CERT_STATUS_UNKNOWN) {
- throw new CertPathValidatorException(
- "Certificate's revocation status is unknown", null, cp,
- remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
- }
- } catch (Exception e) {
- throw new CertPathValidatorException(e);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException ioe) {
- throw new CertPathValidatorException(ioe);
- }
- }
- if (out != null) {
- try {
- out.close();
- } catch (IOException ioe) {
- throw new CertPathValidatorException(ioe);
- }
- }
+ RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
+ RevocationStatus.CertStatus certStatus = rs.getCertStatus();
+ if (certStatus == RevocationStatus.CertStatus.REVOKED) {
+ Throwable t = new CertificateRevokedException(
+ rs.getRevocationTime(), rs.getRevocationReason(),
+ responderCert.getSubjectX500Principal(),
+ rs.getSingleExtensions());
+ throw new CertPathValidatorException(t.getMessage(), t,
+ null, -1, BasicReason.REVOKED);
+ } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
+ throw new CertPathValidatorException(
+ "Certificate's revocation status is unknown", null, cp,
+ remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
@@ -431,20 +364,18 @@ class OCSPChecker extends PKIXCertPathChecker {
* 3. ocsp.responderCertIssuerName
* 4. ocsp.responderCertSerialNumber
*/
- private static URL getOCSPServerURL(X509CertImpl currCertImpl,
- String[] properties)
- throws CertificateParsingException, CertPathValidatorException {
+ private static URI getOCSPServerURI(X509CertImpl currCertImpl,
+ String responderURL) throws CertPathValidatorException {
- if (properties[0] != null) {
- try {
- return new URL(properties[0]);
- } catch (java.net.MalformedURLException e) {
+ if (responderURL != null) {
+ try {
+ return new URI(responderURL);
+ } catch (URISyntaxException e) {
throw new CertPathValidatorException(e);
- }
+ }
}
// Examine the certificate's AuthorityInfoAccess extension
-
AuthorityInfoAccessExtension aia =
currCertImpl.getAuthorityInfoAccessExtension();
if (aia == null) {
@@ -459,13 +390,8 @@ class OCSPChecker extends PKIXCertPathChecker {
GeneralName generalName = description.getAccessLocation();
if (generalName.getType() == GeneralNameInterface.NAME_URI) {
- try {
- URIName uri = (URIName) generalName.getName();
- return (new URL(uri.getName()));
-
- } catch (java.net.MalformedURLException e) {
- throw new CertPathValidatorException(e);
- }
+ URIName uri = (URIName) generalName.getName();
+ return uri.getURI();
}
}
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java
index b7350b55e9b..393ac6f0e73 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,9 @@
package sun.security.provider.certpath;
import java.io.IOException;
-import java.security.cert.CertPathValidatorException;
+import java.util.Collections;
+import java.util.List;
import sun.misc.HexDumpEncoder;
-import sun.security.x509.*;
import sun.security.util.*;
/**
@@ -77,47 +77,33 @@ class OCSPRequest {
private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false;
- // Serial number of the certificates to be checked for revocation
- private SerialNumber serialNumber;
-
- // Issuer's certificate (for computing certId hash values)
- private X509CertImpl issuerCert;
-
- // CertId of the certificate to be checked
- private CertId certId = null;
+ // List of request CertIds
+ private final List certIds;
/*
* Constructs an OCSPRequest. This constructor is used
* to construct an unsigned OCSP Request for a single user cert.
*/
- // used by OCSPChecker
- OCSPRequest(X509CertImpl userCert, X509CertImpl issuerCert)
- throws CertPathValidatorException {
-
- if (issuerCert == null) {
- throw new CertPathValidatorException("Null IssuerCertificate");
- }
- this.issuerCert = issuerCert;
- serialNumber = userCert.getSerialNumberObject();
+ OCSPRequest(CertId certId) {
+ this.certIds = Collections.singletonList(certId);
+ }
+
+ OCSPRequest(List certIds) {
+ this.certIds = certIds;
}
- // used by OCSPChecker
byte[] encodeBytes() throws IOException {
// encode tbsRequest
DerOutputStream tmp = new DerOutputStream();
- DerOutputStream derSingleReqList = new DerOutputStream();
- SingleRequest singleRequest = null;
-
- try {
- singleRequest = new SingleRequest(issuerCert, serialNumber);
- } catch (Exception e) {
- throw new IOException("Error encoding OCSP request");
+ DerOutputStream requestsOut = new DerOutputStream();
+ for (CertId certId : certIds) {
+ DerOutputStream certIdOut = new DerOutputStream();
+ certId.encode(certIdOut);
+ requestsOut.write(DerValue.tag_Sequence, certIdOut);
}
- certId = singleRequest.getCertId();
- singleRequest.encode(derSingleReqList);
- tmp.write(DerValue.tag_Sequence, derSingleReqList);
+ tmp.write(DerValue.tag_Sequence, requestsOut);
// No extensions supported
DerOutputStream tbsRequest = new DerOutputStream();
tbsRequest.write(DerValue.tag_Sequence, tmp);
@@ -130,35 +116,14 @@ class OCSPRequest {
if (dump) {
HexDumpEncoder hexEnc = new HexDumpEncoder();
- System.out.println ("OCSPRequest bytes are... ");
+ System.out.println("OCSPRequest bytes are... ");
System.out.println(hexEnc.encode(bytes));
}
- return(bytes);
+ return bytes;
}
- // used by OCSPChecker
- CertId getCertId() {
- return certId;
- }
-
- private static class SingleRequest {
- private CertId certId;
-
- // No extensions are set
-
- private SingleRequest(X509CertImpl cert, SerialNumber serialNo) throws Exception {
- certId = new CertId(cert, serialNo);
- }
-
- private void encode(DerOutputStream out) throws IOException {
- DerOutputStream tmp = new DerOutputStream();
- certId.encode(tmp);
- out.write(DerValue.tag_Sequence, tmp);
- }
-
- private CertId getCertId() {
- return certId;
- }
+ List getCertIds() {
+ return certIds;
}
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
index cdadc45f66c..e7b148fbc7c 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
@@ -28,17 +28,16 @@ package sun.security.provider.certpath;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason;
import java.security.cert.X509Certificate;
-import java.security.cert.PKIXParameters;
-import javax.security.auth.x500.X500Principal;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
@@ -113,32 +112,29 @@ import sun.security.util.*;
* @author Ram Marti
*/
-class OCSPResponse {
+public final class OCSPResponse {
- // Certificate status CHOICE
- public static final int CERT_STATUS_GOOD = 0;
- public static final int CERT_STATUS_REVOKED = 1;
- public static final int CERT_STATUS_UNKNOWN = 2;
+ public enum ResponseStatus {
+ SUCCESSFUL, // Response has valid confirmations
+ MALFORMED_REQUEST, // Illegal confirmation request
+ INTERNAL_ERROR, // Internal error in issuer
+ TRY_LATER, // Try again later
+ UNUSED, // is not used
+ SIG_REQUIRED, // Must sign the request
+ UNAUTHORIZED // Request unauthorized
+ };
+ private static ResponseStatus[] rsvalues = ResponseStatus.values();
private static final Debug DEBUG = Debug.getInstance("certpath");
private static final boolean dump = false;
- private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID;
- private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID;
- static {
- ObjectIdentifier tmp1 = null;
- ObjectIdentifier tmp2 = null;
- try {
- tmp1 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.1");
- tmp2 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.2");
- } catch (Exception e) {
- // should not happen; log and exit
- }
- OCSP_BASIC_RESPONSE_OID = tmp1;
- OCSP_NONCE_EXTENSION_OID = tmp2;
- }
+ private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
+ ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
+ private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
+ ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
- // OCSP response status code
- private static final int OCSP_RESPONSE_OK = 0;
+ private static final int CERT_STATUS_GOOD = 0;
+ private static final int CERT_STATUS_REVOKED = 1;
+ private static final int CERT_STATUS_UNKNOWN = 2;
// ResponderID CHOICE tags
private static final int NAME_TAG = 1;
@@ -147,7 +143,8 @@ class OCSPResponse {
// Object identifier for the OCSPSigning key purpose
private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
- private SingleResponse singleResponse;
+ private final ResponseStatus responseStatus;
+ private final Map singleResponseMap;
// Maximum clock skew in milliseconds (15 minutes) allowed when checking
// validity of OCSP responses
@@ -159,289 +156,289 @@ class OCSPResponse {
/*
* Create an OCSP response from its ASN.1 DER encoding.
*/
- // used by OCSPChecker
- OCSPResponse(byte[] bytes, PKIXParameters params,
+ OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
X509Certificate responderCert)
throws IOException, CertPathValidatorException {
- try {
- int responseStatus;
- ObjectIdentifier responseType;
- int version;
- CertificateIssuerName responderName = null;
- Date producedAtDate;
- AlgorithmId sigAlgId;
- byte[] ocspNonce;
+ // OCSPResponse
+ if (dump) {
+ HexDumpEncoder hexEnc = new HexDumpEncoder();
+ System.out.println("OCSPResponse bytes are...");
+ System.out.println(hexEnc.encode(bytes));
+ }
+ DerValue der = new DerValue(bytes);
+ if (der.tag != DerValue.tag_Sequence) {
+ throw new IOException("Bad encoding in OCSP response: " +
+ "expected ASN.1 SEQUENCE tag.");
+ }
+ DerInputStream derIn = der.getData();
- // OCSPResponse
- if (dump) {
- HexDumpEncoder hexEnc = new HexDumpEncoder();
- System.out.println("OCSPResponse bytes are...");
- System.out.println(hexEnc.encode(bytes));
- }
- DerValue der = new DerValue(bytes);
- if (der.tag != DerValue.tag_Sequence) {
- throw new IOException("Bad encoding in OCSP response: " +
- "expected ASN.1 SEQUENCE tag.");
- }
- DerInputStream derIn = der.getData();
+ // responseStatus
+ int status = derIn.getEnumerated();
+ if (status >= 0 && status < rsvalues.length) {
+ responseStatus = rsvalues[status];
+ } else {
+ // unspecified responseStatus
+ throw new IOException("Unknown OCSPResponse status: " + status);
+ }
+ if (DEBUG != null) {
+ DEBUG.println("OCSP response status: " + responseStatus);
+ }
+ if (responseStatus != ResponseStatus.SUCCESSFUL) {
+ // no need to continue, responseBytes are not set.
+ singleResponseMap = Collections.emptyMap();
+ return;
+ }
- // responseStatus
- responseStatus = derIn.getEnumerated();
+ // responseBytes
+ der = derIn.getDerValue();
+ if (!der.isContextSpecific((byte)0)) {
+ throw new IOException("Bad encoding in responseBytes element " +
+ "of OCSP response: expected ASN.1 context specific tag 0.");
+ }
+ DerValue tmp = der.data.getDerValue();
+ if (tmp.tag != DerValue.tag_Sequence) {
+ throw new IOException("Bad encoding in responseBytes element " +
+ "of OCSP response: expected ASN.1 SEQUENCE tag.");
+ }
+
+ // responseType
+ derIn = tmp.data;
+ ObjectIdentifier responseType = derIn.getOID();
+ if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
if (DEBUG != null) {
- DEBUG.println("OCSP response: " +
- responseToText(responseStatus));
+ DEBUG.println("OCSP response type: basic");
}
- if (responseStatus != OCSP_RESPONSE_OK) {
- throw new CertPathValidatorException(
- "OCSP Response Failure: " +
- responseToText(responseStatus));
+ } else {
+ if (DEBUG != null) {
+ DEBUG.println("OCSP response type: " + responseType);
}
+ throw new IOException("Unsupported OCSP response type: " +
+ responseType);
+ }
- // responseBytes
- der = derIn.getDerValue();
- if (! der.isContextSpecific((byte)0)) {
- throw new IOException("Bad encoding in responseBytes element " +
- "of OCSP response: expected ASN.1 context specific tag 0.");
- };
- DerValue tmp = der.data.getDerValue();
- if (tmp.tag != DerValue.tag_Sequence) {
- throw new IOException("Bad encoding in responseBytes element " +
- "of OCSP response: expected ASN.1 SEQUENCE tag.");
- }
+ // BasicOCSPResponse
+ DerInputStream basicOCSPResponse =
+ new DerInputStream(derIn.getOctetString());
- // responseType
- derIn = tmp.data;
- responseType = derIn.getOID();
- if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
- if (DEBUG != null) {
- DEBUG.println("OCSP response type: basic");
+ DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
+ if (seqTmp.length < 3) {
+ throw new IOException("Unexpected BasicOCSPResponse value");
+ }
+
+ DerValue responseData = seqTmp[0];
+
+ // Need the DER encoded ResponseData to verify the signature later
+ byte[] responseDataDer = seqTmp[0].toByteArray();
+
+ // tbsResponseData
+ if (responseData.tag != DerValue.tag_Sequence) {
+ throw new IOException("Bad encoding in tbsResponseData " +
+ "element of OCSP response: expected ASN.1 SEQUENCE tag.");
+ }
+ DerInputStream seqDerIn = responseData.data;
+ DerValue seq = seqDerIn.getDerValue();
+
+ // version
+ if (seq.isContextSpecific((byte)0)) {
+ // seq[0] is version
+ if (seq.isConstructed() && seq.isContextSpecific()) {
+ //System.out.println ("version is available");
+ seq = seq.data.getDerValue();
+ int version = seq.getInteger();
+ if (seq.data.available() != 0) {
+ throw new IOException("Bad encoding in version " +
+ " element of OCSP response: bad format");
}
- } else {
- if (DEBUG != null) {
- DEBUG.println("OCSP response type: " + responseType);
- }
- throw new IOException("Unsupported OCSP response type: " +
- responseType);
- }
-
- // BasicOCSPResponse
- DerInputStream basicOCSPResponse =
- new DerInputStream(derIn.getOctetString());
-
- DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
- DerValue responseData = seqTmp[0];
-
- // Need the DER encoded ResponseData to verify the signature later
- byte[] responseDataDer = seqTmp[0].toByteArray();
-
- // tbsResponseData
- if (responseData.tag != DerValue.tag_Sequence) {
- throw new IOException("Bad encoding in tbsResponseData " +
- " element of OCSP response: expected ASN.1 SEQUENCE tag.");
- }
- DerInputStream seqDerIn = responseData.data;
- DerValue seq = seqDerIn.getDerValue();
-
- // version
- if (seq.isContextSpecific((byte)0)) {
- // seq[0] is version
- if (seq.isConstructed() && seq.isContextSpecific()) {
- //System.out.println ("version is available");
- seq = seq.data.getDerValue();
- version = seq.getInteger();
- if (seq.data.available() != 0) {
- throw new IOException("Bad encoding in version " +
- " element of OCSP response: bad format");
- }
- seq = seqDerIn.getDerValue();
- }
- }
-
- // responderID
- short tag = (byte)(seq.tag & 0x1f);
- if (tag == NAME_TAG) {
- responderName = new CertificateIssuerName(seq.getData());
- if (DEBUG != null) {
- DEBUG.println("OCSP Responder name: " + responderName);
- }
- } else if (tag == KEY_TAG) {
- // Ignore, for now
- } else {
- throw new IOException("Bad encoding in responderID element " +
- "of OCSP response: expected ASN.1 context specific tag 0 " +
- "or 1");
- }
-
- // producedAt
- seq = seqDerIn.getDerValue();
- producedAtDate = seq.getGeneralizedTime();
-
- // responses
- DerValue[] singleResponseDer = seqDerIn.getSequence(1);
- // Examine only the first response
- singleResponse = new SingleResponse(singleResponseDer[0]);
-
- // responseExtensions
- if (seqDerIn.available() > 0) {
seq = seqDerIn.getDerValue();
- if (seq.isContextSpecific((byte)1)) {
- DerValue[] responseExtDer = seq.data.getSequence(3);
- Extension[] responseExtension =
- new Extension[responseExtDer.length];
- for (int i = 0; i < responseExtDer.length; i++) {
- responseExtension[i] = new Extension(responseExtDer[i]);
- if (DEBUG != null) {
- DEBUG.println("OCSP extension: " +
- responseExtension[i]);
- }
- if ((responseExtension[i].getExtensionId()).equals(
- OCSP_NONCE_EXTENSION_OID)) {
- ocspNonce =
- responseExtension[i].getExtensionValue();
+ }
+ }
- } else if (responseExtension[i].isCritical()) {
- throw new IOException(
- "Unsupported OCSP critical extension: " +
- responseExtension[i].getExtensionId());
- }
+ // responderID
+ short tag = (byte)(seq.tag & 0x1f);
+ if (tag == NAME_TAG) {
+ if (DEBUG != null) {
+ X500Name responderName = new X500Name(seq.getData());
+ DEBUG.println("OCSP Responder name: " + responderName);
+ }
+ } else if (tag == KEY_TAG) {
+ // Ignore, for now
+ } else {
+ throw new IOException("Bad encoding in responderID element of " +
+ "OCSP response: expected ASN.1 context specific tag 0 or 1");
+ }
+
+ // producedAt
+ seq = seqDerIn.getDerValue();
+ if (DEBUG != null) {
+ Date producedAtDate = seq.getGeneralizedTime();
+ DEBUG.println("OCSP response produced at: " + producedAtDate);
+ }
+
+ // responses
+ DerValue[] singleResponseDer = seqDerIn.getSequence(1);
+ singleResponseMap
+ = new HashMap(singleResponseDer.length);
+ if (DEBUG != null) {
+ DEBUG.println("OCSP number of SingleResponses: "
+ + singleResponseDer.length);
+ }
+ for (int i = 0; i < singleResponseDer.length; i++) {
+ SingleResponse singleResponse
+ = new SingleResponse(singleResponseDer[i]);
+ singleResponseMap.put(singleResponse.getCertId(), singleResponse);
+ }
+
+ // responseExtensions
+ if (seqDerIn.available() > 0) {
+ seq = seqDerIn.getDerValue();
+ if (seq.isContextSpecific((byte)1)) {
+ DerValue[] responseExtDer = seq.data.getSequence(3);
+ for (int i = 0; i < responseExtDer.length; i++) {
+ Extension responseExtension
+ = new Extension(responseExtDer[i]);
+ if (DEBUG != null) {
+ DEBUG.println("OCSP extension: " + responseExtension);
+ }
+ if (responseExtension.getExtensionId().equals(
+ OCSP_NONCE_EXTENSION_OID)) {
+ /*
+ ocspNonce =
+ responseExtension[i].getExtensionValue();
+ */
+ } else if (responseExtension.isCritical()) {
+ throw new IOException(
+ "Unsupported OCSP critical extension: " +
+ responseExtension.getExtensionId());
}
}
}
+ }
- // signatureAlgorithmId
- sigAlgId = AlgorithmId.parse(seqTmp[1]);
+ // signatureAlgorithmId
+ AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
- // signature
- byte[] signature = seqTmp[2].getBitString();
- X509CertImpl[] x509Certs = null;
+ // signature
+ byte[] signature = seqTmp[2].getBitString();
+ X509CertImpl[] x509Certs = null;
- // if seq[3] is available , then it is a sequence of certificates
- if (seqTmp.length > 3) {
- // certs are available
- DerValue seqCert = seqTmp[3];
- if (! seqCert.isContextSpecific((byte)0)) {
- throw new IOException("Bad encoding in certs element " +
- "of OCSP response: expected ASN.1 context specific tag 0.");
- }
- DerValue[] certs = (seqCert.getData()).getSequence(3);
- x509Certs = new X509CertImpl[certs.length];
+ // if seq[3] is available , then it is a sequence of certificates
+ if (seqTmp.length > 3) {
+ // certs are available
+ DerValue seqCert = seqTmp[3];
+ if (!seqCert.isContextSpecific((byte)0)) {
+ throw new IOException("Bad encoding in certs element of " +
+ "OCSP response: expected ASN.1 context specific tag 0.");
+ }
+ DerValue[] certs = seqCert.getData().getSequence(3);
+ x509Certs = new X509CertImpl[certs.length];
+ try {
for (int i = 0; i < certs.length; i++) {
x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
}
+ } catch (CertificateException ce) {
+ throw new IOException("Bad encoding in X509 Certificate", ce);
}
+ }
- // Check whether the cert returned by the responder is trusted
- if (x509Certs != null && x509Certs[0] != null) {
- X509CertImpl cert = x509Certs[0];
+ // Check whether the cert returned by the responder is trusted
+ if (x509Certs != null && x509Certs[0] != null) {
+ X509CertImpl cert = x509Certs[0];
- // First check if the cert matches the responder cert which
- // was set locally.
- if (cert.equals(responderCert)) {
- // cert is trusted, now verify the signed response
+ // First check if the cert matches the responder cert which
+ // was set locally.
+ if (cert.equals(responderCert)) {
+ // cert is trusted, now verify the signed response
- // Next check if the cert was issued by the responder cert
- // which was set locally.
- } else if (cert.getIssuerX500Principal().equals(
- responderCert.getSubjectX500Principal())) {
+ // Next check if the cert was issued by the responder cert
+ // which was set locally.
+ } else if (cert.getIssuerX500Principal().equals(
+ responderCert.getSubjectX500Principal())) {
- // Check for the OCSPSigning key purpose
+ // Check for the OCSPSigning key purpose
+ try {
List keyPurposes = cert.getExtendedKeyUsage();
if (keyPurposes == null ||
!keyPurposes.contains(KP_OCSP_SIGNING_OID)) {
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is not " +
- "valid for signing OCSP responses.");
- }
throw new CertPathValidatorException(
"Responder's certificate not valid for signing " +
"OCSP responses");
}
+ } catch (CertificateParsingException cpe) {
+ // assume cert is not valid for signing
+ throw new CertPathValidatorException(
+ "Responder's certificate not valid for signing " +
+ "OCSP responses", cpe);
+ }
- // check the validity
- try {
- Date dateCheckedAgainst = params.getDate();
- if (dateCheckedAgainst == null) {
- cert.checkValidity();
- } else {
- cert.checkValidity(dateCheckedAgainst);
- }
- } catch (GeneralSecurityException e) {
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is not " +
- "within the validity period.");
- }
- throw new CertPathValidatorException(
- "Responder's certificate not within the " +
- "validity period");
- }
-
- // check for revocation
- //
- // A CA may specify that an OCSP client can trust a
- // responder for the lifetime of the responder's
- // certificate. The CA does so by including the
- // extension id-pkix-ocsp-nocheck.
- //
- Extension noCheck =
- cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
- if (noCheck != null) {
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate includes " +
- "the extension id-pkix-ocsp-nocheck.");
- }
+ // check the validity
+ try {
+ if (dateCheckedAgainst == null) {
+ cert.checkValidity();
} else {
- // we should do the revocating checking of the
- // authorized responder in a future update.
+ cert.checkValidity(dateCheckedAgainst);
}
+ } catch (GeneralSecurityException e) {
+ throw new CertPathValidatorException(
+ "Responder's certificate not within the " +
+ "validity period", e);
+ }
- // verify the signature
- try {
- cert.verify(responderCert.getPublicKey());
- responderCert = cert;
- // cert is trusted, now verify the signed response
-
- } catch (GeneralSecurityException e) {
- responderCert = null;
+ // check for revocation
+ //
+ // A CA may specify that an OCSP client can trust a
+ // responder for the lifetime of the responder's
+ // certificate. The CA does so by including the
+ // extension id-pkix-ocsp-nocheck.
+ //
+ Extension noCheck =
+ cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
+ if (noCheck != null) {
+ if (DEBUG != null) {
+ DEBUG.println("Responder's certificate includes " +
+ "the extension id-pkix-ocsp-nocheck.");
}
} else {
- if (DEBUG != null) {
- DEBUG.println("Responder's certificate is not " +
- "authorized to sign OCSP responses.");
- }
- throw new CertPathValidatorException(
- "Responder's certificate not authorized to sign " +
- "OCSP responses");
+ // we should do the revocation checking of the
+ // authorized responder in a future update.
}
- }
- // Confirm that the signed response was generated using the public
- // key from the trusted responder cert
- if (responderCert != null) {
+ // verify the signature
+ try {
+ cert.verify(responderCert.getPublicKey());
+ responderCert = cert;
+ // cert is trusted, now verify the signed response
- if (! verifyResponse(responseDataDer, responderCert,
- sigAlgId, signature, params)) {
- if (DEBUG != null) {
- DEBUG.println("Error verifying OCSP Responder's " +
- "signature");
- }
- throw new CertPathValidatorException(
- "Error verifying OCSP Responder's signature");
+ } catch (GeneralSecurityException e) {
+ responderCert = null;
}
} else {
- // Need responder's cert in order to verify the signature
- if (DEBUG != null) {
- DEBUG.println("Unable to verify OCSP Responder's " +
- "signature");
- }
throw new CertPathValidatorException(
- "Unable to verify OCSP Responder's signature");
+ "Responder's certificate is not authorized to sign " +
+ "OCSP responses");
}
- } catch (CertPathValidatorException cpve) {
- throw cpve;
- } catch (Exception e) {
- throw new CertPathValidatorException(e);
}
+
+ // Confirm that the signed response was generated using the public
+ // key from the trusted responder cert
+ if (responderCert != null) {
+ if (!verifyResponse(responseDataDer, responderCert,
+ sigAlgId, signature)) {
+ throw new CertPathValidatorException(
+ "Error verifying OCSP Responder's signature");
+ }
+ } else {
+ // Need responder's cert in order to verify the signature
+ throw new CertPathValidatorException(
+ "Unable to verify OCSP Responder's signature");
+ }
+ }
+
+ /**
+ * Returns the OCSP ResponseStatus.
+ */
+ ResponseStatus getResponseStatus() {
+ return responseStatus;
}
/*
@@ -449,11 +446,10 @@ class OCSPResponse {
* The responder's cert is implicitly trusted.
*/
private boolean verifyResponse(byte[] responseData, X509Certificate cert,
- AlgorithmId sigAlgId, byte[] signBytes, PKIXParameters params)
- throws SignatureException {
+ AlgorithmId sigAlgId, byte[] signBytes)
+ throws CertPathValidatorException {
try {
-
Signature respSignature = Signature.getInstance(sigAlgId.getName());
respSignature.initVerify(cert);
respSignature.update(responseData);
@@ -472,92 +468,33 @@ class OCSPResponse {
return false;
}
} catch (InvalidKeyException ike) {
- throw new SignatureException(ike);
-
+ throw new CertPathValidatorException(ike);
} catch (NoSuchAlgorithmException nsae) {
- throw new SignatureException(nsae);
+ throw new CertPathValidatorException(nsae);
+ } catch (SignatureException se) {
+ throw new CertPathValidatorException(se);
}
}
- /*
- * Return the revocation status code for a given certificate.
+ /**
+ * Returns the SingleResponse of the specified CertId, or null if
+ * there is no response for that CertId.
*/
- // used by OCSPChecker
- int getCertStatus(SerialNumber sn) {
- // ignore serial number for now; if we support multiple
- // requests/responses then it will be used
- return singleResponse.getStatus();
- }
-
- // used by OCSPChecker
- CertId getCertId() {
- return singleResponse.getCertId();
- }
-
- Date getRevocationTime() {
- return singleResponse.getRevocationTime();
- }
-
- CRLReason getRevocationReason() {
- return singleResponse.getRevocationReason();
- }
-
- Map getSingleExtensions() {
- return singleResponse.getSingleExtensions();
- }
-
- /*
- * Map an OCSP response status code to a string.
- */
- static private String responseToText(int status) {
- switch (status) {
- case 0:
- return "Successful";
- case 1:
- return "Malformed request";
- case 2:
- return "Internal error";
- case 3:
- return "Try again later";
- case 4:
- return "Unused status code";
- case 5:
- return "Request must be signed";
- case 6:
- return "Request is unauthorized";
- default:
- return ("Unknown status code: " + status);
- }
- }
-
- /*
- * Map a certificate's revocation status code to a string.
- */
- // used by OCSPChecker
- static String certStatusToText(int certStatus) {
- switch (certStatus) {
- case 0:
- return "Good";
- case 1:
- return "Revoked";
- case 2:
- return "Unknown";
- default:
- return ("Unknown certificate status code: " + certStatus);
- }
+ SingleResponse getSingleResponse(CertId certId) {
+ return singleResponseMap.get(certId);
}
/*
* A class representing a single OCSP response.
*/
- private class SingleResponse {
- private CertId certId;
- private int certStatus;
- private Date thisUpdate;
- private Date nextUpdate;
- private Date revocationTime;
- private CRLReason revocationReason = CRLReason.UNSPECIFIED;
- private HashMap singleExtensions;
+ final static class SingleResponse implements OCSP.RevocationStatus {
+ private final CertId certId;
+ private final CertStatus certStatus;
+ private final Date thisUpdate;
+ private final Date nextUpdate;
+ private final Date revocationTime;
+ private final CRLReason revocationReason;
+ private final Map singleExtensions;
private SingleResponse(DerValue der) throws IOException {
if (der.tag != DerValue.tag_Sequence) {
@@ -568,35 +505,48 @@ class OCSPResponse {
certId = new CertId(tmp.getDerValue().data);
DerValue derVal = tmp.getDerValue();
short tag = (byte)(derVal.tag & 0x1f);
- if (tag == CERT_STATUS_GOOD) {
- certStatus = CERT_STATUS_GOOD;
- } else if (tag == CERT_STATUS_REVOKED) {
- certStatus = CERT_STATUS_REVOKED;
+ if (tag == CERT_STATUS_REVOKED) {
+ certStatus = CertStatus.REVOKED;
revocationTime = derVal.data.getGeneralizedTime();
if (derVal.data.available() != 0) {
- int reason = derVal.getEnumerated();
- // if reason out-of-range just leave as UNSPECIFIED
- if (reason >= 0 && reason < values.length) {
- revocationReason = values[reason];
+ DerValue dv = derVal.data.getDerValue();
+ tag = (byte)(dv.tag & 0x1f);
+ if (tag == 0) {
+ int reason = dv.data.getEnumerated();
+ // if reason out-of-range just leave as UNSPECIFIED
+ if (reason >= 0 && reason < values.length) {
+ revocationReason = values[reason];
+ } else {
+ revocationReason = CRLReason.UNSPECIFIED;
+ }
+ } else {
+ revocationReason = CRLReason.UNSPECIFIED;
}
+ } else {
+ revocationReason = CRLReason.UNSPECIFIED;
}
// RevokedInfo
if (DEBUG != null) {
DEBUG.println("Revocation time: " + revocationTime);
DEBUG.println("Revocation reason: " + revocationReason);
}
-
- } else if (tag == CERT_STATUS_UNKNOWN) {
- certStatus = CERT_STATUS_UNKNOWN;
-
} else {
- throw new IOException("Invalid certificate status");
+ revocationTime = null;
+ revocationReason = CRLReason.UNSPECIFIED;
+ if (tag == CERT_STATUS_GOOD) {
+ certStatus = CertStatus.GOOD;
+ } else if (tag == CERT_STATUS_UNKNOWN) {
+ certStatus = CertStatus.UNKNOWN;
+ } else {
+ throw new IOException("Invalid certificate status");
+ }
}
thisUpdate = tmp.getGeneralizedTime();
if (tmp.available() == 0) {
// we are done
+ nextUpdate = null;
} else {
derVal = tmp.getDerValue();
tag = (byte)(derVal.tag & 0x1f);
@@ -610,6 +560,8 @@ class OCSPResponse {
derVal = tmp.getDerValue();
tag = (byte)(derVal.tag & 0x1f);
}
+ } else {
+ nextUpdate = null;
}
}
// singleExtensions
@@ -627,7 +579,11 @@ class OCSPResponse {
DEBUG.println("OCSP single extension: " + ext);
}
}
+ } else {
+ singleExtensions = Collections.emptyMap();
}
+ } else {
+ singleExtensions = Collections.emptyMap();
}
long now = System.currentTimeMillis();
@@ -657,7 +613,7 @@ class OCSPResponse {
/*
* Return the certificate's revocation status code
*/
- private int getStatus() {
+ @Override public CertStatus getCertStatus() {
return certStatus;
}
@@ -665,28 +621,28 @@ class OCSPResponse {
return certId;
}
- private Date getRevocationTime() {
- return revocationTime;
+ @Override public Date getRevocationTime() {
+ return (Date) revocationTime.clone();
}
- private CRLReason getRevocationReason() {
+ @Override public CRLReason getRevocationReason() {
return revocationReason;
}
- private Map getSingleExtensions() {
- return singleExtensions;
+ @Override
+ public Map getSingleExtensions() {
+ return Collections.unmodifiableMap(singleExtensions);
}
/**
* Construct a string representation of a single OCSP response.
*/
- public String toString() {
+ @Override public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("SingleResponse: \n");
sb.append(certId);
- sb.append("\nCertStatus: "+ certStatusToText(getCertStatus(null)) +
- "\n");
- if (certStatus == CERT_STATUS_REVOKED) {
+ sb.append("\nCertStatus: "+ certStatus + "\n");
+ if (certStatus == CertStatus.REVOKED) {
sb.append("revocationTime is " + revocationTime + "\n");
sb.append("revocationReason is " + revocationReason + "\n");
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
index 63335d2342c..145879239ac 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@ package sun.security.provider.certpath;
import java.io.IOException;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
-import java.security.PrivilegedAction;
-import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.CertPathParameters;
import java.security.cert.CertPathValidatorException;
@@ -49,6 +47,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanSecurityPropertyAction;
import sun.security.util.Debug;
/**
@@ -67,7 +66,8 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
private List userCheckers;
private String sigProvider;
private BasicChecker basicChecker;
- private String ocspProperty;
+ private boolean ocspEnabled = false;
+ private boolean onlyEECert = false;
/**
* Default constructor.
@@ -253,13 +253,12 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
if (pkixParam.isRevocationEnabled()) {
// Examine OCSP security property
- ocspProperty = AccessController.doPrivileged(
- new PrivilegedAction() {
- public String run() {
- return
- Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP);
- }
- });
+ ocspEnabled = AccessController.doPrivileged(
+ new GetBooleanSecurityPropertyAction
+ (OCSPChecker.OCSP_ENABLE_PROP));
+ onlyEECert = AccessController.doPrivileged(
+ new GetBooleanSecurityPropertyAction
+ ("com.sun.security.onlyCheckRevocationOfEECert"));
}
}
@@ -301,15 +300,15 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
if (pkixParam.isRevocationEnabled()) {
// Use OCSP if it has been enabled
- if ("true".equalsIgnoreCase(ocspProperty)) {
+ if (ocspEnabled) {
OCSPChecker ocspChecker =
- new OCSPChecker(cpOriginal, pkixParam);
+ new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
certPathCheckers.add(ocspChecker);
}
// Always use CRLs
- CrlRevocationChecker revocationChecker =
- new CrlRevocationChecker(anchor, pkixParam, certList);
+ CrlRevocationChecker revocationChecker = new
+ CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
certPathCheckers.add(revocationChecker);
}
diff --git a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
index 0c439349d3c..6723cb8c6b8 100644
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package sun.security.provider.certpath;
import java.io.IOException;
+import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.Principal;
@@ -44,6 +45,7 @@ import java.util.LinkedList;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanSecurityPropertyAction;
import sun.security.x509.X500Name;
import sun.security.x509.PKIXExtensions;
import sun.security.util.Debug;
@@ -85,6 +87,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
private PublicKey finalPublicKey;
private X509CertSelector targetSel;
private List orderedCertStores;
+ private boolean onlyEECert = false;
/**
* Create an instance of SunCertPathBuilder.
@@ -97,6 +100,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
} catch (CertificateException e) {
throw new CertPathBuilderException(e);
}
+ onlyEECert = AccessController.doPrivileged(
+ new GetBooleanSecurityPropertyAction
+ ("com.sun.security.onlyCheckRevocationOfEECert"));
}
/**
@@ -256,7 +262,6 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/*
* Private build reverse method.
- *
*/
private void buildReverse(List> adjacencyList,
LinkedList certPathList) throws Exception
@@ -296,7 +301,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
currentState.updateState(anchor);
// init the crl checker
currentState.crlChecker =
- new CrlRevocationChecker(null, buildParams);
+ new CrlRevocationChecker(null, buildParams, null, onlyEECert);
try {
depthFirstSearchReverse(null, currentState,
new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -341,10 +346,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
adjacencyList.add(new LinkedList());
// init the crl checker
- currentState.crlChecker = new CrlRevocationChecker(null, buildParams);
+ currentState.crlChecker
+ = new CrlRevocationChecker(null, buildParams, null, onlyEECert);
depthFirstSearchForward(targetSubjectDN, currentState,
- new ForwardBuilder(buildParams, targetSubjectDN, searchAllCertStores),
+ new ForwardBuilder
+ (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
adjacencyList, certPathList);
}
@@ -486,8 +493,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
userCheckers.add(mustCheck, basicChecker);
mustCheck++;
if (buildParams.isRevocationEnabled()) {
- userCheckers.add(mustCheck,
- new CrlRevocationChecker(anchor, buildParams));
+ userCheckers.add(mustCheck, new CrlRevocationChecker
+ (anchor, buildParams, null, onlyEECert));
mustCheck++;
}
}
diff --git a/jdk/src/share/classes/sun/security/x509/AccessDescription.java b/jdk/src/share/classes/sun/security/x509/AccessDescription.java
index 1544ea953be..0911018110f 100644
--- a/jdk/src/share/classes/sun/security/x509/AccessDescription.java
+++ b/jdk/src/share/classes/sun/security/x509/AccessDescription.java
@@ -113,7 +113,7 @@ public final class AccessDescription {
} else {
method = accessMethod.toString();
}
- return ("accessMethod: " + method +
+ return ("\n accessMethod: " + method +
"\n accessLocation: " + accessLocation.toString() + "\n");
}
}
diff --git a/jdk/src/share/demo/jvmti/waiters/Agent.cpp b/jdk/src/share/demo/jvmti/waiters/Agent.cpp
index 30786133d50..f4da70281fd 100644
--- a/jdk/src/share/demo/jvmti/waiters/Agent.cpp
+++ b/jdk/src/share/demo/jvmti/waiters/Agent.cpp
@@ -72,36 +72,30 @@ Agent::get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object)
{
jvmtiError err;
Monitor *m;
+ jlong tag;
- /* We use tags to track these, the tag is the Monitor pointer */
- err = jvmti->RawMonitorEnter(lock); {
- check_jvmti_error(jvmti, err, "raw monitor enter");
-
- /* The raw monitor enter/exit protects us from creating two
- * instances for the same object.
- */
- jlong tag;
-
- m = NULL;
- tag = (jlong)0;
- err = jvmti->GetTag(object, &tag);
- check_jvmti_error(jvmti, err, "get tag");
- /*LINTED*/
- m = (Monitor *)(void *)(ptrdiff_t)tag;
- if ( m == NULL ) {
- m = new Monitor(jvmti, env, object);
- /*LINTED*/
- tag = (jlong)(ptrdiff_t)(void *)m;
- err = jvmti->SetTag(object, tag);
- check_jvmti_error(jvmti, err, "set tag");
- /* Save monitor on list */
+ m = NULL;
+ tag = (jlong)0;
+ err = jvmti->GetTag(object, &tag);
+ check_jvmti_error(jvmti, err, "get tag");
+ /*LINTED*/
+ m = (Monitor *)(void *)(ptrdiff_t)tag;
+ if ( m == NULL ) {
+ m = new Monitor(jvmti, env, object);
+ /* Save monitor on list */
+ if (monitor_count == monitor_list_size) {
+ monitor_list_size += monitor_list_grow_size;
monitor_list = (Monitor**)realloc((void*)monitor_list,
- (monitor_count+1)*(int)sizeof(Monitor*));
- monitor_list[monitor_count++] = m;
+ (monitor_list_size)*(int)sizeof(Monitor*));
}
- } err = jvmti->RawMonitorExit(lock);
- check_jvmti_error(jvmti, err, "raw monitor exit");
-
+ monitor_list[monitor_count] = m;
+ m->set_slot(monitor_count);
+ monitor_count++;
+ /*LINTED*/
+ tag = (jlong)(ptrdiff_t)(void *)m;
+ err = jvmti->SetTag(object, tag);
+ check_jvmti_error(jvmti, err, "set tag");
+ }
return m;
}
@@ -112,12 +106,11 @@ Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
stdout_message("Agent created..\n");
stdout_message("VMInit...\n");
- /* Create a Monitor lock to use */
- err = jvmti->CreateRawMonitor("waiters Agent lock", &lock);
- check_jvmti_error(jvmti, err, "create raw monitor");
/* Start monitor list */
monitor_count = 0;
- monitor_list = (Monitor**)malloc((int)sizeof(Monitor*));
+ monitor_list_size = initial_monitor_list_size;
+ monitor_list = (Monitor**)
+ malloc(monitor_list_size*(int)sizeof(Monitor*));
}
Agent::~Agent()
@@ -134,9 +127,6 @@ void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env)
delete monitor_list[i];
}
free(monitor_list);
- /* Destroy the Monitor lock to use */
- err = jvmti->DestroyRawMonitor(lock);
- check_jvmti_error(jvmti, err, "destroy raw monitor");
/* Print death message */
stdout_message("VMDeath...\n");
}
@@ -215,8 +205,16 @@ void Agent::object_free(jvmtiEnv* jvmti, jlong tag)
/* We just cast the tag to a C++ pointer and delete it.
* we know it can only be a Monitor *.
*/
- Monitor *m;
+ Monitor *m;
/*LINTED*/
m = (Monitor *)(ptrdiff_t)tag;
+ if (monitor_count > 1) {
+ /* Move the last element to this Monitor's slot */
+ int slot = m->get_slot();
+ Monitor *last = monitor_list[monitor_count-1];
+ monitor_list[slot] = last;
+ last->set_slot(slot);
+ }
+ monitor_count--;
delete m;
}
diff --git a/jdk/src/share/demo/jvmti/waiters/Agent.hpp b/jdk/src/share/demo/jvmti/waiters/Agent.hpp
index 9885baf8ba3..65fe1227362 100644
--- a/jdk/src/share/demo/jvmti/waiters/Agent.hpp
+++ b/jdk/src/share/demo/jvmti/waiters/Agent.hpp
@@ -34,8 +34,12 @@
class Agent {
private:
- jrawMonitorID lock;
+ enum {
+ initial_monitor_list_size = 64,
+ monitor_list_grow_size = 16
+ };
Monitor **monitor_list;
+ unsigned monitor_list_size;
unsigned monitor_count;
Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
diff --git a/jdk/src/share/demo/jvmti/waiters/Monitor.cpp b/jdk/src/share/demo/jvmti/waiters/Monitor.cpp
index a5efc5b23b3..acd092a142a 100644
--- a/jdk/src/share/demo/jvmti/waiters/Monitor.cpp
+++ b/jdk/src/share/demo/jvmti/waiters/Monitor.cpp
@@ -73,6 +73,16 @@ Monitor::~Monitor()
name, contends, waits, timeouts);
}
+int Monitor::get_slot()
+{
+ return slot;
+}
+
+void Monitor::set_slot(int aslot)
+{
+ slot = aslot;
+}
+
void Monitor::contended()
{
contends++;
diff --git a/jdk/src/share/demo/jvmti/waiters/Monitor.hpp b/jdk/src/share/demo/jvmti/waiters/Monitor.hpp
index 95b49560abd..af6dedda5b9 100644
--- a/jdk/src/share/demo/jvmti/waiters/Monitor.hpp
+++ b/jdk/src/share/demo/jvmti/waiters/Monitor.hpp
@@ -35,6 +35,7 @@ class Monitor {
private:
char name[64];
+ int slot;
unsigned contends;
unsigned waits;
unsigned timeouts;
@@ -42,6 +43,8 @@ class Monitor {
public:
Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
~Monitor();
+ int get_slot();
+ void set_slot(int i);
void contended();
void waited();
void timeout();
diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h
index df8f27e6602..4f141d21fb8 100644
--- a/jdk/src/share/javavm/export/jvm.h
+++ b/jdk/src/share/javavm/export/jvm.h
@@ -374,6 +374,12 @@ JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
JNIEXPORT void JNICALL
JVM_ResolveClass(JNIEnv *env, jclass cls);
+/*
+ * Find a class from a boot class loader. Returns NULL if class not found.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
+
/*
* Find a class from a given class loader. Throw ClassNotFoundException
* or NoClassDefFoundError depending on the value of the last
diff --git a/jdk/src/share/lib/net.properties b/jdk/src/share/lib/net.properties
index e941d50e3f4..da78a84d511 100644
--- a/jdk/src/share/lib/net.properties
+++ b/jdk/src/share/lib/net.properties
@@ -32,7 +32,7 @@ java.net.useSystemProxies=false
#
# http.proxyHost=
# http.proxyPort=80
-# http.nonProxyHosts=localhost|127.0.0.1
+http.nonProxyHosts=localhost|127.*|[::1]
#
# HTTPS Proxy Settings. proxyHost is the name of the proxy server
# (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
@@ -49,7 +49,7 @@ java.net.useSystemProxies=false
#
# ftp.proxyHost=
# ftp.proxyPort=80
-# ftp.nonProxyHosts=localhost|127.0.0.1
+ftp.nonProxyHosts=localhost|127.*|[::1]
#
# Gopher Proxy settings. proxyHost is the name of the proxy server
# (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
diff --git a/jdk/src/share/native/java/lang/ClassLoader.c b/jdk/src/share/native/java/lang/ClassLoader.c
index bedf87ce7e6..b080fef2e53 100644
--- a/jdk/src/share/native/java/lang/ClassLoader.c
+++ b/jdk/src/share/native/java/lang/ClassLoader.c
@@ -237,6 +237,9 @@ Java_java_lang_ClassLoader_resolveClass0(JNIEnv *env, jobject this,
JVM_ResolveClass(env, cls);
}
+/*
+ * Returns NULL if class not found.
+ */
JNIEXPORT jclass JNICALL
Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
jstring classname)
@@ -246,7 +249,6 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
char buf[128];
if (classname == NULL) {
- JNU_ThrowClassNotFoundException(env, 0);
return 0;
}
@@ -258,11 +260,10 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
VerifyFixClassname(clname);
if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
- JNU_ThrowClassNotFoundException(env, clname);
goto done;
}
- cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE);
+ cls = JVM_FindClassFromBootLoader(env, clname);
done:
if (clname != buf) {
diff --git a/jdk/src/solaris/bin/java_md.c b/jdk/src/solaris/bin/java_md.c
index 2e574ec2cec..73efc1090fd 100644
--- a/jdk/src/solaris/bin/java_md.c
+++ b/jdk/src/solaris/bin/java_md.c
@@ -1324,12 +1324,12 @@ FindBootStrapClass(JNIEnv *env, const char* classname)
{
if (findBootClass == NULL) {
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
- "JVM_FindClassFromClassLoader");
+ "JVM_FindClassFromBootLoader");
if (findBootClass == NULL) {
JLI_ReportErrorMessage(DLL_ERROR4,
- "JVM_FindClassFromClassLoader");
+ "JVM_FindClassFromBootLoader");
return NULL;
}
}
- return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE);
+ return findBootClass(env, classname);
}
diff --git a/jdk/src/windows/bin/java_md.c b/jdk/src/windows/bin/java_md.c
index df5e6988c5e..a4fa4ccd63a 100644
--- a/jdk/src/windows/bin/java_md.c
+++ b/jdk/src/windows/bin/java_md.c
@@ -1093,12 +1093,6 @@ void SetJavaLauncherPlatformProps() {}
*/
static FindClassFromBootLoader_t *findBootClass = NULL;
-#ifdef _M_AMD64
-#define JVM_BCLOADER "JVM_FindClassFromClassLoader"
-#else
-#define JVM_BCLOADER "_JVM_FindClassFromClassLoader@20"
-#endif /* _M_AMD64 */
-
jclass FindBootStrapClass(JNIEnv *env, const char *classname)
{
HMODULE hJvm;
@@ -1108,13 +1102,13 @@ jclass FindBootStrapClass(JNIEnv *env, const char *classname)
if (hJvm == NULL) return NULL;
/* need to use the demangled entry point */
findBootClass = (FindClassFromBootLoader_t *)GetProcAddress(hJvm,
- JVM_BCLOADER);
+ "JVM_FindClassFromBootLoader");
if (findBootClass == NULL) {
- JLI_ReportErrorMessage(DLL_ERROR4, JVM_BCLOADER);
+ JLI_ReportErrorMessage(DLL_ERROR4, "JVM_FindClassFromBootLoader");
return NULL;
}
}
- return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE);
+ return findBootClass(env, classname);
}
void
diff --git a/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java b/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java
index a4334b42f12..788a4d0ff21 100644
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java
@@ -67,6 +67,9 @@ public class D3DGraphicsDevice extends Win32GraphicsDevice {
if (d3dAvailable) {
// we don't use pixel formats for the d3d pipeline
pfDisabled = true;
+ sun.misc.PerfCounter.getD3DAvailable().set(1);
+ } else {
+ sun.misc.PerfCounter.getD3DAvailable().set(0);
}
}
diff --git a/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh
new file mode 100644
index 00000000000..74106760c79
--- /dev/null
+++ b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 6862295
+# @summary Verify breakpoints still work after a full GC.
+# @author dcubed (based on the test program posted to the following
+# Eclipse thread https://bugs.eclipse.org/bugs/show_bug.cgi?id=279137)
+#
+# @run shell BreakpointWithFullGC.sh
+
+compileOptions=-g
+# Hijacking the mode parameter to make sure we use a small amount
+# of memory and can see what GC is doing.
+mode="-Xmx32m -verbose:gc"
+# Force use of a GC framework collector to see the original failure.
+#mode="$mode -XX:+UseSerialGC"
+
+# Uncomment this to see the JDI trace
+#jdbOptions=-dbgtrace
+
+createJavaFile()
+{
+ cat < $1.java.1
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class $1 {
+ public static List